@@ -2556,6 +2556,27 @@ def test_package_model_inferred_url_property(self):
25562556 expected = "https://github.com/package-url/packageurl-python/tree/v0.10.4"
25572557 self .assertEqual (expected , package1 .inferred_url )
25582558
2559+ @mock .patch ("dejacode_toolkit.purldb.PurlDB.find_packages" )
2560+ def test_package_model_get_purldb_entries (self , mock_find_packages ):
2561+ purl = "pkg:pypi/django@3.0"
2562+ package1 = make_package (self .dataspace , package_url = purl )
2563+ purldb_entry1 = {
2564+ "purl" : purl ,
2565+ "type" : "pypi" ,
2566+ "name" : "django" ,
2567+ "version" : "3.0" ,
2568+ }
2569+ purldb_entry2 = {
2570+ "purl" : "pkg:pypi/django" ,
2571+ "type" : "pypi" ,
2572+ "name" : "django" ,
2573+ }
2574+
2575+ mock_find_packages .return_value = [purldb_entry1 , purldb_entry2 ]
2576+ purldb_entries = package1 .get_purldb_entries (user = self .user )
2577+ # The purldb_entry2 is excluded as the PURL differs
2578+ self .assertEqual ([purldb_entry1 ], purldb_entries )
2579+
25592580 @mock .patch ("component_catalog.models.Package.get_purldb_entries" )
25602581 def test_package_model_update_from_purldb (self , mock_get_purldb_entries ):
25612582 purldb_entry = {
@@ -2577,9 +2598,9 @@ def test_package_model_update_from_purldb(self, mock_get_purldb_entries):
25772598 }
25782599
25792600 mock_get_purldb_entries .return_value = [purldb_entry ]
2580- package1 = Package .objects .create (
2601+ package1 = make_package (
2602+ self .dataspace ,
25812603 filename = "package" ,
2582- dataspace = self .dataspace ,
25832604 # "unknown" values are overrided
25842605 declared_license_expression = "unknown" ,
25852606 )
@@ -2607,6 +2628,68 @@ def test_package_model_update_from_purldb(self, mock_get_purldb_entries):
26072628 for field_name in updated_fields :
26082629 self .assertEqual (purldb_entry [field_name ], getattr (package1 , field_name ))
26092630
2631+ @mock .patch ("component_catalog.models.Package.get_purldb_entries" )
2632+ def test_package_model_update_from_purldb_multiple_entries (self , mock_get_purldb_entries ):
2633+ purldb_entry1 = {
2634+ "uuid" : "326aa7a8-4f28-406d-89f9-c1404916925b" ,
2635+ "purl" : "pkg:pypi/django@3.0" ,
2636+ "type" : "pypi" ,
2637+ "name" : "django" ,
2638+ "version" : "3.0" ,
2639+ "keywords" : ["Keyword1" , "Keyword2" ],
2640+ "filename" : "Django-3.0.tar.gz" ,
2641+ "download_url" : "https://files.pythonhosted.org/packages/38/Django-3.0.tar.gz" ,
2642+ }
2643+ purldb_entry2 = {
2644+ "uuid" : "e133e70b-8dd3-4cf1-9711-72b1f57523a0" ,
2645+ "purl" : "pkg:pypi/django@3.0" ,
2646+ "type" : "pypi" ,
2647+ "name" : "django" ,
2648+ "version" : "3.0" ,
2649+ "primary_language" : "Python" ,
2650+ "keywords" : ["Keyword1" , "Keyword2" ],
2651+ "download_url" : "https://another.url/Django-3.0.tar.gz" ,
2652+ }
2653+
2654+ mock_get_purldb_entries .return_value = [purldb_entry1 , purldb_entry2 ]
2655+ package1 = make_package (self .dataspace , package_url = "pkg:pypi/django@3.0" )
2656+ updated_fields = package1 .update_from_purldb (self .user )
2657+ expected = ["filename" , "keywords" , "primary_language" ]
2658+ self .assertEqual (expected , sorted (updated_fields ))
2659+ self .assertEqual ("Django-3.0.tar.gz" , package1 .filename )
2660+ self .assertEqual (["Keyword1" , "Keyword2" ], package1 .keywords )
2661+ self .assertEqual ("Python" , package1 .primary_language )
2662+
2663+ @mock .patch ("component_catalog.models.Package.get_purldb_entries" )
2664+ def test_package_model_update_from_purldb_duplicate_exception (self , mock_get_purldb_entries ):
2665+ package_url = "pkg:pypi/django@3.0"
2666+ download_url = "https://files.pythonhosted.org/packages/38/Django-3.0.tar.gz"
2667+ purldb_entry = {
2668+ "purl" : package_url ,
2669+ "type" : "pypi" ,
2670+ "name" : "django" ,
2671+ "version" : "3.0" ,
2672+ "download_url" : download_url ,
2673+ "description" : "This value will be updated" ,
2674+ "md5" : "This value is skipped" ,
2675+ "sha1" : "This value is skipped" ,
2676+ }
2677+ mock_get_purldb_entries .return_value = [purldb_entry ]
2678+
2679+ # 2 packages with the same "pkg:pypi/django@3.0" PURL:
2680+ # - 1 with a `download_url` value
2681+ # - 1 without a `download_url` value
2682+ make_package (self .dataspace , package_url = package_url , download_url = download_url )
2683+ package_no_download_url = make_package (self .dataspace , package_url = package_url )
2684+
2685+ # Updating the package with the `download_url` from the purldb_entry data
2686+ # would violates the unique constraint.
2687+ # This is handle properly by update_from_purldb.
2688+ updated_fields = package_no_download_url .update_from_purldb (self .user )
2689+ self .assertEqual (["description" ], updated_fields )
2690+ package_no_download_url .refresh_from_db ()
2691+ self .assertEqual (purldb_entry ["description" ], package_no_download_url .description )
2692+
26102693 def test_package_model_vulnerability_queryset_mixin (self ):
26112694 package1 = make_package (self .dataspace , is_vulnerable = True )
26122695 package2 = make_package (self .dataspace )
0 commit comments