Repository: spdx/tools-python

Issue:
Make usage of `license_concluded` consistent
Currently, the data model uses `license_concluded` for packages and `concluded_license` for files and snippets.
The serialized name in json and tag-value is "licenseConcluded", so this should probably be the reference.

Discussion:

Patch:
diff --git a/src/spdx/jsonschema/file_converter.py b/src/spdx/jsonschema/file_converter.py
index 78af0b9..5806ee6 100644
--- a/src/spdx/jsonschema/file_converter.py
+++ b/src/spdx/jsonschema/file_converter.py
@@ -62,7 +62,7 @@ class FileConverter(TypedConverter[File]):
         elif file_property == FileProperty.LICENSE_COMMENTS:
             return file.license_comment
         elif file_property == FileProperty.LICENSE_CONCLUDED:
-            return apply_if_present(str, file.concluded_license)
+            return apply_if_present(str, file.license_concluded)
         elif file_property == FileProperty.LICENSE_INFO_IN_FILES:
             if isinstance(file.license_info_in_file, list):
                 return [str(license_expression) for license_expression in file.license_info_in_file] or None
diff --git a/src/spdx/jsonschema/snippet_converter.py b/src/spdx/jsonschema/snippet_converter.py
index 0d3013e..90dc988 100644
--- a/src/spdx/jsonschema/snippet_converter.py
+++ b/src/spdx/jsonschema/snippet_converter.py
@@ -46,7 +46,7 @@ class SnippetConverter(TypedConverter[Snippet]):
         elif snippet_property == SnippetProperty.LICENSE_COMMENTS:
             return snippet.license_comment
         elif snippet_property == SnippetProperty.LICENSE_CONCLUDED:
-            return apply_if_present(str, snippet.concluded_license)
+            return apply_if_present(str, snippet.license_concluded)
         elif snippet_property == SnippetProperty.LICENSE_INFO_IN_SNIPPETS:
             if isinstance(snippet.license_info_in_snippet, list):
                 return [str(license_expression) for license_expression in snippet.license_info_in_snippet] or None
diff --git a/src/spdx/model/file.py b/src/spdx/model/file.py
index fa23f54..7783775 100644
--- a/src/spdx/model/file.py
+++ b/src/spdx/model/file.py
@@ -40,7 +40,7 @@ class File:
     spdx_id: str
     checksums: List[Checksum]
     file_type: List[FileType] = field(default_factory=list)
-    concluded_license: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None
+    license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None
     license_info_in_file: Optional[Union[List[LicenseExpression], SpdxNoAssertion, SpdxNone]] = field(
         default_factory=list)
     license_comment: Optional[str] = None
