Skip to content

Commit 9f0a4bc

Browse files
authored
Fix the unique_together_lookups in import_package #295 (#298)
Signed-off-by: tdruez <tdruez@nexb.com>
1 parent b5590c8 commit 9f0a4bc

File tree

3 files changed

+72
-5
lines changed

3 files changed

+72
-5
lines changed

CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ Release notes
128128
- Add the ability to download Product "Imports" input file.
129129
https://github.com/aboutcode-org/dejacode/issues/156
130130

131+
- Fix a logic issue in the ImportPackageFromScanCodeIO.import_package that occurs when
132+
multiple packages with the same PURL, but different download_url or filename,
133+
are present in the Dataspace.
134+
https://github.com/aboutcode-org/dejacode/issues/295
135+
131136
### Version 5.2.1
132137

133138
- Fix the models documentation navigation.

product_portfolio/importers.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
from collections import defaultdict
1111

1212
from django import forms
13-
from django.core.exceptions import MultipleObjectsReturned
1413
from django.core.exceptions import ValidationError
1514
from django.core.validators import EMPTY_VALUES
1615
from django.db import IntegrityError
@@ -694,16 +693,14 @@ def import_package(self, package_data):
694693
package_data.pop("affected_by_vulnerabilities", None)
695694

696695
unique_together_lookups = {
697-
field: value
698-
for field in self.unique_together_fields
699-
if (value := package_data.get(field))
696+
field: package_data.get(field, "") for field in self.unique_together_fields
700697
}
701698

702699
# Check if the Package already exists in the local Dataspace
703700
try:
704701
package = Package.objects.scope(self.user.dataspace).get(**unique_together_lookups)
705702
self.existing["package"].append(str(package))
706-
except (ObjectDoesNotExist, MultipleObjectsReturned):
703+
except ObjectDoesNotExist:
707704
package = None
708705

709706
# Check if the Package already exists in the reference Dataspace

product_portfolio/tests/test_importers.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
from component_catalog.models import Component
2121
from component_catalog.models import Package
22+
from component_catalog.tests import make_package
2223
from dje.models import Dataspace
2324
from dje.tests import create_admin
2425
from dje.tests import create_superuser
@@ -1055,3 +1056,67 @@ def test_product_portfolio_import_packages_from_scancodeio_importer(
10551056
)
10561057
importer.save()
10571058
mock_fetch.assert_called()
1059+
1060+
@mock.patch("dejacode_toolkit.scancodeio.ScanCodeIO.fetch_project_dependencies")
1061+
@mock.patch("dejacode_toolkit.scancodeio.ScanCodeIO.fetch_project_packages")
1062+
def test_product_portfolio_import_packages_from_scio_importer_multiple_package_objs(
1063+
self, mock_fetch_packages, mock_fetch_dependencies
1064+
):
1065+
purl = "pkg:maven/org.apache.activemq/activemq-camel@5.11.0"
1066+
filename = "activemq-camel.zip"
1067+
1068+
package_data = {
1069+
"type": "maven",
1070+
"namespace": "org.apache.activemq",
1071+
"name": "activemq-camel",
1072+
"version": "5.11.0",
1073+
"primary_language": "Java",
1074+
"purl": purl,
1075+
"declared_license_expression": "bsd-new",
1076+
}
1077+
mock_fetch_packages.return_value = [package_data]
1078+
mock_fetch_dependencies.return_value = []
1079+
1080+
package1 = make_package(self.dataspace, package_url=purl)
1081+
package2 = make_package(self.dataspace, package_url=purl, filename=filename)
1082+
1083+
importer = ImportPackageFromScanCodeIO(
1084+
user=self.super_user,
1085+
project_uuid=uuid.uuid4(),
1086+
product=self.product1,
1087+
)
1088+
created, existing, errors = importer.save()
1089+
self.assertEqual({}, created)
1090+
self.assertEqual(purl, existing["package"][0])
1091+
self.assertEqual({}, errors)
1092+
# The package without the filename or download_url is used
1093+
self.assertEqual(package1, self.product1.packages.get())
1094+
1095+
self.product1.productpackages.all().delete()
1096+
package_data["filename"] = filename
1097+
importer = ImportPackageFromScanCodeIO(
1098+
user=self.super_user,
1099+
project_uuid=uuid.uuid4(),
1100+
product=self.product1,
1101+
)
1102+
created, existing, errors = importer.save()
1103+
self.assertEqual({}, created)
1104+
self.assertEqual(purl, existing["package"][0])
1105+
self.assertEqual({}, errors)
1106+
# The package with the filename is used
1107+
self.assertEqual(package2, self.product1.packages.get())
1108+
1109+
self.product1.productpackages.all().delete()
1110+
package_data["filename"] = "DO_NOT_EXISTS"
1111+
importer = ImportPackageFromScanCodeIO(
1112+
user=self.super_user,
1113+
project_uuid=uuid.uuid4(),
1114+
product=self.product1,
1115+
)
1116+
created, existing, errors = importer.save()
1117+
# New package is created.
1118+
self.assertEqual(
1119+
{"package": ["pkg:maven/org.apache.activemq/activemq-camel@5.11.0"]}, created
1120+
)
1121+
self.assertEqual({}, existing)
1122+
self.assertEqual({}, errors)

0 commit comments

Comments
 (0)