Skip to content

Commit dba4891

Browse files
committed
Refactor update_from_data method into a UpdateFromDataMixin #447
Signed-off-by: Thomas Druez <[email protected]>
1 parent 01a4648 commit dba4891

File tree

2 files changed

+43
-40
lines changed

2 files changed

+43
-40
lines changed

scanpipe/models.py

+43-36
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ class RunInProgressError(Exception):
8383
"""Run are in progress or queued on this project."""
8484

8585

86+
# PackageURL._fields
87+
PURL_FIELDS = ("type", "namespace", "name", "version", "qualifiers", "subpath")
88+
89+
8690
class UUIDPKModel(models.Model):
8791
uuid = models.UUIDField(
8892
verbose_name=_("UUID"),
@@ -1006,6 +1010,39 @@ def add_errors(self, errors):
10061010
self.add_error(error)
10071011

10081012

1013+
class UpdateFromDataMixin:
1014+
"""
1015+
Adds a method to update an object instance from a `data` dict.
1016+
"""
1017+
1018+
def update_from_data(self, data, override=False):
1019+
"""
1020+
Update this object instance with the provided `data`.
1021+
The `save()` is called only if at least one field was modified.
1022+
"""
1023+
model_fields = self.__class__.model_fields()
1024+
updated_fields = []
1025+
1026+
for field_name, value in data.items():
1027+
skip_reasons = [
1028+
not value,
1029+
field_name not in model_fields,
1030+
field_name in PURL_FIELDS,
1031+
]
1032+
if any(skip_reasons):
1033+
continue
1034+
1035+
current_value = getattr(self, field_name, None)
1036+
if not current_value or (current_value != value and override):
1037+
setattr(self, field_name, value)
1038+
updated_fields.append(field_name)
1039+
1040+
if updated_fields:
1041+
self.save()
1042+
1043+
return updated_fields
1044+
1045+
10091046
class RunQuerySet(ProjectRelatedQuerySet):
10101047
def not_started(self):
10111048
"""
@@ -1814,6 +1851,7 @@ class DiscoveredPackage(
18141851
ProjectRelatedModel,
18151852
ExtraDataFieldMixin,
18161853
SaveProjectErrorMixin,
1854+
UpdateFromDataMixin,
18171855
AbstractPackage,
18181856
):
18191857
"""
@@ -1873,15 +1911,11 @@ def purl(self):
18731911
"""
18741912
return self.package_url
18751913

1876-
@classmethod
1877-
def purl_fields(cls):
1878-
return PackageURL._fields
1879-
18801914
@classmethod
18811915
def extract_purl_data(cls, package_data):
18821916
purl_data = {}
18831917

1884-
for field_name in cls.purl_fields():
1918+
for field_name in PURL_FIELDS:
18851919
value = package_data.get(field_name)
18861920
if field_name == "qualifiers":
18871921
value = normalize_qualifiers(value, encode=True)
@@ -1929,33 +1963,6 @@ def create_from_data(cls, project, package_data):
19291963
discovered_package.save(save_error=False, capture_exception=False)
19301964
return discovered_package
19311965

1932-
def update_from_data(self, package_data, override=False):
1933-
"""
1934-
Update this discovered package instance with the provided `package_data`.
1935-
The `save()` is called only if at least one field was modified.
1936-
"""
1937-
model_fields = DiscoveredPackage.model_fields()
1938-
updated_fields = []
1939-
1940-
for field_name, value in package_data.items():
1941-
skip_reasons = [
1942-
not value,
1943-
field_name not in model_fields,
1944-
field_name in self.purl_fields(),
1945-
]
1946-
if any(skip_reasons):
1947-
continue
1948-
1949-
current_value = getattr(self, field_name, None)
1950-
if not current_value or (current_value != value and override):
1951-
setattr(self, field_name, value)
1952-
updated_fields.append(field_name)
1953-
1954-
if updated_fields:
1955-
self.save()
1956-
1957-
return updated_fields
1958-
19591966

19601967
class DiscoveredDependencyQuerySet(ProjectRelatedQuerySet):
19611968
pass
@@ -2140,15 +2147,15 @@ def create_from_data(
21402147

21412148
return discovered_dependency
21422149

2143-
def update_from_data(self, dependency_data):
2150+
def update_from_data(self, data):
21442151
"""
2145-
Update this discovered dependency instance with the provided `dependency_data`.
2152+
Update this object instance with the provided `data`.
21462153
The `save()` is called only if at least one field was modified.
21472154
"""
2148-
model_fields = DiscoveredDependency.model_fields()
2155+
model_fields = self.__class__.model_fields()
21492156
updated_fields = []
21502157

2151-
for field_name, value in dependency_data.items():
2158+
for field_name, value in data.items():
21522159
skip_reasons = [
21532160
not value,
21542161
field_name not in model_fields,

scanpipe/tests/test_models.py

-4
Original file line numberDiff line numberDiff line change
@@ -1261,10 +1261,6 @@ def test_scanpipe_webhook_subscription_send_method(self, mock_post):
12611261
webhook.refresh_from_db()
12621262
self.assertTrue(webhook.sent)
12631263

1264-
def test_scanpipe_discovered_package_model_purl_fields(self):
1265-
expected = ("type", "namespace", "name", "version", "qualifiers", "subpath")
1266-
self.assertEqual(expected, DiscoveredPackage.purl_fields())
1267-
12681264
def test_scanpipe_discovered_package_model_extract_purl_data(self):
12691265
package_data = {}
12701266
expected = {

0 commit comments

Comments
 (0)