@@ -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