← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:py3-stable-branch-target-related-branches into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:py3-stable-branch-target-related-branches into launchpad:master.

Commit message:
Stabilize sorting of branch target related branches

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/398783

Tie-break the sort on the branch ID.  This required extending sorted_version_numbers a bit to allow for tie-breaking.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:py3-stable-branch-target-related-branches into launchpad:master.
diff --git a/lib/lp/code/model/branchtarget.py b/lib/lp/code/model/branchtarget.py
index 9c32ad2..2b84a8f 100644
--- a/lib/lp/code/model/branchtarget.py
+++ b/lib/lp/code/model/branchtarget.py
@@ -177,7 +177,7 @@ class PackageBranchTarget(_BaseBranchTarget):
                     distroseries.status != SeriesStatus.OBSOLETE)])
 
         result = sorted_version_numbers(result, key=lambda branch_info: (
-                    getattr(branch_info[1], 'name')))
+            getattr(branch_info[1], 'name'), branch_info[0].id))
 
         if limit_results is not None:
             # We only want the most recent branches
@@ -416,7 +416,7 @@ class ProductBranchTarget(_BaseBranchTarget):
                 pass
 
         result = sorted_version_numbers(result, key=lambda branch_info: (
-                    getattr(branch_info[1], 'name')))
+            getattr(branch_info[1], 'name'), branch_info[0].id))
 
         if limit_results is not None:
             # We only want the most recent branches
diff --git a/lib/lp/services/webapp/sorting.py b/lib/lp/services/webapp/sorting.py
index 052c669..81a907f 100644
--- a/lib/lp/services/webapp/sorting.py
+++ b/lib/lp/services/webapp/sorting.py
@@ -98,10 +98,43 @@ def sorted_version_numbers(sequence, key=_identity):
     bzr-0.9
     foo
 
+    Items in the sequence can also be tuples or lists, allowing for
+    tie-breaking.  In such cases, only the first element in each item is
+    considered as a version.
+
+    >>> bzr_versions = [
+    ...     (series('0.9'), 8), (series('0.9'), 9), (series('0.9'), 10),
+    ...     (series('1.0'), 1)]
+    >>> for version, tiebreak in sorted_version_numbers(
+    ...         bzr_versions, key=lambda item: item[0].name):
+    ...     print(version.name, tiebreak)
+    1.0 1
+    0.9 8
+    0.9 9
+    0.9 10
+
+    >>> bzr_versions = [
+    ...     [series('0.9'), 8], [series('0.9'), 9], [series('0.9'), 10],
+    ...     [series('1.0'), 1]]
+    >>> for version, tiebreak in sorted_version_numbers(
+    ...         bzr_versions, key=lambda item: item[0].name):
+    ...     print(version.name, tiebreak)
+    1.0 1
+    0.9 8
+    0.9 9
+    0.9 10
+
     """
-    return sorted(
-        sequence,
-        key=lambda x: _reversed_number_sort_key(expand_numbers(key(x))))
+    def sort_key(item):
+        k = key(item)
+        if isinstance(k, (tuple, list)):
+            return (
+                (_reversed_number_sort_key(expand_numbers(k[0])),) +
+                tuple(k[1:]))
+        else:
+            return _reversed_number_sort_key(expand_numbers(k))
+
+    return sorted(sequence, key=sort_key)
 
 
 def sorted_dotted_numbers(sequence, key=_identity):