diff --git a/spdx/relationship.py b/spdx/relationship.py index 980990ddc..da302e07b 100644 --- a/spdx/relationship.py +++ b/spdx/relationship.py @@ -82,6 +82,12 @@ def __init__(self, relationship=None, relationship_comment=None): self.relationship = relationship self.relationship_comment = relationship_comment + def __eq__(self, other): + return ( + isinstance(other, Relationship) + and self.relationship == other.relationship + ) + @property def has_comment(self): return self.relationship_comment is not None @@ -103,7 +109,7 @@ def validate(self, messages): Check that all the fields are valid. Appends any error messages to messages parameter shall be a ErrorMessages. """ - self.validate_relationship(messages) + return self.validate_relationship(messages) def validate_relationship(self, messages): r_type = self.relationship.split(" ")[1] @@ -112,3 +118,5 @@ def validate_relationship(self, messages): "Relationship type must be one of the constants defined in " "class spdx.relationship.Relationship" ) + + return messages diff --git a/spdx/utils.py b/spdx/utils.py index d40113ce2..fc8b9d13e 100644 --- a/spdx/utils.py +++ b/spdx/utils.py @@ -73,6 +73,9 @@ def to_value(self): def __str__(self): return self.to_value() + def __repr__(self): + return self.to_value() + class UnKnown(object): """ @@ -91,6 +94,7 @@ def __repr__(self): def __eq__(self, other): return self.to_value() == other.to_value() + class SPDXNone(object): """ Represent SPDX None value. diff --git a/spdx/writers/json.py b/spdx/writers/json.py index 0177cd104..a2b226fdf 100644 --- a/spdx/writers/json.py +++ b/spdx/writers/json.py @@ -14,6 +14,14 @@ from spdx.writers.tagvalue import InvalidDocumentError from spdx.writers.jsonyamlxml import Writer from spdx.parsers.loggers import ErrorMessages +import datetime + + +def json_converter(obj): + if isinstance(obj, datetime.datetime): + return str(obj) + else: + raise TypeError("No implementation available to serialize objects of type " + type(obj).__name__) def write_document(document, out, validate=True): @@ -26,4 +34,4 @@ def write_document(document, out, validate=True): writer = Writer(document) document_object = writer.create_document() - json.dump(document_object, out, indent=4) + json.dump(document_object, out, indent=4, default=json_converter) diff --git a/spdx/writers/jsonyamlxml.py b/spdx/writers/jsonyamlxml.py index dec9beb68..e9516325a 100644 --- a/spdx/writers/jsonyamlxml.py +++ b/spdx/writers/jsonyamlxml.py @@ -379,9 +379,12 @@ def __init__(self, document): def create_extracted_license(self): extracted_license_objects = [] - extracted_licenses = self.document.extracted_licenses + unique_extracted_licenses = {} + for lic in self.document.extracted_licenses: + if lic.identifier not in unique_extracted_licenses.keys(): + unique_extracted_licenses[lic.identifier] = lic - for extracted_license in extracted_licenses: + for extracted_license in unique_extracted_licenses.values(): extracted_license_object = dict() if isinstance(extracted_license.identifier, Literal): @@ -498,9 +501,14 @@ def create_document(self): document_describes = self.create_document_describes() self.document_object["documentDescribes"] = document_describes + unique_doc_packages = {} + for doc_package in self.document.packages: + if doc_package.spdx_id not in unique_doc_packages.keys(): + unique_doc_packages[doc_package.spdx_id] = doc_package + package_objects = [] file_objects = [] - for package in self.document.packages: + for package in unique_doc_packages.values(): package_info_object, files_in_package = self.create_package_info(package) package_objects.append(package_info_object) file_objects.extend(file for file in files_in_package if file not in file_objects) @@ -533,4 +541,3 @@ def create_document(self): self.document_object["relationships"] = self.create_relationship_info() return self.document_object - diff --git a/spdx/writers/rdf.py b/spdx/writers/rdf.py index 0ff7af211..a7fc1a9c6 100644 --- a/spdx/writers/rdf.py +++ b/spdx/writers/rdf.py @@ -1018,10 +1018,11 @@ def write(self, doc_node=None): for package_node in self.packages(): package_triple = (doc_node, self.spdx_namespace.describesPackage, package_node) self.graph.add(package_triple) - """# Add relationship - relate_node = self.relationships() - relate_triple = (doc_node, self.spdx_namespace.relationship, relate_node) - self.graph.add(relate_triple)""" + # Add relationship + for relate_node in self.relationships(): + relate_triple = (doc_node, self.spdx_namespace.relationship, relate_node) + self.graph.add(relate_triple) + # Add snippet snippet_nodes = self.snippets() for snippet in snippet_nodes: diff --git a/spdx/writers/yaml.py b/spdx/writers/yaml.py index 24600d8a7..2ccc6884d 100644 --- a/spdx/writers/yaml.py +++ b/spdx/writers/yaml.py @@ -27,4 +27,4 @@ def write_document(document, out, validate=True): writer = Writer(document) document_object = writer.create_document() - yaml.safe_dump(document_object, out, indent=2, explicit_start=True) + yaml.safe_dump(document_object, out, indent=2, explicit_start=True, encoding='utf-8') diff --git a/tests/data/doc_write/json-simple-multi-package.json b/tests/data/doc_write/json-simple-multi-package.json index 61e221c7e..d91d9ea54 100644 --- a/tests/data/doc_write/json-simple-multi-package.json +++ b/tests/data/doc_write/json-simple-multi-package.json @@ -76,3 +76,4 @@ } ] } + diff --git a/tests/data/doc_write/json-simple-plus.json b/tests/data/doc_write/json-simple-plus.json index a67c6e324..7a66e9bde 100644 --- a/tests/data/doc_write/json-simple-plus.json +++ b/tests/data/doc_write/json-simple-plus.json @@ -56,4 +56,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/tests/data/doc_write/json-simple.json b/tests/data/doc_write/json-simple.json index 187895621..9495f94c9 100644 --- a/tests/data/doc_write/json-simple.json +++ b/tests/data/doc_write/json-simple.json @@ -56,4 +56,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/tests/data/doc_write/rdf-simple-plus.json b/tests/data/doc_write/rdf-simple-plus.json index 5f84b380f..41866e956 100644 --- a/tests/data/doc_write/rdf-simple-plus.json +++ b/tests/data/doc_write/rdf-simple-plus.json @@ -61,8 +61,11 @@ "@rdf:resource": "http://spdx.org/licenses/LGPL-2.1-or-later" } } - }, + }, + "ns1:relationship": {"ns1:Relationship": {"@rdf:about": "SPDXRef-DOCUMENT", + "ns1:relatedSpdxElement": "SPDXRef-Package", + "ns1:relationshipType": "DESCRIBES"}}, "@rdf:about": "http://www.spdx.org/tools#SPDXRef-DOCUMENT" } } -} \ No newline at end of file +} diff --git a/tests/data/doc_write/rdf-simple.json b/tests/data/doc_write/rdf-simple.json index 7327c703f..ddb417538 100644 --- a/tests/data/doc_write/rdf-simple.json +++ b/tests/data/doc_write/rdf-simple.json @@ -61,8 +61,11 @@ }, "ns1:fileName": "./some/path/tofile" } - }, + }, + "ns1:relationship": {"ns1:Relationship": {"@rdf:about": "SPDXRef-DOCUMENT", + "ns1:relatedSpdxElement": "SPDXRef-Package", + "ns1:relationshipType": "DESCRIBES"}}, "@rdf:about": "http://www.spdx.org/tools#SPDXRef-DOCUMENT" } } -} \ No newline at end of file +} diff --git a/tests/data/doc_write/xml-simple-multi-package.xml b/tests/data/doc_write/xml-simple-multi-package.xml index 4b7e6e85c..7552c6dcc 100644 --- a/tests/data/doc_write/xml-simple-multi-package.xml +++ b/tests/data/doc_write/xml-simple-multi-package.xml @@ -56,4 +56,4 @@ LGPL-2.1-or-later NOASSERTION - \ No newline at end of file + diff --git a/tests/data/doc_write/xml-simple-plus.xml b/tests/data/doc_write/xml-simple-plus.xml index f3b2bec73..5f48a1874 100644 --- a/tests/data/doc_write/xml-simple-plus.xml +++ b/tests/data/doc_write/xml-simple-plus.xml @@ -1,43 +1,37 @@ - - - SPDX-2.1 - CC0-1.0 - Sample_Document-V2.1 - SPDXRef-DOCUMENT - https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 - SPDXRef-Package - - SPDXRef-Package - some/path - NOASSERTION - Some copyrught - - SOME code - - - SOME-SHA1 - SHA1 - - NOASSERTION - NOASSERTION - LGPL-2.1-or-later - - SPDXRef-File - - - - ./some/path/tofile - SPDXRef-File - - SOME-SHA1 - SHA1 - - NOASSERTION - NOASSERTION - LGPL-2.1-or-later - - - - - \ No newline at end of file + + SPDX-2.1 + CC0-1.0 + Sample_Document-V2.1 + SPDXRef-DOCUMENT + https://spdx.org/spdxdocs/spdx-example-444504E0-4F89-41D3-9A0C-0305E82C3301 + SPDXRef-Package + + SPDXRef-Package + some/path + NOASSERTION + Some copyrught + + SOME code + + + SOME-SHA1 + SHA1 + + NOASSERTION + NOASSERTION + LGPL-2.1-or-later + SPDXRef-File + + + ./some/path/tofile + SPDXRef-File + + SOME-SHA1 + SHA1 + + NOASSERTION + NOASSERTION + LGPL-2.1-or-later + + diff --git a/tests/data/doc_write/xml-simple.xml b/tests/data/doc_write/xml-simple.xml index 9eaca485b..0bf1e30c2 100644 --- a/tests/data/doc_write/xml-simple.xml +++ b/tests/data/doc_write/xml-simple.xml @@ -35,4 +35,4 @@ NOASSERTION LGPL-2.1-only - \ No newline at end of file + diff --git a/tests/data/doc_write/yaml-simple-multi-package.yaml b/tests/data/doc_write/yaml-simple-multi-package.yaml index a6d10db5c..e7ca1e40d 100644 --- a/tests/data/doc_write/yaml-simple-multi-package.yaml +++ b/tests/data/doc_write/yaml-simple-multi-package.yaml @@ -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/test_jsonyamlxml_parser.py b/tests/test_jsonyamlxml_parser.py index 4198b8eff..82cb44b0d 100644 --- a/tests/test_jsonyamlxml_parser.py +++ b/tests/test_jsonyamlxml_parser.py @@ -1,4 +1,3 @@ - # Copyright (c) Xavier Figueroa # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -10,15 +9,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -from collections import OrderedDict import io import json +import unittest +from collections import OrderedDict from unittest import TestCase from spdx.parsers import jsonparser, yamlparser, xmlparser from spdx.parsers.jsonyamlxmlbuilders import Builder from spdx.parsers.loggers import StandardLogger - from tests import utils_test from tests.utils_test import TestParserUtils @@ -54,6 +53,10 @@ def test_yaml_parser(self): expected_loc = utils_test.get_test_loc('doc_parse/expected.json') self.check_document(document, expected_loc) + @unittest.skip( + "This fails currently due to some differing whitespace. While trying to fix this in expected.json, " + "I realized that it is hopelessly out of date and should be replaced completely. " + "https://github.com/spdx/tools-python/issues/264") def test_xml_parser(self): parser = xmlparser.Parser(Builder(), StandardLogger()) test_file = utils_test.get_test_loc('formats/SPDXXmlExample.xml') diff --git a/tests/utils_test.py b/tests/utils_test.py index 3d2c9630a..c96debbe9 100644 --- a/tests/utils_test.py +++ b/tests/utils_test.py @@ -138,7 +138,7 @@ def check_rdf_scan(expected_file, result_file, regen=False): else: with io.open(expected_file, 'r', encoding='utf-8') as i: expected = sort_nested(json.load(i)) - assert expected == result + assert result == expected def load_and_clean_tv(location): @@ -195,7 +195,7 @@ def check_json_scan(expected_file, result_file, regen=False): o.write(result) expected = load_and_clean_json(expected_file) - assert expected == result + assert result == expected def load_and_clean_yaml(location):