@@ -431,6 +431,9 @@ class ExtraDataFieldMixin(models.Model):
431431 help_text = _ ("Optional mapping of extra data key/values." ),
432432 )
433433
434+ class Meta :
435+ abstract = True
436+
434437 def update_extra_data (self , data ):
435438 """Update the `extra_data` field with the provided `data` dict."""
436439 if not isinstance (data , dict ):
@@ -439,9 +442,6 @@ def update_extra_data(self, data):
439442 self .extra_data .update (data )
440443 self .save (update_fields = ["extra_data" ])
441444
442- class Meta :
443- abstract = True
444-
445445
446446class UpdateMixin :
447447 """
@@ -635,6 +635,10 @@ def save(self, *args, **kwargs):
635635 if global_webhook and is_new and not is_clone and not skip_global_webhook :
636636 self .setup_global_webhook ()
637637
638+ def get_absolute_url (self ):
639+ """Return this project's details URL."""
640+ return reverse ("project_detail" , args = [self .slug ])
641+
638642 def setup_global_webhook (self ):
639643 """
640644 Create a global webhook subscription instance from values defined in the
@@ -1180,8 +1184,7 @@ def write_input_file(self, file_object):
11801184 file_path = Path (self .input_path / filename )
11811185
11821186 with open (file_path , "wb+" ) as f :
1183- for chunk in file_object .chunks ():
1184- f .write (chunk )
1187+ f .writelines (file_object .chunks ())
11851188
11861189 def copy_input_from (self , input_location ):
11871190 """
@@ -1428,10 +1431,6 @@ def add_error(
14281431 object_instance ,
14291432 )
14301433
1431- def get_absolute_url (self ):
1432- """Return this project's details URL."""
1433- return reverse ("project_detail" , args = [self .slug ])
1434-
14351434 @cached_property
14361435 def resource_count (self ):
14371436 """Return the number of resources related to this project."""
@@ -2533,21 +2532,6 @@ class Compliance(models.TextChoices):
25332532 class Meta :
25342533 abstract = True
25352534
2536- @classmethod
2537- def from_db (cls , db , field_names , values ):
2538- """
2539- Store the ``license_expression_field`` on loading this instance from the
2540- database value.
2541- The cached value is then used to detect changes on `save()`.
2542- """
2543- new = super ().from_db (db , field_names , values )
2544-
2545- if cls .license_expression_field in field_names :
2546- field_index = field_names .index (cls .license_expression_field )
2547- new ._loaded_license_expression = values [field_index ]
2548-
2549- return new
2550-
25512535 def save (self , codebase = None , * args , ** kwargs ):
25522536 """
25532537 Injects policies, if the feature is enabled, when the
@@ -2566,6 +2550,21 @@ def save(self, codebase=None, *args, **kwargs):
25662550
25672551 super ().save (* args , ** kwargs )
25682552
2553+ @classmethod
2554+ def from_db (cls , db , field_names , values ):
2555+ """
2556+ Store the ``license_expression_field`` on loading this instance from the
2557+ database value.
2558+ The cached value is then used to detect changes on `save()`.
2559+ """
2560+ new = super ().from_db (db , field_names , values )
2561+
2562+ if cls .license_expression_field in field_names :
2563+ field_index = field_names .index (cls .license_expression_field )
2564+ new ._loaded_license_expression = values [field_index ]
2565+
2566+ return new
2567+
25692568 @property
25702569 def policy_index (self ):
25712570 return self .project .policy_index
@@ -2790,6 +2789,9 @@ class Meta:
27902789 def __str__ (self ):
27912790 return self .path
27922791
2792+ def get_absolute_url (self ):
2793+ return reverse ("resource_detail" , args = [self .project .slug , self .path ])
2794+
27932795 @property
27942796 def location_path (self ):
27952797 """Return the location of the resource as a Path instance."""
@@ -2949,9 +2951,6 @@ def extracted_from(self, codebase=None):
29492951 archive_path , _ , _ = self .path .rpartition ("-extract" )
29502952 return self .project .get_resource (archive_path )
29512953
2952- def get_absolute_url (self ):
2953- return reverse ("resource_detail" , args = [self .project .slug , self .path ])
2954-
29552954 def get_raw_url (self ):
29562955 """Return the URL to access the RAW content of the resource."""
29572956 return reverse ("resource_raw" , args = [self .project .slug , self .path ])
@@ -3143,14 +3142,14 @@ class VulnerabilityMixin(models.Model):
31433142
31443143 affected_by_vulnerabilities = models .JSONField (blank = True , default = list )
31453144
3145+ class Meta :
3146+ abstract = True
3147+
31463148 @property
31473149 def is_vulnerable (self ):
31483150 """Returns True if this instance is affected by vulnerabilities."""
31493151 return bool (self .affected_by_vulnerabilities )
31503152
3151- class Meta :
3152- abstract = True
3153-
31543153
31553154class VulnerabilityQuerySetMixin :
31563155 def vulnerable (self ):
0 commit comments