@@ -56,7 +56,7 @@ class File:
     #   between the file and this package
 
     def __init__(self, name: str, spdx_id: str, checksums: List[Checksum], file_type: List[FileType] = None,
-                 concluded_license: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None,
+                 license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None,
                  license_info_in_file: Optional[Union[List[LicenseExpression], SpdxNoAssertion, SpdxNone]] = None,
                  license_comment: Optional[str] = None,
                  copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None,
diff --git a/src/spdx/model/snippet.py b/src/spdx/model/snippet.py
index 5fba0c6..1d5fa6b 100644
--- a/src/spdx/model/snippet.py
+++ b/src/spdx/model/snippet.py
@@ -24,7 +24,7 @@ class Snippet:
     file_spdx_id: str
     byte_range: Tuple[int, int]
     line_range: Optional[Tuple[int, int]] = None
-    concluded_license: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None
+    license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None
     license_info_in_snippet: Optional[Union[List[LicenseExpression], SpdxNoAssertion, SpdxNone]] = None
     license_comment: Optional[str] = None
     copyright_text: Optional[Union[str, SpdxNoAssertion, SpdxNone]] = None
@@ -34,7 +34,7 @@ class Snippet:
 
     def __init__(self, spdx_id: str, file_spdx_id: str, byte_range: Tuple[int, int],
                  line_range: Optional[Tuple[int, int]] = None,
-                 concluded_license: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None,
+                 license_concluded: Optional[Union[LicenseExpression, SpdxNoAssertion, SpdxNone]] = None,
                  license_info_in_snippet: Optional[Union[List[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):
diff --git a/src/spdx/parser/jsonlikedict/file_parser.py b/src/spdx/parser/jsonlikedict/file_parser.py
index 44a62b5..57954c0 100644
--- a/src/spdx/parser/jsonlikedict/file_parser.py
+++ b/src/spdx/parser/jsonlikedict/file_parser.py
@@ -64,7 +64,7 @@ class FileParser:
                                                            copyright_text=copyright_text, file_type=file_types,
                                                            contributors=file_contributors,
                                                            license_comment=license_comments,
-                                                           concluded_license=license_concluded,
+                                                           license_concluded=license_concluded,
                                                            license_info_in_file=license_info_in_files,
                                                            notice=notice_text)
                                                 )
diff --git a/src/spdx/parser/jsonlikedict/snippet_parser.py b/src/spdx/parser/jsonlikedict/snippet_parser.py
index f0a8fef..9dbb733 100644
--- a/src/spdx/parser/jsonlikedict/snippet_parser.py
+++ b/src/spdx/parser/jsonlikedict/snippet_parser.py
@@ -52,7 +52,7 @@ class SnippetParser:
         comment: Optional[str] = snippet_dict.get("comment")
         copyright_text: Optional[str] = snippet_dict.get("copyrightText")
         license_comment: Optional[str] = snippet_dict.get("licenseComments")
-        concluded_license: Optional[Union[
+        license_concluded: Optional[Union[
             LicenseExpression, SpdxNoAssertion, SpdxNone]] = parse_field_or_log_error(logger, snippet_dict.get(
             "licenseConcluded"), lambda x: parse_field_or_no_assertion_or_none(x,
                                                                                self.license_expression_parser.parse_license_expression))
@@ -69,7 +69,7 @@ class SnippetParser:
                                                         file_spdx_id=file_spdx_id, line_range=line_range,
                                                         attribution_texts=attribution_texts, comment=comment,
                                                         copyright_text=copyright_text, license_comment=license_comment,
-                                                        concluded_license=concluded_license,
+                                                        license_concluded=license_concluded,
                                                         license_info_in_snippet=license_info))
 
         return snippet
diff --git a/src/spdx/validation/file_validator.py b/src/spdx/validation/file_validator.py
index 33cc732..cc4375e 100644
--- a/src/spdx/validation/file_validator.py
+++ b/src/spdx/validation/file_validator.py
@@ -65,7 +65,7 @@ def validate_file(file: File, context: Optional[ValidationContext] = None) -> Li
 
     validation_messages.extend(validate_checksums(file.checksums, file.spdx_id))
 
-    validation_messages.extend(validate_license_expression(file.concluded_license))
+    validation_messages.extend(validate_license_expression(file.license_concluded))
 
     validation_messages.extend(validate_license_expressions(file.license_info_in_file))
 
diff --git a/src/spdx/validation/snippet_validator.py b/src/spdx/validation/snippet_validator.py
index 3140a85..4d350f3 100644
--- a/src/spdx/validation/snippet_validator.py
+++ b/src/spdx/validation/snippet_validator.py
@@ -83,7 +83,7 @@ def validate_snippet(snippet: Snippet, context: Optional[ValidationContext] = No
                     context)
             )
 
-    validation_messages.extend(validate_license_expression(snippet.concluded_license))
+    validation_messages.extend(validate_license_expression(snippet.license_concluded))
 
     validation_messages.extend(validate_license_expressions(snippet.license_info_in_snippet))
 
diff --git a/src/spdx/writer/tagvalue/file_writer.py b/src/spdx/writer/tagvalue/file_writer.py
index e281d4f..ce1ec0a 100644
--- a/src/spdx/writer/tagvalue/file_writer.py
+++ b/src/spdx/writer/tagvalue/file_writer.py
@@ -28,7 +28,7 @@ def write_file(file: File, text_output: TextIO):
     for file_checksum in file.checksums:
         write_value("FileChecksum", write_checksum_to_tag_value(file_checksum), text_output)
 
-    write_license_expression("LicenseConcluded", file.concluded_license, text_output)
+    write_license_expression("LicenseConcluded", file.license_concluded, text_output)
     write_license_expression("LicenseInfoInFile", file.license_info_in_file, text_output)
     write_text_value("LicenseComments", file.license_comment, text_output)
     write_text_value("FileCopyrightText", file.copyright_text, text_output)
diff --git a/src/spdx/writer/tagvalue/snippet_writer.py b/src/spdx/writer/tagvalue/snippet_writer.py
index 7f5d8d6..dc8553e 100644
--- a/src/spdx/writer/tagvalue/snippet_writer.py
+++ b/src/spdx/writer/tagvalue/snippet_writer.py
@@ -23,7 +23,7 @@ def write_snippet(snippet: Snippet, output_text: TextIO):
     write_range("SnippetByteRange", snippet.byte_range, output_text)
     write_range("SnippetLineRange", snippet.line_range, output_text)
 
-    write_license_expression("SnippetLicenseConcluded", snippet.concluded_license, output_text)
+    write_license_expression("SnippetLicenseConcluded", snippet.license_concluded, output_text)
     write_license_expression("LicenseInfoInSnippet", snippet.license_info_in_snippet, output_text)
     write_text_value("SnippetLicenseComments", snippet.license_comment, output_text)
     write_text_value("SnippetCopyrightText", snippet.copyright_text, output_text)


Test patch:
diff --git a/tests/fixtures.py b/tests/fixtures.py
index 8bcb0f3..389fa56 100644
--- a/tests/fixtures.py
+++ b/tests/fixtures.py
@@ -53,7 +53,7 @@ def creation_info_fixture(spdx_version="SPDX-2.3", spdx_id="SPDXRef-DOCUMENT", n
 
 
 def file_fixture(name="./fileName.py", spdx_id="SPDXRef-File", checksums=None, file_type=None,
-                 concluded_license=LicenseExpression("concludedLicenseExpression"), license_info_in_file=None,
+                 license_concluded=LicenseExpression("licenseConcludedExpression"), 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
@@ -63,7 +63,7 @@ def file_fixture(name="./fileName.py", spdx_id="SPDXRef-File", checksums=None, f
     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_type=file_type,
-                concluded_license=concluded_license, license_info_in_file=license_info_in_file,
+                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)
 
@@ -108,7 +108,7 @@ def external_package_ref_fixture(category=ExternalPackageRefCategory.PACKAGE_MAN
 
 
 def snippet_fixture(spdx_id="SPDXRef-Snippet", file_spdx_id="SPDXRef-File", byte_range=(1, 2),
-                    line_range=(3, 4), concluded_license=LicenseExpression("snippetLicenseConcluded"),
+                    line_range=(3, 4), license_concluded=LicenseExpression("snippetLicenseConcluded"),
                     license_info_in_snippet=None, license_comment="snippetLicenseComment",
                     copyright_text="licenseCopyrightText", comment="snippetComment", name="snippetName",
                     attribution_texts=None) -> Snippet:
@@ -116,7 +116,7 @@ def snippet_fixture(spdx_id="SPDXRef-Snippet", file_spdx_id="SPDXRef-File", byte
         LicenseExpression("licenseInfoInSnippet")] 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,
-                   concluded_license=concluded_license, license_info_in_snippet=license_info_in_snippet,
+                   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)
 
diff --git a/tests/jsonschema/test_file_converter.py b/tests/jsonschema/test_file_converter.py
index 452d08c..f0e968a 100644
--- a/tests/jsonschema/test_file_converter.py
+++ b/tests/jsonschema/test_file_converter.py
@@ -73,7 +73,7 @@ def test_successful_conversion(converter: FileConverter):
     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_type=[FileType.SPDX, FileType.OTHER], concluded_license=LicenseExpression("licenseExpression1"),
+                file_type=[FileType.SPDX, FileType.OTHER], license_concluded=LicenseExpression("licenseExpression1"),
                 license_info_in_file=[LicenseExpression("licenseExpression2"), LicenseExpression("licenseExpression3")],
                 license_comment="licenseComment", copyright_text="copyrightText", comment="comment", notice="notice",
                 contributors=["contributor1", "contributor2"],
@@ -103,7 +103,7 @@ def test_successful_conversion(converter: FileConverter):
 
 
 def test_null_values(converter: FileConverter):
-    file = file_fixture(copyright_text=None, concluded_license=None, license_comment=None, comment=None, notice=None,
+    file = file_fixture(copyright_text=None, license_concluded=None, license_comment=None, comment=None, notice=None,
                         attribution_texts=[], checksums=[], contributors=[], file_type=[], license_info_in_file=[])
     document = Document(creation_info_fixture(), files=[file])
 
@@ -123,7 +123,7 @@ def test_null_values(converter: FileConverter):
 
 
 def test_spdx_no_assertion(converter: FileConverter):
-    file = file_fixture(concluded_license=SpdxNoAssertion(), license_info_in_file=SpdxNoAssertion(),
+    file = file_fixture(license_concluded=SpdxNoAssertion(), license_info_in_file=SpdxNoAssertion(),
                         copyright_text=SpdxNoAssertion())
     document = Document(creation_info_fixture(), files=[file])
 
@@ -136,7 +136,7 @@ def test_spdx_no_assertion(converter: FileConverter):
 
 
 def test_spdx_none(converter: FileConverter):
-    file = file_fixture(concluded_license=SpdxNone(), license_info_in_file=SpdxNone(), copyright_text=SpdxNone())
+    file = file_fixture(license_concluded=SpdxNone(), license_info_in_file=SpdxNone(), copyright_text=SpdxNone())
     document = Document(creation_info_fixture(), files=[file])
 
     converted_dict = converter.convert(file, document)
diff --git a/tests/jsonschema/test_snippet_converter.py b/tests/jsonschema/test_snippet_converter.py
index c29ad08..788bb43 100644
--- a/tests/jsonschema/test_snippet_converter.py
+++ b/tests/jsonschema/test_snippet_converter.py
@@ -66,7 +66,7 @@ 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),
-                      concluded_license=LicenseExpression("licenseExpression1"),
+                      license_concluded=LicenseExpression("licenseExpression1"),
                       license_info_in_snippet=[LicenseExpression("licenseExpression2"),
                                                LicenseExpression("licenseExpression3")],
                       license_comment="licenseComment", copyright_text="copyrightText", comment="comment", name="name",
@@ -98,7 +98,7 @@ def test_successful_conversion(converter: SnippetConverter):
 
 
 def test_null_values(converter: SnippetConverter):
-    snippet = snippet_fixture(concluded_license=None, license_comment=None, copyright_text=None, comment=None,
+    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])
@@ -115,7 +115,7 @@ def test_null_values(converter: SnippetConverter):
 
 
 def test_spdx_no_assertion(converter: SnippetConverter):
-    snippet = snippet_fixture(concluded_license=SpdxNoAssertion(), license_info_in_snippet=SpdxNoAssertion())
+    snippet = snippet_fixture(license_concluded=SpdxNoAssertion(), license_info_in_snippet=SpdxNoAssertion())
 
     document = Document(creation_info_fixture(), snippets=[snippet])
     converted_dict = converter.convert(snippet, document)
@@ -126,7 +126,7 @@ def test_spdx_no_assertion(converter: SnippetConverter):
 
 
 def test_spdx_none(converter: SnippetConverter):
-    snippet = snippet_fixture(concluded_license=SpdxNone(), license_info_in_snippet=SpdxNone())
+    snippet = snippet_fixture(license_concluded=SpdxNone(), license_info_in_snippet=SpdxNone())
 
     document = Document(creation_info_fixture(), snippets=[snippet])
     converted_dict = converter.convert(snippet, document)
diff --git a/tests/model/test_file.py b/tests/model/test_file.py
index 40a77d7..14d6b4c 100644
--- a/tests/model/test_file.py
+++ b/tests/model/test_file.py
@@ -16,7 +16,7 @@ def test_correct_initialization(checksum):
     assert file.spdx_id == "id"
     assert file.checksums == [checksum, checksum]
     assert file.file_type == [FileType.OTHER, FileType.SPDX]
-    assert file.concluded_license == SpdxNone()
+    assert file.license_concluded == SpdxNone()
     assert file.license_info_in_file == SpdxNoAssertion()
     assert file.license_comment == "comment on license"
     assert file.copyright_text == "copyright"
@@ -33,7 +33,7 @@ def test_correct_initialization_with_default_values(checksum):
     assert file.spdx_id == "id"
     assert file.checksums == [checksum, checksum]
     assert file.file_type == []
-    assert file.concluded_license is None
+    assert file.license_concluded is None
     assert file.license_info_in_file == []
     assert file.license_comment is None
     assert file.copyright_text is None
@@ -68,9 +68,9 @@ def test_wrong_type_in_file_type(checksum):
 
 
 @mock.patch('spdx.model.checksum.Checksum', autospec=True)
-def test_wrong_type_in_concluded_license(checksum):
+def test_wrong_type_in_license_concluded(checksum):
     with pytest.raises(TypeError):
-        File("name", "id", [checksum], concluded_license="NONE")
+        File("name", "id", [checksum], license_concluded="NONE")
 
 
 @mock.patch('spdx.model.checksum.Checksum', autospec=True)
diff --git a/tests/model/test_snippet.py b/tests/model/test_snippet.py
index 779e0c6..23bc2b6 100644
--- a/tests/model/test_snippet.py
+++ b/tests/model/test_snippet.py
@@ -12,7 +12,7 @@ def test_correct_initialization():
     assert snippet.file_spdx_id == "file_id"
     assert snippet.byte_range == (200, 400)
     assert snippet.line_range == (20, 40)
-    assert snippet.concluded_license == SpdxNone()
+    assert snippet.license_concluded == SpdxNone()
     assert snippet.license_info_in_snippet == SpdxNoAssertion()
     assert snippet.license_comment == "comment on license"
     assert snippet.copyright_text == "copyright"
@@ -27,7 +27,7 @@ def test_correct_initialization_with_default_values():
     assert snippet.file_spdx_id == "file_id"
     assert snippet.byte_range == (200, 400)
     assert snippet.line_range is None
-    assert snippet.concluded_license is None
+    assert snippet.license_concluded is None
     assert snippet.license_info_in_snippet is None
     assert snippet.license_comment is None
     assert snippet.copyright_text is None
@@ -56,9 +56,9 @@ def test_wrong_type_in_line_range():
         Snippet("id", "file_id", (200, 400), line_range=(20, "40"))
 
 
-def test_wrong_type_in_concluded_license():
+def test_wrong_type_in_license_concluded():
     with pytest.raises(TypeError):
-        Snippet("id", "file_id", (200, 400), concluded_license="NONE")
+        Snippet("id", "file_id", (200, 400), license_concluded="NONE")
 
 
 def test_wrong_type_in_license_info_in_snippet():
diff --git a/tests/parser/jsonlikedict/test_file_parser.py b/tests/parser/jsonlikedict/test_file_parser.py
index ea8eabe..8a06f63 100644
--- a/tests/parser/jsonlikedict/test_file_parser.py
+++ b/tests/parser/jsonlikedict/test_file_parser.py
@@ -56,7 +56,7 @@ def test_parse_file():
     assert file.file_type == [FileType.SOURCE]
     TestCase().assertCountEqual(file.contributors, ["The Regents of the University of California",
                                                     "Modified by Paul Mundt lethal@linux-sh.org", "IBM Corporation"])
-    assert file.concluded_license == LicenseExpression("(LGPL-2.0-only OR LicenseRef-2)")
+    assert file.license_concluded == LicenseExpression("(LGPL-2.0-only OR LicenseRef-2)")
     TestCase().assertCountEqual(file.license_info_in_file,
                                 [LicenseExpression("GPL-2.0-only"), LicenseExpression("LicenseRef-2")])
     assert file.license_comment == "The concluded license was taken from the package level that the file was included in."
diff --git a/tests/parser/jsonlikedict/test_snippet_parser.py b/tests/parser/jsonlikedict/test_snippet_parser.py
index e9108ee..1fe87ae 100644
--- a/tests/parser/jsonlikedict/test_snippet_parser.py
+++ b/tests/parser/jsonlikedict/test_snippet_parser.py
@@ -61,7 +61,7 @@ def test_parse_snippet():
     assert snippet.line_range == (5, 23)
     assert snippet.file_spdx_id == "SPDXRef-DoapSource"
     assert snippet.license_info_in_snippet == [LicenseExpression("GPL-2.0-only")]
-    assert snippet.concluded_license == LicenseExpression("GPL-2.0-only")
+    assert snippet.license_concluded == LicenseExpression("GPL-2.0-only")
     assert snippet.attribution_texts == ["Some example attibution text."]
 
 
diff --git a/tests/writer/json/expected_results/expected.json b/tests/writer/json/expected_results/expected.json
index ee4b8e9..5277817 100644
--- a/tests/writer/json/expected_results/expected.json
+++ b/tests/writer/json/expected_results/expected.json
@@ -54,7 +54,7 @@
                 "TEXT"
             ],
             "licenseComments": "licenseComment",
-            "licenseConcluded": "concludedLicenseExpression",
+            "licenseConcluded": "licenseConcludedExpression",
             "licenseInfoInFiles": [
                 "licenseInfoInFileExpression"
             ],