py3: get rid of __cmp__

This commit is contained in:
Kovid Goyal 2019-03-28 11:24:37 +05:30
parent 775ffdee21
commit 57e11977b7
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
7 changed files with 137 additions and 51 deletions

View File

@ -11,7 +11,7 @@ import os, traceback, random, shutil, operator
from io import BytesIO from io import BytesIO
from collections import defaultdict, Set, MutableSet from collections import defaultdict, Set, MutableSet
from functools import wraps, partial from functools import wraps, partial
from polyglot.builtins import iteritems, itervalues, unicode_type, zip, string_or_bytes from polyglot.builtins import iteritems, itervalues, unicode_type, zip, string_or_bytes, cmp
from time import time from time import time
from calibre import isbytestring, as_unicode from calibre import isbytestring, as_unicode
@ -956,14 +956,14 @@ class Cache(object):
class SortKey(object): class SortKey(object):
__slots__ = ('book_id', 'sort_key') __slots__ = 'book_id', 'sort_key'
def __init__(self, book_id): def __init__(self, book_id):
self.book_id = book_id self.book_id = book_id
# Calculate only the first sub-sort key since that will always be used # Calculate only the first sub-sort key since that will always be used
self.sort_key = [key(book_id) if i == 0 else Lazy for i, key in enumerate(sort_key_funcs)] self.sort_key = [key(book_id) if i == 0 else Lazy for i, key in enumerate(sort_key_funcs)]
def __cmp__(self, other): def compare_to_other(self, other):
for i, (order, self_key, other_key) in enumerate(zip(orders, self.sort_key, other.sort_key)): for i, (order, self_key, other_key) in enumerate(zip(orders, self.sort_key, other.sort_key)):
if self_key is Lazy: if self_key is Lazy:
self_key = self.sort_key[i] = sort_key_funcs[i](self.book_id) self_key = self.sort_key[i] = sort_key_funcs[i](self.book_id)
@ -974,6 +974,24 @@ class Cache(object):
return ans * order return ans * order
return 0 return 0
def __eq__(self, other):
return self.compare_to_other(other) == 0
def __ne__(self, other):
return self.compare_to_other(other) != 0
def __lt__(self, other):
return self.compare_to_other(other) < 0
def __le__(self, other):
return self.compare_to_other(other) <= 0
def __gt__(self, other):
return self.compare_to_other(other) > 0
def __ge__(self, other):
return self.compare_to_other(other) >= 0
return sorted(ids_to_sort, key=SortKey) return sorted(ids_to_sort, key=SortKey)
@read_api @read_api

View File

@ -8,13 +8,14 @@ __copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import re, threading import re, threading
from functools import total_ordering
from calibre import browser, random_user_agent from calibre import browser, random_user_agent
from calibre.customize import Plugin from calibre.customize import Plugin
from calibre.ebooks.metadata import check_isbn from calibre.ebooks.metadata import check_isbn
from calibre.ebooks.metadata.author_mapper import cap_author_token from calibre.ebooks.metadata.author_mapper import cap_author_token
from calibre.utils.localization import canonicalize_lang, get_lang from calibre.utils.localization import canonicalize_lang, get_lang
from polyglot.builtins import iteritems from polyglot.builtins import iteritems, cmp
def create_log(ostream=None): def create_log(ostream=None):
@ -41,6 +42,7 @@ def cleanup_title(s):
return s.strip() return s.strip()
@total_ordering
class InternalMetadataCompareKeyGen(object): class InternalMetadataCompareKeyGen(object):
''' '''
@ -86,21 +88,38 @@ class InternalMetadataCompareKeyGen(object):
source_plugin.get_cached_cover_url(mi.identifiers) is None) else 1 source_plugin.get_cached_cover_url(mi.identifiers) is None) else 1
self.base = (same_identifier, has_cover, all_fields, language, exact_title) self.base = (same_identifier, has_cover, all_fields, language, exact_title)
self.comments_len = len(mi.comments.strip() if mi.comments else '') self.comments_len = len((mi.comments or '').strip())
self.extra = (getattr(mi, 'source_relevance', 0), ) self.extra = getattr(mi, 'source_relevance', 0)
def __cmp__(self, other): def compare_to_other(self, other):
result = cmp(self.base, other.base) a = cmp(self.base, other.base)
if result == 0: if a != 0:
# Now prefer results with the longer comments, within 10% return a
cx, cy = self.comments_len, other.comments_len cx, cy = self.comments_len, other.comments_len
if cx and cy:
t = (cx + cy) / 20 t = (cx + cy) / 20
delta = cy - cx delta = cy - cx
if abs(delta) > t: if abs(delta) > t:
result = delta return -1 if delta < 0 else 1
else: return cmp(self.extra, other.extra)
result = cmp(self.extra, other.extra)
return result def __eq__(self, other):
return self.compare_to_other(other) == 0
def __ne__(self, other):
return self.compare_to_other(other) != 0
def __lt__(self, other):
return self.compare_to_other(other) < 0
def __le__(self, other):
return self.compare_to_other(other) <= 0
def __gt__(self, other):
return self.compare_to_other(other) > 0
def __ge__(self, other):
return self.compare_to_other(other) >= 0
# }}} # }}}

