Merge branch 'main' into avm99963-monorail
Merged commit 34d8229ae2b51fb1a15bd208e6fe6185c94f6266
GitOrigin-RevId: 7ee0917f93a577e475f8e09526dd144d245593f4
diff --git a/framework/sorting.py b/framework/sorting.py
index 558044c..2ad4c1c 100644
--- a/framework/sorting.py
+++ b/framework/sorting.py
@@ -1,7 +1,6 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file or at
-# https://developers.google.com/open-source/licenses/bsd
+# Copyright 2016 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
"""Helper functions for sorting lists of project artifacts.
@@ -23,16 +22,16 @@
from __future__ import division
from __future__ import absolute_import
-from functools import total_ordering
+import functools
import settings
-from proto import tracker_pb2
+from mrproto import tracker_pb2
from services import caches
from tracker import tracker_bizobj
from tracker import tracker_constants
-@total_ordering
+@functools.total_ordering
class DescendingValue(object):
"""A wrapper which reverses the sort order of values."""
@@ -149,7 +148,7 @@
art_values_cache.CacheItem(art.issue_id, art_values)
return sort_key
- return sorted(artifacts, key=SortKey)
+ return sorted(artifacts, key=lambda x: Python2Key(SortKey(x)))
def ComputeSortDirectives(config, group_by_spec, sort_spec, tie_breakers=None):
@@ -249,7 +248,7 @@
key_part.extend(value)
else:
key_part.append(value)
- return sorted(key_part)
+ return sorted(key_part, key=Python2Key)
return _MaybeMakeDescending(CombinedAccessor, descending)
@@ -341,7 +340,7 @@
else:
values = [postprocessor(users_by_id[id_or_id_list])]
- return sorted(values) or MAX_STRING
+ return sorted(values) or [MAX_STRING]
return Accessor
@@ -427,10 +426,10 @@
values = base_accessor(art)
if not values:
# Undefined values sort last.
- return MAX_STRING
+ return [MAX_STRING]
indexes = [well_known_value_indexes.get(val, MAX_STRING) for val in values]
- return sorted(indexes)
+ return sorted(indexes, key=Python2Key)
return Accessor
@@ -465,8 +464,8 @@
_SortableApprovalApproverValues(art, approval_fds, users_by_id) +
_SortableLabelValues(art, col_name, well_known_value_indexes))
if not idx_or_lex_list:
- return MAX_STRING # issues with no value sort to the end of the list.
- return sorted(idx_or_lex_list)
+ return [MAX_STRING] # issues with no value sort to the end of the list.
+ return sorted(idx_or_lex_list, key=Python2Key)
return ApproverAccessor
@@ -494,8 +493,8 @@
_SortableFieldValues(art, fd_list, users_by_id, phase_name) +
_SortableLabelValues(art, col_name, well_known_value_indexes))
if not idx_or_lex_list:
- return MAX_STRING # issues with no value sort to the end of the list.
- return sorted(idx_or_lex_list)
+ return [MAX_STRING] # issues with no value sort to the end of the list.
+ return sorted(idx_or_lex_list, key=Python2Key)
return Accessor
@@ -573,3 +572,37 @@
sortable_value_list.append(idx_or_lex)
return sortable_value_list
+
+
+def _Python2Cmp(a, b):
+ """Compares two objects in the Python 2 way.
+
+ In Python 3, comparing two objects of different types raises a TypeError.
+ In Python 2, when you compare two objects of different types, they are
+ generally ordered by their type names, with a few special cases carved
+ out for int/float and str/unicode.
+
+ This comparison function also looks through lists and compares them pairwise.
+ It doesn't do the same for other iterables.
+ """
+ try:
+ # First try comparing the objects directly.
+ # https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons
+ return (a > b) - (a < b)
+ except TypeError:
+ s1, s2 = type(a).__name__, type(b).__name__
+ if not (s1 == 'list' and s2 == 'list'):
+ # If they are different types, compare their type names.
+ return (s1 > s2) - (s1 < s2)
+
+ # If they are both lists, compare their elements pairwise.
+ for x, y in zip(a, b):
+ element_cmp = _Python2Cmp(x, y)
+ if element_cmp != 0:
+ return element_cmp
+
+ # If the lists start with the same elements, compare their lengths.
+ return (len(a) > len(b)) - (len(a) < len(b))
+
+
+Python2Key = functools.cmp_to_key(_Python2Cmp)