Skip to content

Commit 176228c

Browse files
committed
Q
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent e32fb72 commit 176228c

File tree

1 file changed

+49
-31
lines changed

1 file changed

+49
-31
lines changed

vulnerabilities/models.py

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -762,51 +762,69 @@ def calculate_version_rank(self):
762762
if self.version_rank > 0:
763763
return self.version_rank
764764

765-
# Determine the version_class for this package's type
766-
version_class = RANGE_CLASS_BY_SCHEMES.get(self.type).version_class
767-
if not version_class:
768-
raise ValueError(f"No version_class defined for package type {self.type}")
769-
770765
group_packages = Package.objects.filter(
771766
type=self.type,
772767
namespace=self.namespace,
773768
name=self.name,
774769
)
775770

776-
# if all packages have version rank 0
771+
sorted_packages = sorted(group_packages, key=lambda p: version_class(p.version))
777772

778773
if all(p.version_rank == 0 for p in group_packages):
779-
sorted_packages = sorted(group_packages, key=lambda p: version_class(p.version))
780774
for rank, package in enumerate(sorted_packages, start=1):
781775
package.version_rank = rank
782776
Package.objects.bulk_update(sorted_packages, fields=["version_rank"])
783777
return self.version_rank
784778

785-
group_packages = group_packages.exclude(version_rank=0)
779+
packages_with_zero_vesion_rank = group_packages.filter(version_rank=0)
786780
sorted_packages = sorted(group_packages, key=lambda p: version_class(p.version))
787-
current_version = version_class(self.version)
788-
789-
lower_package, higher_package = None, None
790-
for package in sorted_packages:
791-
package_version = version_class(package.version)
792-
if package_version < current_version:
793-
lower_package = package
794-
elif package_version > current_version:
795-
higher_package = package
796-
break
797-
798-
if lower_package and higher_package:
799-
# Interpolate rank between neighbors
800-
return (lower_package.version_rank + higher_package.version_rank) / 2
801-
elif lower_package:
802-
# If only lower neighbor exists, assign a rank slightly higher than the lower neighbor
803-
return lower_package.version_rank + 1
804-
elif higher_package:
805-
# If only higher neighbor exists, assign a rank slightly lower than the higher neighbor
806-
return higher_package.version_rank - 1
807-
else:
808-
# No neighbors with version_rank; return default rank (e.g., 0)
809-
return 0
781+
782+
if not packages_with_zero_vesion_rank:
783+
return self.version_rank
784+
785+
for package in packages_with_zero_vesion_rank:
786+
# Instead of interpolating the rank between the two closest neighbors,
787+
788+
# Should not we calculate rank for all packages again, we are using O(n^k) here where k is the number of packages with version_rank = 0
789+
# If we reassign rank to all packages, we can avoid this issue
790+
# It can be done in O(n) time complexity
791+
# Determine the version_class for this package's type
792+
version_class = RANGE_CLASS_BY_SCHEMES.get(package.type).version_class
793+
if not version_class:
794+
raise ValueError(f"No version_class defined for package type {package.type}")
795+
796+
current_version = version_class(package.version)
797+
798+
lower_package, higher_package = None, None
799+
800+
for package in sorted_packages:
801+
package_version = version_class(package.version)
802+
if package_version < current_version:
803+
lower_package = package
804+
elif package_version > current_version:
805+
higher_package = package
806+
break
807+
808+
if lower_package and higher_package:
809+
# Interpolate rank between neighbors
810+
package.version_rank = (
811+
lower_package.version_rank + higher_package.version_rank
812+
) / 2
813+
814+
elif lower_package:
815+
# If only lower neighbor exists, assign a rank slightly higher than the lower neighbor
816+
package.version_rank = lower_package.version_rank + 1
817+
818+
elif higher_package:
819+
# If only higher neighbor exists, assign a rank slightly lower than the higher neighbor
820+
package.version_rank = higher_package.version_rank - 1
821+
822+
else:
823+
# No neighbors with version_rank; return default rank (e.g., 0)
824+
package.version_rank = 0
825+
826+
Package.objects.bulk_update(packages_with_zero_vesion_rank, fields=["version_rank"])
827+
return self.version_rank
810828

811829
@property
812830
def affected_by(self):

0 commit comments

Comments
 (0)