View File

@ -6,6 +6,7 @@
import textwrap import textwrap
from collections import OrderedDict from collections import OrderedDict
from functools import partial from functools import partial
from operator import attrgetter
from PyQt5.Qt import ( from PyQt5.Qt import (
QAbstractListModel, QApplication, QDialog, QDialogButtonBox, QFont, QGridLayout, QAbstractListModel, QApplication, QDialog, QDialogButtonBox, QFont, QGridLayout,
@ -104,9 +105,9 @@ class Tweak(object): # {{{
ans = ans.encode('utf-8') ans = ans.encode('utf-8')
return ans return ans
def __cmp__(self, other): @property
return -1 * cmp(self.is_customized, def sort_key(self):
getattr(other, 'is_customized', False)) return 0 if self.is_customized else 1
@property @property
def is_customized(self): def is_customized(self):
@ -190,7 +191,7 @@ class Tweaks(QAbstractListModel, AdaptSQP): # {{{
pos = self.read_tweak(lines, pos, default_tweaks, custom_tweaks) pos = self.read_tweak(lines, pos, default_tweaks, custom_tweaks)
pos += 1 pos += 1
self.tweaks.sort() self.tweaks.sort(key=attrgetter('sort_key'))
default_keys = set(default_tweaks) default_keys = set(default_tweaks)
custom_keys = set(custom_tweaks) custom_keys = set(custom_tweaks)

View File

@ -1113,13 +1113,31 @@ class SortKey(object):
def __init__(self, orders, values): def __init__(self, orders, values):
self.orders, self.values = orders, values self.orders, self.values = orders, values
def __cmp__(self, other): def compare_to_other(self, other):
for i, ascending in enumerate(self.orders): for i, ascending in enumerate(self.orders):
ans = cmp(self.values[i], other.values[i]) ans = cmp(self.values[i], other.values[i])
if ans != 0: if ans != 0:
return ans * ascending return ans * ascending
return 0 return 0
def __eq__(self, other):
return self.compare_to_other(other) == 0
def __ne__(self, other):
return self.compare_to_other(other) != 0
def __lt__(self, other):
return self.compare_to_other(other) < 0
def __le__(self, other):
return self.compare_to_other(other) <= 0
def __gt__(self, other):
return self.compare_to_other(other) > 0
def __ge__(self, other):
return self.compare_to_other(other) >= 0
class SortKeyGenerator(object): class SortKeyGenerator(object):

View File

@ -6,13 +6,17 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
_count = 0
import time, io import time, io
from itertools import count
from calibre import prints from calibre import prints
from calibre.constants import DEBUG from calibre.constants import DEBUG
from polyglot.queue import Queue, Empty from polyglot.queue import Queue, Empty
from polyglot.builtins import cmp
job_counter = count()
class BaseJob(object): class BaseJob(object):
@ -22,10 +26,7 @@ class BaseJob(object):
FINISHED = 2 FINISHED = 2
def __init__(self, description, done=lambda x: x): def __init__(self, description, done=lambda x: x):
global _count self.id = next(job_counter)
_count += 1
self.id = _count
self.description = description self.description = description
self.done = done self.done = done
self.done2 = None self.done2 = None
@ -125,22 +126,36 @@ class BaseJob(object):
def is_running(self): def is_running(self):
return self.is_started and not self.is_finished return self.is_started and not self.is_finished
def __cmp__(self, other): def __eq__(self, other):
if self.is_finished == other.is_finished: return self is other
if self.start_time is None:
if other.start_time is None: # Both waiting
return cmp(other.id, self.id)
else:
return 1
else:
if other.start_time is None:
return -1
else: # Both running
return cmp(other.start_time, self.start_time)
else: def __ne__(self, other):
return self is not other
def __lt__(self, other):
return self.compare_to_other(other) < 0
def __le__(self, other):
return self.compare_to_other(other) <= 0
def __gt__(self, other):
return self.compare_to_other(other) > 0
def __ge__(self, other):
return self.compare_to_other(other) >= 0
def compare_to_other(self, other):
if self.is_finished != other.is_finished:
return 1 if self.is_finished else -1 return 1 if self.is_finished else -1
return 0
if self.start_time is None:
if other.start_time is None: # Both waiting
return cmp(other.id, self.id)
return 1
if other.start_time is None:
return -1
# Both running
return cmp((other.start_time, id(other)), (self.start_time, id(self)))
@property @property
def log_file(self): def log_file(self):

View File

@ -7,6 +7,7 @@ __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import copy, zipfile import copy, zipfile
from functools import total_ordering
from PyQt5.Qt import QAbstractItemModel, Qt, QColor, QFont, QIcon, \ from PyQt5.Qt import QAbstractItemModel, Qt, QColor, QFont, QIcon, \
QModelIndex, pyqtSignal, QPixmap QModelIndex, pyqtSignal, QPixmap
@ -18,6 +19,8 @@ from calibre.web.feeds.recipes.collection import \
SchedulerConfig, download_builtin_recipe, update_custom_recipe, \ SchedulerConfig, download_builtin_recipe, update_custom_recipe, \
update_custom_recipes, add_custom_recipe, add_custom_recipes, \ update_custom_recipes, add_custom_recipe, add_custom_recipes, \
remove_custom_recipe, get_custom_recipe, get_builtin_recipe remove_custom_recipe, get_custom_recipe, get_builtin_recipe
from calibre import force_unicode
from calibre.utils.icu import primary_sort_key
from calibre.utils.search_query_parser import ParseException from calibre.utils.search_query_parser import ParseException
from polyglot.builtins import iteritems, unicode_type from polyglot.builtins import iteritems, unicode_type
@ -59,12 +62,19 @@ class NewsTreeItem(object):
child.parent = None child.parent = None
@total_ordering
class NewsCategory(NewsTreeItem): class NewsCategory(NewsTreeItem):
def __init__(self, category, builtin, custom, scheduler_config, parent): def __init__(self, category, builtin, custom, scheduler_config, parent):
NewsTreeItem.__init__(self, builtin, custom, scheduler_config, parent) NewsTreeItem.__init__(self, builtin, custom, scheduler_config, parent)
self.category = category self.category = category
self.cdata = get_language(self.category) self.cdata = get_language(self.category)
if self.category == _('Scheduled'):
self.sortq = 0, ''
elif self.category == _('Custom'):
self.sortq = 1, ''
else:
self.sortq = 2, self.cdata
self.bold_font = QFont() self.bold_font = QFont()
self.bold_font.setBold(True) self.bold_font.setBold(True)
self.bold_font = (self.bold_font) self.bold_font = (self.bold_font)
@ -81,25 +91,23 @@ class NewsCategory(NewsTreeItem):
def flags(self): def flags(self):
return Qt.ItemIsEnabled return Qt.ItemIsEnabled
def __cmp__(self, other): def __eq__(self, other):
def decorate(x): return self.cdata == other.cdata
if x == _('Scheduled'):
x = '0' + x
elif x == _('Custom'):
x = '1' + x
else:
x = '2' + x
return x
return cmp(decorate(self.cdata), decorate(getattr(other, 'cdata', ''))) def __lt__(self, other):
return self.sortq < getattr(other, 'sortq', (3, ''))
@total_ordering
class NewsItem(NewsTreeItem): class NewsItem(NewsTreeItem):
def __init__(self, urn, title, default_icon, custom_icon, favicons, zf, def __init__(self, urn, title, default_icon, custom_icon, favicons, zf,
builtin, custom, scheduler_config, parent): builtin, custom, scheduler_config, parent):
NewsTreeItem.__init__(self, builtin, custom, scheduler_config, parent) NewsTreeItem.__init__(self, builtin, custom, scheduler_config, parent)
self.urn, self.title = urn, title self.urn, self.title = urn, title
if isinstance(self.title, bytes):
self.title = force_unicode(self.title)
self.sortq = primary_sort_key(self.title)
self.icon = self.default_icon = None self.icon = self.default_icon = None
self.default_icon = default_icon self.default_icon = default_icon
self.favicons, self.zf = favicons, zf self.favicons, self.zf = favicons, zf
@ -126,8 +134,11 @@ class NewsItem(NewsTreeItem):
return self.icon return self.icon
return None return None
def __cmp__(self, other): def __eq__(self, other):
return cmp(self.title.lower(), getattr(other, 'title', '').lower()) return self.urn == other.urn
def __lt__(self, other):
return self.sortq < other.sortq
class AdaptSQP(SearchQueryParser): class AdaptSQP(SearchQueryParser):

View File

@ -56,6 +56,9 @@ if is_py3:
code = compile(code, f.name, 'exec') code = compile(code, f.name, 'exec')
exec(code, ctx) exec(code, ctx)
def cmp(a, b):
return (a > b) - (a < b)
else: else:
exec("""def reraise(tp, value, tb=None): exec("""def reraise(tp, value, tb=None):
try: try:
@ -74,6 +77,7 @@ else:
long_type = long long_type = long
exec_path = execfile exec_path = execfile
raw_input = builtins.raw_input raw_input = builtins.raw_input
cmp = builtins.cmp
def iteritems(d): def iteritems(d):
return d.iteritems() return d.iteritems()