@@ -705,7 +705,7 @@ class Package(PackageURLMixin):
705705 "indicate greater vulnerability risk for the package." ,
706706 )
707707
708- version_rank = models .FloatField (
708+ version_rank = models .IntegerField (
709709 help_text = "Rank of the version to support ordering by version. Rank "
710710 "zero means the rank has not been defined yet" ,
711711 default = 0 ,
@@ -759,73 +759,19 @@ def calculate_version_rank(self):
759759 `version_rank` values and are closest to this package in terms of version order.
760760 """
761761
762- if self .version_rank > 0 :
763- return self .version_rank
764-
765762 group_packages = Package .objects .filter (
766763 type = self .type ,
767764 namespace = self .namespace ,
768765 name = self .name ,
769766 )
770767
771- sorted_packages = sorted (group_packages , key = lambda p : version_class (p .version ))
772-
773- if all (p .version_rank == 0 for p in group_packages ):
768+ if any (p .version_rank == 0 for p in group_packages ):
769+ sorted_packages = sorted (group_packages , key = lambda p : self .version_class (p .version ))
774770 for rank , package in enumerate (sorted_packages , start = 1 ):
775771 package .version_rank = rank
776772 Package .objects .bulk_update (sorted_packages , fields = ["version_rank" ])
777773 return self .version_rank
778774
779- packages_with_zero_vesion_rank = group_packages .filter (version_rank = 0 )
780- sorted_packages = sorted (group_packages , key = lambda p : version_class (p .version ))
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
828-
829775 @property
830776 def affected_by (self ):
831777 """
0 commit comments