Mercurial > hg
changeset 30685:95325386cd1a
exchange: use rich class for sorting clone bundle entries
Python 3 removed the "cmp" argument from sorted(). Custom sorting in
Python 3 must be implemented with the dunder comparison methods on
types and/or with a "key" function.
This patch converts our custom "cmp" function to a custom type.
The implementation is very similar to functools.cmp_to_key(). However,
cmp_to_key() doesn't exist in Python 2, so we can't use it.
This was the only use of the "cmp" argument to sorted() in the code
base.
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Mon, 26 Dec 2016 12:11:29 -0700 |
parents | 0064a1eb28e2 |
children | 8352c42a0a0d |
files | mercurial/exchange.py |
diffstat | 1 files changed, 41 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/exchange.py Mon Dec 26 00:02:42 2016 +0000 +++ b/mercurial/exchange.py Mon Dec 26 12:11:29 2016 -0700 @@ -1902,18 +1902,22 @@ return newentries -def sortclonebundleentries(ui, entries): - prefers = ui.configlist('ui', 'clonebundleprefers', default=[]) - if not prefers: - return list(entries) +class clonebundleentry(object): + """Represents an item in a clone bundles manifest. + + This rich class is needed to support sorting since sorted() in Python 3 + doesn't support ``cmp`` and our comparison is complex enough that ``key=`` + won't work. + """ - prefers = [p.split('=', 1) for p in prefers] + def __init__(self, value, prefers): + self.value = value + self.prefers = prefers - # Our sort function. - def compareentry(a, b): - for prefkey, prefvalue in prefers: - avalue = a.get(prefkey) - bvalue = b.get(prefkey) + def _cmp(self, other): + for prefkey, prefvalue in self.prefers: + avalue = self.value.get(prefkey) + bvalue = other.value.get(prefkey) # Special case for b missing attribute and a matches exactly. if avalue is not None and bvalue is None and avalue == prefvalue: @@ -1944,7 +1948,33 @@ # back to index order. return 0 - return sorted(entries, cmp=compareentry) + def __lt__(self, other): + return self._cmp(other) < 0 + + def __gt__(self, other): + return self._cmp(other) > 0 + + def __eq__(self, other): + return self._cmp(other) == 0 + + def __le__(self, other): + return self._cmp(other) <= 0 + + def __ge__(self, other): + return self._cmp(other) >= 0 + + def __ne__(self, other): + return self._cmp(other) != 0 + +def sortclonebundleentries(ui, entries): + prefers = ui.configlist('ui', 'clonebundleprefers', default=[]) + if not prefers: + return list(entries) + + prefers = [p.split('=', 1) for p in prefers] + + items = sorted(clonebundleentry(v, prefers) for v in entries) + return [i.value for i in items] def trypullbundlefromurl(ui, repo, url): """Attempt to apply a bundle from a URL."""