py3: Dont use MethodType as it is incompatible in python3

This commit is contained in:
Kovid Goyal 2019-04-01 20:24:17 +05:30
parent 9b3e525610
commit 3cc148dd6e
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 51 additions and 64 deletions

View File

@ -6,7 +6,7 @@ from __future__ import (unicode_literals, division, absolute_import,
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
import os, traceback, types import os, traceback
from polyglot.builtins import iteritems, zip from polyglot.builtins import iteritems, zip
from calibre import force_unicode, isbytestring from calibre import force_unicode, isbytestring
@ -750,8 +750,6 @@ class LibraryDatabase(object):
# }}} # }}}
MT = lambda func: types.MethodType(func, None, LibraryDatabase)
# Legacy getter API {{{ # Legacy getter API {{{
for prop in ('author_sort', 'authors', 'comment', 'comments', 'publisher', 'max_size', for prop in ('author_sort', 'authors', 'comment', 'comments', 'publisher', 'max_size',
'rating', 'series', 'series_index', 'tags', 'title', 'title_sort', 'rating', 'series', 'series_index', 'tags', 'title', 'title_sort',
@ -763,7 +761,7 @@ for prop in ('author_sort', 'authors', 'comment', 'comments', 'publisher', 'max_
def func(self, index, index_is_id=False): def func(self, index, index_is_id=False):
return self.get_property(index, index_is_id=index_is_id, loc=self.FIELD_MAP[fm]) return self.get_property(index, index_is_id=index_is_id, loc=self.FIELD_MAP[fm])
return func return func
setattr(LibraryDatabase, prop, MT(getter(prop))) setattr(LibraryDatabase, prop, getter(prop))
for prop in ('series', 'publisher'): for prop in ('series', 'publisher'):
def getter(field): def getter(field):
@ -775,22 +773,19 @@ for prop in ('series', 'publisher'):
except IndexError: except IndexError:
pass pass
return func return func
setattr(LibraryDatabase, prop + '_id', MT(getter(prop))) setattr(LibraryDatabase, prop + '_id', getter(prop))
LibraryDatabase.format_hash = MT(lambda self, book_id, fmt:self.new_api.format_hash(book_id, fmt)) LibraryDatabase.format_hash = lambda self, book_id, fmt:self.new_api.format_hash(book_id, fmt)
LibraryDatabase.index = MT(lambda self, book_id, cache=False:self.data.id_to_index(book_id)) LibraryDatabase.index = lambda self, book_id, cache=False:self.data.id_to_index(book_id)
LibraryDatabase.has_cover = MT(lambda self, book_id:self.new_api.field_for('cover', book_id)) LibraryDatabase.has_cover = lambda self, book_id:self.new_api.field_for('cover', book_id)
LibraryDatabase.get_tags = MT(lambda self, book_id:set(self.new_api.field_for('tags', book_id))) LibraryDatabase.get_tags = lambda self, book_id:set(self.new_api.field_for('tags', book_id))
LibraryDatabase.get_categories = MT(lambda self, sort='name', ids=None:self.new_api.get_categories(sort=sort, book_ids=ids)) LibraryDatabase.get_categories = lambda self, sort='name', ids=None:self.new_api.get_categories(sort=sort, book_ids=ids)
LibraryDatabase.get_identifiers = MT( LibraryDatabase.get_identifiers = lambda self, index, index_is_id=False: self.new_api.field_for('identifiers', index if index_is_id else self.id(index))
lambda self, index, index_is_id=False: self.new_api.field_for('identifiers', index if index_is_id else self.id(index))) LibraryDatabase.isbn = lambda self, index, index_is_id=False: self.get_identifiers(index, index_is_id=index_is_id).get('isbn', None)
LibraryDatabase.isbn = MT( LibraryDatabase.get_books_for_category = lambda self, category, id_:self.new_api.get_books_for_category(category, id_)
lambda self, index, index_is_id=False: self.get_identifiers(index, index_is_id=index_is_id).get('isbn', None)) LibraryDatabase.get_data_as_dict = get_data_as_dict
LibraryDatabase.get_books_for_category = MT( LibraryDatabase.find_identical_books = lambda self, mi:self.new_api.find_identical_books(mi)
lambda self, category, id_:self.new_api.get_books_for_category(category, id_)) LibraryDatabase.get_top_level_move_items = lambda self:self.new_api.get_top_level_move_items()
LibraryDatabase.get_data_as_dict = MT(get_data_as_dict)
LibraryDatabase.find_identical_books = MT(lambda self, mi:self.new_api.find_identical_books(mi))
LibraryDatabase.get_top_level_move_items = MT(lambda self:self.new_api.get_top_level_move_items())
# }}} # }}}
# Legacy setter API {{{ # Legacy setter API {{{
@ -826,7 +821,7 @@ for field in (
self.notify([book_id]) self.notify([book_id])
return ret if field == 'languages' else retval return ret if field == 'languages' else retval
return func return func
setattr(LibraryDatabase, 'set_%s' % field.replace('!', ''), MT(setter(field))) setattr(LibraryDatabase, 'set_%s' % field.replace('!', ''), setter(field))
for field in ('authors', 'tags', 'publisher'): for field in ('authors', 'tags', 'publisher'):
def renamer(field): def renamer(field):
@ -836,10 +831,9 @@ for field in ('authors', 'tags', 'publisher'):
return id_map[old_id] return id_map[old_id]
return func return func
fname = field[:-1] if field in {'tags', 'authors'} else field fname = field[:-1] if field in {'tags', 'authors'} else field
setattr(LibraryDatabase, 'rename_%s' % fname, MT(renamer(field))) setattr(LibraryDatabase, 'rename_%s' % fname, renamer(field))
LibraryDatabase.update_last_modified = MT( LibraryDatabase.update_last_modified = lambda self, book_ids, commit=False, now=None: self.new_api.update_last_modified(book_ids, now=now)
lambda self, book_ids, commit=False, now=None: self.new_api.update_last_modified(book_ids, now=now))
# }}} # }}}
@ -850,23 +844,21 @@ for field in ('authors', 'tags', 'publisher', 'series'):
return self.new_api.all_field_names(field) return self.new_api.all_field_names(field)
return func return func
name = field[:-1] if field in {'authors', 'tags'} else field name = field[:-1] if field in {'authors', 'tags'} else field
setattr(LibraryDatabase, 'all_%s_names' % name, MT(getter(field))) setattr(LibraryDatabase, 'all_%s_names' % name, getter(field))
LibraryDatabase.all_formats = MT(lambda self:self.new_api.all_field_names('formats')) LibraryDatabase.all_formats = lambda self:self.new_api.all_field_names('formats')
LibraryDatabase.all_custom = MT(lambda self, label=None, num=None:self.new_api.all_field_names(self.custom_field_name(label, num))) LibraryDatabase.all_custom = lambda self, label=None, num=None:self.new_api.all_field_names(self.custom_field_name(label, num))
for func, field in iteritems({'all_authors':'authors', 'all_titles':'title', 'all_tags2':'tags', 'all_series':'series', 'all_publishers':'publisher'}): for func, field in iteritems({'all_authors':'authors', 'all_titles':'title', 'all_tags2':'tags', 'all_series':'series', 'all_publishers':'publisher'}):
def getter(field): def getter(field):
def func(self): def func(self):
return self.field_id_map(field) return self.field_id_map(field)
return func return func
setattr(LibraryDatabase, func, MT(getter(field))) setattr(LibraryDatabase, func, getter(field))
LibraryDatabase.all_tags = MT(lambda self: list(self.all_tag_names())) LibraryDatabase.all_tags = lambda self: list(self.all_tag_names())
LibraryDatabase.get_all_identifier_types = MT(lambda self: list(self.new_api.fields['identifiers'].table.all_identifier_types())) LibraryDatabase.get_all_identifier_types = lambda self: list(self.new_api.fields['identifiers'].table.all_identifier_types())
LibraryDatabase.get_authors_with_ids = MT( LibraryDatabase.get_authors_with_ids = lambda self: [[aid, adata['name'], adata['sort'], adata['link']] for aid, adata in iteritems(self.new_api.author_data())]
lambda self: [[aid, adata['name'], adata['sort'], adata['link']] for aid, adata in iteritems(self.new_api.author_data())]) LibraryDatabase.get_author_id = lambda self, author: {icu_lower(v):k for k, v in iteritems(self.new_api.get_id_map('authors'))}.get(icu_lower(author), None)
LibraryDatabase.get_author_id = MT(
lambda self, author: {icu_lower(v):k for k, v in iteritems(self.new_api.get_id_map('authors'))}.get(icu_lower(author), None))
for field in ('tags', 'series', 'publishers', 'ratings', 'languages'): for field in ('tags', 'series', 'publishers', 'ratings', 'languages'):
def getter(field): def getter(field):
@ -875,7 +867,7 @@ for field in ('tags', 'series', 'publishers', 'ratings', 'languages'):
def func(self): def func(self):
return [[tid, tag] for tid, tag in iteritems(self.new_api.get_id_map(fname))] return [[tid, tag] for tid, tag in iteritems(self.new_api.get_id_map(fname))]
return func return func
setattr(LibraryDatabase, 'get_%s_with_ids' % field, MT(getter(field))) setattr(LibraryDatabase, 'get_%s_with_ids' % field, getter(field))
for field in ('author', 'tag', 'series'): for field in ('author', 'tag', 'series'):
def getter(field): def getter(field):
@ -884,7 +876,7 @@ for field in ('author', 'tag', 'series'):
def func(self, item_id): def func(self, item_id):
return self.new_api.get_item_name(field, item_id) return self.new_api.get_item_name(field, item_id)
return func return func
setattr(LibraryDatabase, '%s_name' % field, MT(getter(field))) setattr(LibraryDatabase, '%s_name' % field, getter(field))
for field in ('publisher', 'series', 'tag'): for field in ('publisher', 'series', 'tag'):
def getter(field): def getter(field):
@ -893,7 +885,7 @@ for field in ('publisher', 'series', 'tag'):
def func(self, item_id): def func(self, item_id):
self.new_api.remove_items(fname, (item_id,)) self.new_api.remove_items(fname, (item_id,))
return func return func
setattr(LibraryDatabase, 'delete_%s_using_id' % field, MT(getter(field))) setattr(LibraryDatabase, 'delete_%s_using_id' % field, getter(field))
# }}} # }}}
# Legacy field API {{{ # Legacy field API {{{
@ -915,8 +907,8 @@ for func in (
def meth(self): def meth(self):
return getattr(self.field_metadata, func)() return getattr(self.field_metadata, func)()
return meth return meth
setattr(LibraryDatabase, func.replace('!', ''), MT(getter(func))) setattr(LibraryDatabase, func.replace('!', ''), getter(func))
LibraryDatabase.metadata_for_field = MT(lambda self, field:self.field_metadata.get(field)) LibraryDatabase.metadata_for_field = lambda self, field:self.field_metadata.get(field)
# }}} # }}}
@ -926,21 +918,19 @@ for meth in ('get_next_series_num_for', 'has_book',):
def func(self, x): def func(self, x):
return getattr(self.new_api, meth)(x) return getattr(self.new_api, meth)(x)
return func return func
setattr(LibraryDatabase, meth, MT(getter(meth))) setattr(LibraryDatabase, meth, getter(meth))
LibraryDatabase.saved_search_names = MT(lambda self:self.new_api.saved_search_names()) LibraryDatabase.saved_search_names = lambda self:self.new_api.saved_search_names()
LibraryDatabase.saved_search_lookup = MT(lambda self, x:self.new_api.saved_search_lookup(x)) LibraryDatabase.saved_search_lookup = lambda self, x:self.new_api.saved_search_lookup(x)
LibraryDatabase.saved_search_set_all = MT(lambda self, smap:self.new_api.saved_search_set_all(smap)) LibraryDatabase.saved_search_set_all = lambda self, smap:self.new_api.saved_search_set_all(smap)
LibraryDatabase.saved_search_delete = MT(lambda self, x:self.new_api.saved_search_delete(x)) LibraryDatabase.saved_search_delete = lambda self, x:self.new_api.saved_search_delete(x)
LibraryDatabase.saved_search_add = MT(lambda self, x, y:self.new_api.saved_search_add(x, y)) LibraryDatabase.saved_search_add = lambda self, x, y:self.new_api.saved_search_add(x, y)
LibraryDatabase.saved_search_rename = MT(lambda self, x, y:self.new_api.saved_search_rename(x, y)) LibraryDatabase.saved_search_rename = lambda self, x, y:self.new_api.saved_search_rename(x, y)
LibraryDatabase.commit_dirty_cache = MT(lambda self: self.new_api.commit_dirty_cache()) LibraryDatabase.commit_dirty_cache = lambda self: self.new_api.commit_dirty_cache()
LibraryDatabase.author_sort_from_authors = MT(lambda self, x: self.new_api.author_sort_from_authors(x)) LibraryDatabase.author_sort_from_authors = lambda self, x: self.new_api.author_sort_from_authors(x)
# Cleaning is not required anymore # Cleaning is not required anymore
LibraryDatabase.clean = LibraryDatabase.clean_custom = MT(lambda self:None) LibraryDatabase.clean = LibraryDatabase.clean_custom = lambda self:None
LibraryDatabase.clean_standard_field = MT(lambda self, field, commit=False:None) LibraryDatabase.clean_standard_field = lambda self, field, commit=False:None
# apsw operates in autocommit mode # apsw operates in autocommit mode
LibraryDatabase.commit = MT(lambda self:None) LibraryDatabase.commit = lambda self:None
# }}} # }}}
del MT

View File

@ -7,9 +7,8 @@ __license__ = 'GPL v3'
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
import itertools, operator, os, math import itertools, operator, os, math
from types import MethodType
from threading import Event, Thread from threading import Event, Thread
from functools import wraps, partial from functools import wraps
from textwrap import wrap from textwrap import wrap
from PyQt5.Qt import ( from PyQt5.Qt import (
@ -96,14 +95,14 @@ def event_has_mods(self, event=None):
return mods & Qt.ControlModifier or mods & Qt.ShiftModifier return mods & Qt.ControlModifier or mods & Qt.ShiftModifier
def mousePressEvent(base_class, self, event): def mousePressEvent(self, event):
ep = event.pos() ep = event.pos()
if self.indexAt(ep) in self.selectionModel().selectedIndexes() and \ if self.indexAt(ep) in self.selectionModel().selectedIndexes() and \
event.button() == Qt.LeftButton and not self.event_has_mods(): event.button() == Qt.LeftButton and not self.event_has_mods():
self.drag_start_pos = ep self.drag_start_pos = ep
if hasattr(self, 'handle_mouse_press_event'): if hasattr(self, 'handle_mouse_press_event'):
return self.handle_mouse_press_event(event) return self.handle_mouse_press_event(event)
return base_class.mousePressEvent(self, event) return super(self.__class__, self).mousePressEvent(event)
def drag_icon(self, cover, multiple): def drag_icon(self, cover, multiple):
@ -179,11 +178,11 @@ def drag_data(self):
return drag return drag
def mouseMoveEvent(base_class, self, event): def mouseMoveEvent(self, event):
if not self.drag_allowed: if not self.drag_allowed:
return return
if self.drag_start_pos is None: if self.drag_start_pos is None:
return base_class.mouseMoveEvent(self, event) return super(self.__class__, self).mouseMoveEvent(event)
if self.event_has_mods(): if self.event_has_mods():
self.drag_start_pos = None self.drag_start_pos = None
@ -250,15 +249,12 @@ def paths_from_event(self, event):
def setup_dnd_interface(cls_or_self): def setup_dnd_interface(cls_or_self):
if isinstance(cls_or_self, type): if isinstance(cls_or_self, type):
cls = cls_or_self cls = cls_or_self
base_class = cls.__bases__[0]
fmap = globals() fmap = globals()
for x in ( for x in (
'dragMoveEvent', 'event_has_mods', 'mousePressEvent', 'mouseMoveEvent', 'dragMoveEvent', 'event_has_mods', 'mousePressEvent', 'mouseMoveEvent',
'drag_data', 'drag_icon', 'dragEnterEvent', 'dropEvent', 'paths_from_event'): 'drag_data', 'drag_icon', 'dragEnterEvent', 'dropEvent', 'paths_from_event'):
func = fmap[x] func = fmap[x]
if x in {'mouseMoveEvent', 'mousePressEvent'}: setattr(cls, x, func)
func = partial(func, base_class)
setattr(cls, x, MethodType(func, None, cls))
return cls return cls
else: else:
self = cls_or_self self = cls_or_self

View File

@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en'
The database used to store ebook metadata The database used to store ebook metadata
''' '''
import os, sys, shutil, glob, time, functools, traceback, re, \ import os, sys, shutil, glob, time, functools, traceback, re, \
json, uuid, hashlib, copy, types, numbers json, uuid, hashlib, copy, numbers
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
import threading, random import threading, random
@ -147,11 +147,12 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
def exists_at(cls, path): def exists_at(cls, path):
return path and os.path.exists(os.path.join(path, 'metadata.db')) return path and os.path.exists(os.path.join(path, 'metadata.db'))
get_data_as_dict = get_data_as_dict
def __init__(self, library_path, row_factory=False, default_prefs=None, def __init__(self, library_path, row_factory=False, default_prefs=None,
read_only=False, is_second_db=False, progress_callback=None, read_only=False, is_second_db=False, progress_callback=None,
restore_all_prefs=False): restore_all_prefs=False):
self.is_second_db = is_second_db self.is_second_db = is_second_db
self.get_data_as_dict = types.MethodType(get_data_as_dict, self, LibraryDatabase2)
try: try:
if isbytestring(library_path): if isbytestring(library_path):
library_path = library_path.decode(filesystem_encoding) library_path = library_path.decode(filesystem_encoding)