diff --git a/AUTHORS.rst b/AUTHORS.rst index 9a8224dc7da..1d29e439e4b 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -108,3 +108,5 @@ The following organizations or individuals have contributed to ScanCode: - Yash Sharma @yasharmaster - Yunus Rahbar @yns88 - Stefano Zacchiroli @zacchiro +- Temi Eyesan @teyesan +- Tram Trinh @tram-tr diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d9a5a6b4026..fc373bcb38a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,11 @@ Next release ``licensedcode-data``. https://github.com/aboutcode-org/scancode-toolkit/pull/5056 +- Fixed nuget/nuspec parser to correctly extract file-referenced and + expression-based elements instead of the deprecated + licenseUrl fallback + https://github.com/aboutcode-org/scancode-toolkit/pull/5271 + v33.0.0rc1 - 2026-05-14 ------------------------ diff --git a/src/packagedcode/nuget.py b/src/packagedcode/nuget.py index d0d7e110f2f..72a8521e482 100644 --- a/src/packagedcode/nuget.py +++ b/src/packagedcode/nuget.py @@ -18,6 +18,8 @@ Handle NuGet packages and their manifests. """ +DEPRECATED_NUGET_LICENSE_URL = 'https://aka.ms/deprecateLicenseUrl' + def get_dependencies(nuspec): """ @@ -79,6 +81,32 @@ def _get_dep_packs(deps, extra_data): extra_data=extra, ) +def get_declared_license(nuspec): + extracted_license_statement = None + license_file = None + + license_data = nuspec.get('license') + if license_data: + if isinstance(license_data, dict): + license_type = license_data.get('@type') + license_text = license_data.get('#text') + if license_type == 'file': + license_file = license_text + else: + # "expression" (an SPDX license expression) or any other unspecified type: keep the text as is + extracted_license_statement = license_text + else: + # defensive: in case a plain string ever shows up here. + extracted_license_statement = license_data + + license_url = nuspec.get('licenseUrl') + if license_url and license_url != DEPRECATED_NUGET_LICENSE_URL: + if extracted_license_statement: + extracted_license_statement = f'{extracted_license_statement}\n{license_url}' + else: + extracted_license_statement = license_url + + return extracted_license_statement, license_file def get_urls(name, version, **kwargs): return dict( @@ -155,14 +183,20 @@ def parse(cls, location, package_only=False): urls = get_urls(name, version) - extracted_license_statement = None - # See https://docs.microsoft.com/en-us/nuget/reference/nuspec#license - # This is a SPDX license expression - if 'license' in nuspec: - extracted_license_statement = nuspec.get('license') - # Deprecated and not a license expression, just a URL - elif 'licenseUrl' in nuspec: - extracted_license_statement = nuspec.get('licenseUrl') + # extracted_license_statement = None + # # See https://docs.microsoft.com/en-us/nuget/reference/nuspec#license + # # This is a SPDX license expression + # if 'license' in nuspec: + # extracted_license_statement = nuspec.get('license') + # # Deprecated and not a license expression, just a URL + # elif 'licenseUrl' in nuspec: + # extracted_license_statement = nuspec.get('licenseUrl') + + extracted_license_statement, license_file = get_declared_license(nuspec) + extra_data = {} + if license_file: + extra_data['license_file'] = license_file + package_data = dict( datasource_id=cls.datasource_id, @@ -176,6 +210,7 @@ def parse(cls, location, package_only=False): extracted_license_statement=extracted_license_statement, copyright=nuspec.get('copyright') or None, vcs_url=vcs_url, + extra_data=extra_data, **urls, ) yield models.PackageData.from_data(package_data, package_only) diff --git a/tests/packagedcode/data/license_detection/reference-at-manifest/fizzler.expected.json b/tests/packagedcode/data/license_detection/reference-at-manifest/fizzler.expected.json index e3cfae03ae4..8b1d34f55bd 100644 --- a/tests/packagedcode/data/license_detection/reference-at-manifest/fizzler.expected.json +++ b/tests/packagedcode/data/license_detection/reference-at-manifest/fizzler.expected.json @@ -43,16 +43,17 @@ "license_expression": "unknown-license-reference", "license_expression_spdx": "LicenseRef-scancode-unknown-license-reference", "from_file": "fizzler/Fizzler.nuspec", - "start_line": 1, - "end_line": 1, - "matcher": "1-hash", - "score": 16.0, - "matched_length": 3, + "start_line": 9, + "end_line": 9, + "matcher": "2-aho", + "score": 33.0, + "matched_length": 6, "match_coverage": 100.0, - "rule_relevance": 16, - "rule_identifier": "unknown-license-reference_383.RULE", - "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/unknown-license-reference_383.RULE", - "matched_text": "license COPYING.txt" + "rule_relevance": 33, + "rule_identifier": "unknown-license-reference_382.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/unknown-license-reference_382.RULE", + "matched_text": " COPYING.txt", + "matched_text_diagnostics": "license type=\"file\">COPYING.txt" }, { "license_expression": "lgpl-2.1-plus", @@ -87,21 +88,23 @@ "matched_text_diagnostics": "LICENSE\n \nGNU GENERAL PUBLIC LICENSE" } ], - "identifier": "lgpl_2_1_plus_and_gpl_1_0_plus-15b4d27c-9fa6-eb84-010f-152d45207f46", "detection_log": [ "package-unknown-reference-to-local-file" - ] + ], + "identifier": "lgpl_2_1_plus_and_gpl_1_0_plus-62bd07da-4dc9-fb2e-ad66-9eafe419c120" } ], "other_license_expression": null, "other_license_expression_spdx": null, "other_license_detections": [], - "extracted_license_statement": "'@type': file\n'#text': COPYING.txt\n", + "extracted_license_statement": null, "notice_text": null, "source_packages": [], "is_private": false, "is_virtual": false, - "extra_data": {}, + "extra_data": { + "license_file": "COPYING.txt" + }, "repository_homepage_url": "https://www.nuget.org/packages/Fizzler/1.3.0", "repository_download_url": "https://www.nuget.org/api/v2/package/Fizzler/1.3.0", "api_data_url": "https://api.nuget.org/v3/registration3/fizzler/1.3.0.json", @@ -154,71 +157,13 @@ } ], "license_detections": [ - { - "identifier": "lgpl_2_1_plus_and_gpl_1_0_plus-15b4d27c-9fa6-eb84-010f-152d45207f46", - "license_expression": "lgpl-2.1-plus AND gpl-1.0-plus", - "license_expression_spdx": "LGPL-2.1-or-later AND GPL-1.0-or-later", - "detection_count": 1, - "detection_log": [ - "package-unknown-reference-to-local-file" - ], - "reference_matches": [ - { - "license_expression": "unknown-license-reference", - "license_expression_spdx": "LicenseRef-scancode-unknown-license-reference", - "from_file": "fizzler/Fizzler.nuspec", - "start_line": 1, - "end_line": 1, - "matcher": "1-hash", - "score": 16.0, - "matched_length": 3, - "match_coverage": 100.0, - "rule_relevance": 16, - "rule_identifier": "unknown-license-reference_383.RULE", - "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/unknown-license-reference_383.RULE", - "matched_text": "license COPYING.txt" - }, - { - "license_expression": "lgpl-2.1-plus", - "license_expression_spdx": "LGPL-2.1-or-later", - "from_file": "fizzler/COPYING.txt", - "start_line": 1, - "end_line": 1, - "matcher": "2-aho", - "score": 100.0, - "matched_length": 5, - "match_coverage": 100.0, - "rule_relevance": 100, - "rule_identifier": "lgpl-2.1-plus_485.RULE", - "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/lgpl-2.1-plus_485.RULE", - "matched_text": "GNU LESSER GENERAL PUBLIC LICENSE", - "matched_text_diagnostics": "GNU LESSER GENERAL PUBLIC LICENSE" - }, - { - "license_expression": "gpl-1.0-plus", - "license_expression_spdx": "GPL-1.0-or-later", - "from_file": "fizzler/COPYING.txt", - "start_line": 1, - "end_line": 3, - "matcher": "2-aho", - "score": 100.0, - "matched_length": 5, - "match_coverage": 100.0, - "rule_relevance": 100, - "rule_identifier": "gpl_160.RULE", - "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/gpl_160.RULE", - "matched_text": "GNU LESSER GENERAL PUBLIC LICENSE\n \nGNU GENERAL PUBLIC LICENSE", - "matched_text_diagnostics": "LICENSE\n \nGNU GENERAL PUBLIC LICENSE" - } - ] - }, { "identifier": "lgpl_2_1_plus_and_gpl_1_0_plus-62bd07da-4dc9-fb2e-ad66-9eafe419c120", "license_expression": "lgpl-2.1-plus AND gpl-1.0-plus", "license_expression_spdx": "LGPL-2.1-or-later AND GPL-1.0-or-later", - "detection_count": 1, + "detection_count": 2, "detection_log": [ - "unknown-reference-to-local-file" + "package-unknown-reference-to-local-file" ], "reference_matches": [ { @@ -414,16 +359,17 @@ "license_expression": "unknown-license-reference", "license_expression_spdx": "LicenseRef-scancode-unknown-license-reference", "from_file": "fizzler/Fizzler.nuspec", - "start_line": 1, - "end_line": 1, - "matcher": "1-hash", - "score": 16.0, - "matched_length": 3, + "start_line": 9, + "end_line": 9, + "matcher": "2-aho", + "score": 33.0, + "matched_length": 6, "match_coverage": 100.0, - "rule_relevance": 16, - "rule_identifier": "unknown-license-reference_383.RULE", - "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/unknown-license-reference_383.RULE", - "matched_text": "license COPYING.txt" + "rule_relevance": 33, + "rule_identifier": "unknown-license-reference_382.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/unknown-license-reference_382.RULE", + "matched_text": " COPYING.txt", + "matched_text_diagnostics": "license type=\"file\">COPYING.txt" }, { "license_expression": "lgpl-2.1-plus", @@ -458,22 +404,24 @@ "matched_text_diagnostics": "LICENSE\n \nGNU GENERAL PUBLIC LICENSE" } ], - "identifier": "lgpl_2_1_plus_and_gpl_1_0_plus-15b4d27c-9fa6-eb84-010f-152d45207f46", "detection_log": [ "package-unknown-reference-to-local-file" - ] + ], + "identifier": "lgpl_2_1_plus_and_gpl_1_0_plus-62bd07da-4dc9-fb2e-ad66-9eafe419c120" } ], "other_license_expression": null, "other_license_expression_spdx": null, "other_license_detections": [], - "extracted_license_statement": "'@type': file\n'#text': COPYING.txt\n", + "extracted_license_statement": null, "notice_text": null, "source_packages": [], "file_references": [], "is_private": false, "is_virtual": false, - "extra_data": {}, + "extra_data": { + "license_file": "COPYING.txt" + }, "dependencies": [ { "purl": "pkg:nuget/NETStandard.Library", @@ -514,8 +462,8 @@ "for_packages": [ "pkg:nuget/Fizzler@1.3.0?uuid=fixed-uid-done-for-testing-5642512d1758" ], - "detected_license_expression": "lgpl-2.1-plus AND gpl-1.0-plus", - "detected_license_expression_spdx": "LGPL-2.1-or-later AND GPL-1.0-or-later", + "detected_license_expression": "unknown-license-reference", + "detected_license_expression_spdx": "LicenseRef-scancode-unknown-license-reference", "license_detections": [ { "license_expression": "lgpl-2.1-plus AND gpl-1.0-plus", @@ -571,7 +519,7 @@ } ], "detection_log": [ - "unknown-reference-to-local-file" + "package-unknown-reference-to-local-file" ], "identifier": "lgpl_2_1_plus_and_gpl_1_0_plus-62bd07da-4dc9-fb2e-ad66-9eafe419c120" } diff --git a/tests/packagedcode/data/nuget/ExpressionLicense.nuspec b/tests/packagedcode/data/nuget/ExpressionLicense.nuspec new file mode 100644 index 00000000000..14c253ebb26 --- /dev/null +++ b/tests/packagedcode/data/nuget/ExpressionLicense.nuspec @@ -0,0 +1,9 @@ + + + + ExpressionLicenseExample + 1.0.0 + false + MIT + + \ No newline at end of file diff --git a/tests/packagedcode/data/nuget/ExpressionLicense.nuspec.json.expected b/tests/packagedcode/data/nuget/ExpressionLicense.nuspec.json.expected new file mode 100644 index 00000000000..c63a64d19dc --- /dev/null +++ b/tests/packagedcode/data/nuget/ExpressionLicense.nuspec.json.expected @@ -0,0 +1,69 @@ +[ + { + "type": "nuget", + "namespace": null, + "name": "ExpressionLicenseExample", + "version": "1.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "mit", + "declared_license_expression_spdx": "MIT", + "license_detections": [ + { + "license_expression": "mit", + "license_expression_spdx": "MIT", + "matches": [ + { + "license_expression": "mit", + "license_expression_spdx": "MIT", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-spdx-id", + "score": 100.0, + "matched_length": 1, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx-license-identifier-mit-5da48780aba670b0860c46d899ed42a0f243ff06", + "rule_url": null, + "matched_text": "MIT" + } + ], + "identifier": "mit-a822f434-d61f-f2b1-c792-8b8cb9e7b9bf" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "MIT", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": "https://www.nuget.org/packages/ExpressionLicenseExample/1.0.0", + "repository_download_url": "https://www.nuget.org/api/v2/package/ExpressionLicenseExample/1.0.0", + "api_data_url": "https://api.nuget.org/v3/registration3/expressionlicenseexample/1.0.0.json", + "datasource_id": "nuget_nupsec", + "purl": "pkg:nuget/ExpressionLicenseExample@1.0.0" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/nuget/LicenseURLOnly.nuspec b/tests/packagedcode/data/nuget/LicenseURLOnly.nuspec new file mode 100644 index 00000000000..14cd7e0b4d4 --- /dev/null +++ b/tests/packagedcode/data/nuget/LicenseURLOnly.nuspec @@ -0,0 +1,9 @@ + + + + LicenseUrlOnlyExample + 1.0.0 + false + https://opensource.org/licenses/MIT + + \ No newline at end of file diff --git a/tests/packagedcode/data/nuget/LicenseURLOnly.nuspec.json.expected b/tests/packagedcode/data/nuget/LicenseURLOnly.nuspec.json.expected new file mode 100644 index 00000000000..a1804e7c03f --- /dev/null +++ b/tests/packagedcode/data/nuget/LicenseURLOnly.nuspec.json.expected @@ -0,0 +1,69 @@ +[ + { + "type": "nuget", + "namespace": null, + "name": "LicenseUrlOnlyExample", + "version": "1.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "mit", + "declared_license_expression_spdx": "MIT", + "license_detections": [ + { + "license_expression": "mit", + "license_expression_spdx": "MIT", + "matches": [ + { + "license_expression": "mit", + "license_expression_spdx": "MIT", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-hash", + "score": 100.0, + "matched_length": 5, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "mit_65.RULE", + "rule_url": "https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/rules/mit_65.RULE", + "matched_text": "https://opensource.org/licenses/MIT" + } + ], + "identifier": "mit-8c45a313-6646-a283-ebeb-697e96d45185" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "https://opensource.org/licenses/MIT", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": "https://www.nuget.org/packages/LicenseUrlOnlyExample/1.0.0", + "repository_download_url": "https://www.nuget.org/api/v2/package/LicenseUrlOnlyExample/1.0.0", + "api_data_url": "https://api.nuget.org/v3/registration3/licenseurlonlyexample/1.0.0.json", + "datasource_id": "nuget_nupsec", + "purl": "pkg:nuget/LicenseUrlOnlyExample@1.0.0" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/nuget/NoLicenseInfo.nuspec b/tests/packagedcode/data/nuget/NoLicenseInfo.nuspec new file mode 100644 index 00000000000..ab5abcca401 --- /dev/null +++ b/tests/packagedcode/data/nuget/NoLicenseInfo.nuspec @@ -0,0 +1,8 @@ + + + + NoLicenseInfoExample + 1.0.0 + false + + \ No newline at end of file diff --git a/tests/packagedcode/data/nuget/NoLicenseInfo.nuspec.json.expected b/tests/packagedcode/data/nuget/NoLicenseInfo.nuspec.json.expected new file mode 100644 index 00000000000..a74a297a063 --- /dev/null +++ b/tests/packagedcode/data/nuget/NoLicenseInfo.nuspec.json.expected @@ -0,0 +1,46 @@ +[ + { + "type": "nuget", + "namespace": null, + "name": "NoLicenseInfoExample", + "version": "1.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": "https://www.nuget.org/packages/NoLicenseInfoExample/1.0.0", + "repository_download_url": "https://www.nuget.org/api/v2/package/NoLicenseInfoExample/1.0.0", + "api_data_url": "https://api.nuget.org/v3/registration3/nolicenseinfoexample/1.0.0.json", + "datasource_id": "nuget_nupsec", + "purl": "pkg:nuget/NoLicenseInfoExample@1.0.0" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/nuget/PlainLicense.nuspec b/tests/packagedcode/data/nuget/PlainLicense.nuspec new file mode 100644 index 00000000000..3993bdd7fec --- /dev/null +++ b/tests/packagedcode/data/nuget/PlainLicense.nuspec @@ -0,0 +1,9 @@ + + + + PlainLicenseExample + 1.0.0 + false + MIT + + \ No newline at end of file diff --git a/tests/packagedcode/data/nuget/PlainLicense.nuspec.json.expected b/tests/packagedcode/data/nuget/PlainLicense.nuspec.json.expected new file mode 100644 index 00000000000..05366edcadf --- /dev/null +++ b/tests/packagedcode/data/nuget/PlainLicense.nuspec.json.expected @@ -0,0 +1,69 @@ +[ + { + "type": "nuget", + "namespace": null, + "name": "PlainLicenseExample", + "version": "1.0.0", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": null, + "release_date": null, + "parties": [], + "keywords": [], + "homepage_url": null, + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": null, + "holder": null, + "declared_license_expression": "mit", + "declared_license_expression_spdx": "MIT", + "license_detections": [ + { + "license_expression": "mit", + "license_expression_spdx": "MIT", + "matches": [ + { + "license_expression": "mit", + "license_expression_spdx": "MIT", + "from_file": null, + "start_line": 1, + "end_line": 1, + "matcher": "1-spdx-id", + "score": 100.0, + "matched_length": 1, + "match_coverage": 100.0, + "rule_relevance": 100, + "rule_identifier": "spdx-license-identifier-mit-5da48780aba670b0860c46d899ed42a0f243ff06", + "rule_url": null, + "matched_text": "MIT" + } + ], + "identifier": "mit-a822f434-d61f-f2b1-c792-8b8cb9e7b9bf" + } + ], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": "MIT", + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": {}, + "dependencies": [], + "repository_homepage_url": "https://www.nuget.org/packages/PlainLicenseExample/1.0.0", + "repository_download_url": "https://www.nuget.org/api/v2/package/PlainLicenseExample/1.0.0", + "api_data_url": "https://api.nuget.org/v3/registration3/plainlicenseexample/1.0.0.json", + "datasource_id": "nuget_nupsec", + "purl": "pkg:nuget/PlainLicenseExample@1.0.0" + } +] \ No newline at end of file diff --git a/tests/packagedcode/data/nuget/SpecFlow.MsTest.nuspec b/tests/packagedcode/data/nuget/SpecFlow.MsTest.nuspec new file mode 100644 index 00000000000..53018871859 --- /dev/null +++ b/tests/packagedcode/data/nuget/SpecFlow.MsTest.nuspec @@ -0,0 +1,22 @@ + + + + SpecFlow.MsTest + 3.1.89 + SpecFlow + Tricentis + false + LICENSE.txt + https://aka.ms/deprecateLicenseUrl + https://specflow.org + Provides MsTest bindings for SpecFlow test execution + Copyright + specflow bdd mstest + + + + + + + + \ No newline at end of file diff --git a/tests/packagedcode/data/nuget/SpecFlow.MsTest.nuspec.json.expected b/tests/packagedcode/data/nuget/SpecFlow.MsTest.nuspec.json.expected new file mode 100644 index 00000000000..2c8eb2c8100 --- /dev/null +++ b/tests/packagedcode/data/nuget/SpecFlow.MsTest.nuspec.json.expected @@ -0,0 +1,92 @@ +[ + { + "type": "nuget", + "namespace": null, + "name": "SpecFlow.MsTest", + "version": "3.1.89", + "qualifiers": {}, + "subpath": null, + "primary_language": null, + "description": "Provides MsTest bindings for SpecFlow test execution", + "release_date": null, + "parties": [ + { + "type": null, + "role": "author", + "name": "SpecFlow", + "email": null, + "url": null + }, + { + "type": null, + "role": "owner", + "name": "Tricentis", + "email": null, + "url": null + } + ], + "keywords": [], + "homepage_url": "https://specflow.org", + "download_url": null, + "size": null, + "sha1": null, + "md5": null, + "sha256": null, + "sha512": null, + "bug_tracking_url": null, + "code_view_url": null, + "vcs_url": null, + "copyright": "Copyright", + "holder": "Copyright", + "declared_license_expression": null, + "declared_license_expression_spdx": null, + "license_detections": [], + "other_license_expression": null, + "other_license_expression_spdx": null, + "other_license_detections": [], + "extracted_license_statement": null, + "notice_text": null, + "source_packages": [], + "file_references": [], + "is_private": false, + "is_virtual": false, + "extra_data": { + "license_file": "LICENSE.txt" + }, + "dependencies": [ + { + "purl": "pkg:nuget/SpecFlow", + "extracted_requirement": "3.1.89", + "scope": "dependency", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": { + "framework": ".NETStandard2.0", + "exclude": "Build,Analyzers" + } + }, + { + "purl": "pkg:nuget/MSTest.TestFramework", + "extracted_requirement": "1.3.2", + "scope": "dependency", + "is_runtime": true, + "is_optional": false, + "is_pinned": false, + "is_direct": true, + "resolved_package": {}, + "extra_data": { + "framework": ".NETStandard2.0", + "exclude": "Build,Analyzers" + } + } + ], + "repository_homepage_url": "https://www.nuget.org/packages/SpecFlow.MsTest/3.1.89", + "repository_download_url": "https://www.nuget.org/api/v2/package/SpecFlow.MsTest/3.1.89", + "api_data_url": "https://api.nuget.org/v3/registration3/specflow.mstest/3.1.89.json", + "datasource_id": "nuget_nupsec", + "purl": "pkg:nuget/SpecFlow.MsTest@3.1.89" + } +] \ No newline at end of file diff --git a/tests/packagedcode/test_nuget.py b/tests/packagedcode/test_nuget.py index d3af13ab51b..2e2b915a664 100644 --- a/tests/packagedcode/test_nuget.py +++ b/tests/packagedcode/test_nuget.py @@ -72,3 +72,33 @@ def test_parse_nuget_package_lock_json(self): def test_package_lock_json_is_package_data_file(self): test_file = self.get_test_loc('nuget/packages.lock.json') assert nuget.NugetPackagesLockHandler.is_datafile(test_file) + + def test_parse_creates_package_from_nuspec_plain_license(self): + test_file = self.get_test_loc('nuget/PlainLicense.nuspec') + package = nuget.NugetNuspecHandler.parse(test_file) + expected_loc = self.get_test_loc('nuget/PlainLicense.nuspec.json.expected') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_parse_creates_package_from_nuspec_license_url_only(self): + test_file = self.get_test_loc('nuget/LicenseURLOnly.nuspec') + package = nuget.NugetNuspecHandler.parse(test_file) + expected_loc = self.get_test_loc('nuget/LicenseURLOnly.nuspec.json.expected') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_parse_creates_package_from_nuspec_no_license_info(self): + test_file = self.get_test_loc('nuget/NoLicenseInfo.nuspec') + package = nuget.NugetNuspecHandler.parse(test_file) + expected_loc = self.get_test_loc('nuget/NoLicenseInfo.nuspec.json.expected') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_parse_creates_package_from_nuspec_expression_license(self): + test_file = self.get_test_loc('nuget/ExpressionLicense.nuspec') + package = nuget.NugetNuspecHandler.parse(test_file) + expected_loc = self.get_test_loc('nuget/ExpressionLicense.nuspec.json.expected') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES) + + def test_parse_creates_package_from_nuspec_with_license_file_and_deprecated_license_url(self): + test_file = self.get_test_loc('nuget/SpecFlow.MsTest.nuspec') + package = nuget.NugetNuspecHandler.parse(test_file) + expected_loc = self.get_test_loc('nuget/SpecFlow.MsTest.nuspec.json.expected') + self.check_packages_data(package, expected_loc, regen=REGEN_TEST_FIXTURES)