@@ -1003,6 +1003,19 @@ def walk_codebase_path(self):
10031003 """Return files and directories path of the codebase/ directory recursively."""
10041004 return self .codebase_path .rglob ("*" )
10051005
1006+ def get_resource (self , path ):
1007+ """
1008+ Return the codebase resource present for a given path,
1009+ or None the resource with that path does not exist.
1010+ This path is relative to the scan location.
1011+ This is same as the Codebase.get_resource() function.
1012+ """
1013+ # We don't want to raise an exception if there is no resource
1014+ # as this function is also called from the SCTK side
1015+ resource = self .codebaseresources .get_or_none (path = path )
1016+ if resource :
1017+ return resource
1018+
10061019 @cached_property
10071020 def can_change_inputs (self ):
10081021 """
@@ -2971,6 +2984,8 @@ class AbstractPackage(models.Model):
29712984 blank = True ,
29722985 help_text = _ ("A notice text for this package." ),
29732986 )
2987+ is_private = models .BooleanField (default = False )
2988+ is_virtual = models .BooleanField (default = False )
29742989 datasource_ids = models .JSONField (
29752990 default = list ,
29762991 blank = True ,
@@ -3432,6 +3447,7 @@ class DiscoveredDependency(
34323447 is_runtime = models .BooleanField (default = False )
34333448 is_optional = models .BooleanField (default = False )
34343449 is_resolved = models .BooleanField (default = False )
3450+ is_direct = models .BooleanField (default = False )
34353451
34363452 objects = DiscoveredDependencyQuerySet .as_manager ()
34373453
@@ -3452,6 +3468,7 @@ class Meta:
34523468 models .Index (fields = ["is_runtime" ]),
34533469 models .Index (fields = ["is_optional" ]),
34543470 models .Index (fields = ["is_resolved" ]),
3471+ models .Index (fields = ["is_direct" ]),
34553472 ]
34563473 constraints = [
34573474 models .UniqueConstraint (
@@ -3498,6 +3515,7 @@ def create_from_data(
34983515 project ,
34993516 dependency_data ,
35003517 for_package = None ,
3518+ resolved_to_package = None ,
35013519 datafile_resource = None ,
35023520 datasource_id = None ,
35033521 strip_datafile_path_root = False ,
@@ -3537,6 +3555,13 @@ def create_from_data(
35373555 package_uid = for_package_uid
35383556 )
35393557
3558+ if not resolved_to_package :
3559+ resolved_to_uid = dependency_data .get ("resolved_to_uid" )
3560+ if resolved_to_uid :
3561+ resolved_to_package = project .discoveredpackages .get (
3562+ package_uid = resolved_to_uid
3563+ )
3564+
35403565 if not datafile_resource :
35413566 datafile_path = dependency_data .get ("datafile_path" )
35423567 if datafile_path :
@@ -3562,10 +3587,36 @@ def create_from_data(
35623587 return cls .objects .create (
35633588 project = project ,
35643589 for_package = for_package ,
3590+ resolved_to_package = resolved_to_package ,
35653591 datafile_resource = datafile_resource ,
35663592 ** cleaned_data ,
35673593 )
35683594
3595+ @classmethod
3596+ def extract_purl_data (cls , dependency_data , ignore_nulls = False ):
3597+ purl_mapping = PackageURL .from_string (
3598+ purl = dependency_data .get ("purl" ),
3599+ ).to_dict ()
3600+ purl_data = {}
3601+
3602+ for field_name in PURL_FIELDS :
3603+ value = purl_mapping .get (field_name )
3604+ if field_name == "qualifiers" :
3605+ value = normalize_qualifiers (value , encode = True )
3606+ if not ignore_nulls :
3607+ purl_data [field_name ] = value or ""
3608+ else :
3609+ if value :
3610+ purl_data [field_name ] = value or ""
3611+
3612+ return purl_data
3613+
3614+ @classmethod
3615+ def populate_dependency_uuid (cls , dependency_data ):
3616+ purl = PackageURL .from_string (purl = dependency_data .get ("purl" ))
3617+ purl .qualifiers ["uuid" ] = str (uuid .uuid4 ())
3618+ dependency_data ["dependency_uid" ] = purl .to_string ()
3619+
35693620 @property
35703621 def spdx_id (self ):
35713622 return f"SPDXRef-scancodeio-{ self ._meta .model_name } -{ self .dependency_uid } "
0 commit comments