diff --git a/setup/parallel_build.py b/setup/parallel_build.py index 0dae90fc26..09c8d80cb2 100644 --- a/setup/parallel_build.py +++ b/setup/parallel_build.py @@ -12,6 +12,7 @@ from functools import partial from contextlib import closing from setup import iswindows +from polyglot.builtins import unicode_type if iswindows: from ctypes import windll, Structure, POINTER, c_size_t @@ -52,7 +53,7 @@ def run_worker(job, decorate=True): try: p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) except Exception as err: - return False, human_text, unicode(err) + return False, human_text, unicode_type(err) stdout, stderr = p.communicate() if stdout: stdout = stdout.decode('utf-8') diff --git a/setup/resources.py b/setup/resources.py index 1554b5551f..e12cd18223 100644 --- a/setup/resources.py +++ b/setup/resources.py @@ -12,7 +12,7 @@ from itertools import chain is_ci = os.environ.get('CI', '').lower() == 'true' from setup import Command, basenames, __appname__, download_securely -from polyglot.builtins import itervalues, iteritems +from polyglot.builtins import codepoint_to_chr, itervalues, iteritems def get_opts_from_parser(parser): @@ -173,7 +173,7 @@ class Kakasi(Command): # {{{ continue if re.match(r"^$",line): continue - pair = re.sub(r'\\u([0-9a-fA-F]{4})', lambda x:unichr(int(x.group(1),16)), line) + pair = re.sub(r'\\u([0-9a-fA-F]{4})', lambda x:codepoint_to_chr(int(x.group(1),16)), line) dic[pair[0]] = pair[1] from calibre.utils.serialize import msgpack_dumps with open(dst, 'wb') as f: diff --git a/setup/translations.py b/setup/translations.py index 5549bffd7f..ac8684d820 100644 --- a/setup/translations.py +++ b/setup/translations.py @@ -13,7 +13,7 @@ from functools import partial from setup import Command, __appname__, __version__, require_git_master, build_cache_dir, edit_file from setup.parallel_build import parallel_check_output -from polyglot.builtins import iteritems +from polyglot.builtins import codepoint_to_chr, iteritems is_ci = os.environ.get('CI', '').lower() == 'true' @@ -82,7 +82,7 @@ class POT(Command): # {{{ ans = [] for lineno, msg in msgs: ans.append('#: %s:%d'%(path, lineno)) - slash = unichr(92) + slash = codepoint_to_chr(92) msg = msg.replace(slash, slash*2).replace('"', r'\"').replace('\n', r'\n').replace('\r', r'\r').replace('\t', r'\t') ans.append('msgid "%s"'%msg) diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index 6665dd38db..879cdced87 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -4,7 +4,7 @@ __copyright__ = '2008, Kovid Goyal ' __docformat__ = 'restructuredtext en' import sys, os, re, time, random, warnings -from polyglot.builtins import builtins +from polyglot.builtins import builtins, codepoint_to_chr, unicode_type builtins.__dict__['dynamic_property'] = lambda func: func(None) from math import floor from functools import partial @@ -77,7 +77,7 @@ def get_types_map(): def to_unicode(raw, encoding='utf-8', errors='strict'): - if isinstance(raw, unicode): + if isinstance(raw, unicode_type): return raw return raw.decode(encoding, errors) @@ -113,7 +113,7 @@ def confirm_config_name(name): _filename_sanitize = re.compile(r'[\xae\0\\|\?\*<":>\+/]') _filename_sanitize_unicode = frozenset([u'\\', u'|', u'?', u'*', u'<', - u'"', u':', u'>', u'+', u'/'] + list(map(unichr, xrange(32)))) + u'"', u':', u'>', u'+', u'/'] + list(map(codepoint_to_chr, xrange(32)))) def sanitize_file_name(name, substitute='_', as_unicode=False): @@ -126,7 +126,7 @@ def sanitize_file_name(name, substitute='_', as_unicode=False): *NOTE:* This function always returns byte strings, not unicode objects. The byte strings are encoded in the filesystem encoding of the platform, or UTF-8. ''' - if isinstance(name, unicode): + if isinstance(name, unicode_type): name = name.encode(filesystem_encoding, 'ignore') one = _filename_sanitize.sub(substitute, name) one = re.sub(r'\s', ' ', one).strip() @@ -198,7 +198,7 @@ def prints(*args, **kwargs): safe_encode = kwargs.get('safe_encode', False) count = 0 for i, arg in enumerate(args): - if isinstance(arg, unicode): + if isinstance(arg, unicode_type): if iswindows: from calibre.utils.terminal import Detect cs = Detect(file) @@ -222,8 +222,8 @@ def prints(*args, **kwargs): try: arg = str(arg) except ValueError: - arg = unicode(arg) - if isinstance(arg, unicode): + arg = unicode_type(arg) + if isinstance(arg, unicode_type): try: arg = arg.encode(enc) except UnicodeEncodeError: @@ -288,7 +288,7 @@ def load_library(name, cdll): def filename_to_utf8(name): '''Return C{name} encoded in utf8. Unhandled characters are replaced. ''' - if isinstance(name, unicode): + if isinstance(name, unicode_type): return name.encode('utf8') codec = 'cp1252' if iswindows else 'utf8' return name.decode(codec, 'replace').encode('utf8') @@ -557,7 +557,7 @@ def strftime(fmt, t=None): else: ans = time.strftime(fmt, t).decode(preferred_encoding, 'replace') if early_year: - ans = ans.replace(u'_early year hack##', unicode(orig_year)) + ans = ans.replace(u'_early year hack##', unicode_type(orig_year)) return ans @@ -669,7 +669,7 @@ def force_unicode(obj, enc=preferred_encoding): def as_unicode(obj, enc=preferred_encoding): if not isbytestring(obj): try: - obj = unicode(obj) + obj = unicode_type(obj) except: try: obj = str(obj) diff --git a/src/calibre/constants.py b/src/calibre/constants.py index 1317ea6873..cff793cd1c 100644 --- a/src/calibre/constants.py +++ b/src/calibre/constants.py @@ -2,12 +2,12 @@ # vim:fileencoding=utf-8 # License: GPLv3 Copyright: 2015, Kovid Goyal from __future__ import print_function -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type import sys, locale, codecs, os, importlib, collections __appname__ = u'calibre' numeric_version = (3, 40, 1) -__version__ = u'.'.join(map(unicode, numeric_version)) +__version__ = u'.'.join(map(unicode_type, numeric_version)) __author__ = u"Kovid Goyal " ''' @@ -300,7 +300,7 @@ def get_portable_base(): def get_unicode_windows_env_var(name): getenv = plugins['winutil'][0].getenv - return getenv(unicode(name)) + return getenv(unicode_type(name)) def get_windows_username(): diff --git a/src/calibre/customize/__init__.py b/src/calibre/customize/__init__.py index 2b9c42e49f..2a6135fae5 100644 --- a/src/calibre/customize/__init__.py +++ b/src/calibre/customize/__init__.py @@ -7,6 +7,7 @@ import os, sys, zipfile, importlib from calibre.constants import numeric_version, iswindows, isosx from calibre.ptempfile import PersistentTemporaryFile +from polyglot.builtins import unicode_type platform = 'linux' if iswindows: @@ -195,7 +196,7 @@ class Plugin(object): # {{{ config_dialog.exec_() if config_dialog.result() == QDialog.Accepted: - sc = unicode(sc.text()).strip() + sc = unicode_type(sc.text()).strip() customize_plugin(self, sc) geom = bytearray(config_dialog.saveGeometry()) diff --git a/src/calibre/customize/builtins.py b/src/calibre/customize/builtins.py index 871f4bf516..bba5b1e83b 100644 --- a/src/calibre/customize/builtins.py +++ b/src/calibre/customize/builtins.py @@ -10,6 +10,7 @@ from calibre.customize import (FileTypePlugin, MetadataReaderPlugin, from calibre.constants import numeric_version from calibre.ebooks.metadata.archive import ArchiveExtract, get_comic_metadata from calibre.ebooks.html.to_zip import HTML2ZIP +from polyglot.builtins import unicode_type plugins = [] @@ -64,23 +65,23 @@ class TXT2TXTZ(FileTypePlugin): images = [] # Textile - for m in re.finditer(unicode(r'(?mu)(?:[\[{])?\!(?:\. )?(?P[^\s(!]+)\s?(?:\(([^\)]+)\))?\!(?::(\S+))?(?:[\]}]|(?=\s|$))'), txt): + for m in re.finditer(unicode_type(r'(?mu)(?:[\[{])?\!(?:\. )?(?P[^\s(!]+)\s?(?:\(([^\)]+)\))?\!(?::(\S+))?(?:[\]}]|(?=\s|$))'), txt): path = m.group('path') if path and not os.path.isabs(path) and guess_type(path)[0] in OEB_IMAGES and os.path.exists(os.path.join(base_dir, path)): images.append(path) # Markdown inline - for m in re.finditer(unicode(r'(?mu)\!\[([^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*)\]\s*\((?P[^\)]*)\)'), txt): # noqa + for m in re.finditer(unicode_type(r'(?mu)\!\[([^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*)\]\s*\((?P[^\)]*)\)'), txt): # noqa path = m.group('path') if path and not os.path.isabs(path) and guess_type(path)[0] in OEB_IMAGES and os.path.exists(os.path.join(base_dir, path)): images.append(path) # Markdown reference refs = {} - for m in re.finditer(unicode(r'(?mu)^(\ ?\ ?\ ?)\[(?P[^\]]*)\]:\s*(?P[^\s]*)$'), txt): + for m in re.finditer(unicode_type(r'(?mu)^(\ ?\ ?\ ?)\[(?P[^\]]*)\]:\s*(?P[^\s]*)$'), txt): if m.group('id') and m.group('path'): refs[m.group('id')] = m.group('path') - for m in re.finditer(unicode(r'(?mu)\!\[([^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*)\]\s*\[(?P[^\]]*)\]'), txt): # noqa + for m in re.finditer(unicode_type(r'(?mu)\!\[([^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*(\[[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*\])*[^\]\[]*)\]\s*\[(?P[^\]]*)\]'), txt): # noqa path = refs.get(m.group('id'), None) if path and not os.path.isabs(path) and guess_type(path)[0] in OEB_IMAGES and os.path.exists(os.path.join(base_dir, path)): images.append(path) diff --git a/src/calibre/customize/conversion.py b/src/calibre/customize/conversion.py index 730f866dec..14fb114cfb 100644 --- a/src/calibre/customize/conversion.py +++ b/src/calibre/customize/conversion.py @@ -6,6 +6,7 @@ import re, os, shutil from calibre import CurrentDir from calibre.customize import Plugin +from polyglot.builtins import unicode_type class ConversionOption(object): @@ -79,7 +80,7 @@ class OptionRecommendation(object): self.option.choices: raise ValueError('OpRec: %s: Recommended value not in choices'% self.option.name) - if not (isinstance(self.recommended_value, (int, float, str, unicode)) or self.recommended_value is None): + if not (isinstance(self.recommended_value, (int, float, str, unicode_type)) or self.recommended_value is None): raise ValueError('OpRec: %s:'%self.option.name + repr( self.recommended_value) + ' is not a string or a number') @@ -340,7 +341,7 @@ class OutputFormatPlugin(Plugin): @property def is_periodical(self): return self.oeb.metadata.publication_type and \ - unicode(self.oeb.metadata.publication_type[0]).startswith('periodical:') + unicode_type(self.oeb.metadata.publication_type[0]).startswith('periodical:') def specialize_options(self, log, opts, input_fmt): ''' diff --git a/src/calibre/customize/zipplugin.py b/src/calibre/customize/zipplugin.py index 3c82c72640..821046b169 100644 --- a/src/calibre/customize/zipplugin.py +++ b/src/calibre/customize/zipplugin.py @@ -2,7 +2,7 @@ # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai from __future__ import (unicode_literals, division, absolute_import, print_function) -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type __license__ = 'GPL v3' __copyright__ = '2011, Kovid Goyal ' @@ -216,7 +216,7 @@ class PluginLoader(object): if ans.minimum_calibre_version > numeric_version: raise InvalidPlugin( 'The plugin at %s needs a version of calibre >= %s' % - (as_unicode(path_to_zip_file), '.'.join(map(unicode, + (as_unicode(path_to_zip_file), '.'.join(map(unicode_type, ans.minimum_calibre_version)))) if platform not in ans.supported_platforms: @@ -231,7 +231,7 @@ class PluginLoader(object): raise def _locate_code(self, zf, path_to_zip_file): - names = [x if isinstance(x, unicode) else x.decode('utf-8') for x in + names = [x if isinstance(x, unicode_type) else x.decode('utf-8') for x in zf.namelist()] names = [x[1:] if x[0] == '/' else x for x in names] diff --git a/src/calibre/db/adding.py b/src/calibre/db/adding.py index 5d4ccfbd3a..44fa239ed5 100644 --- a/src/calibre/db/adding.py +++ b/src/calibre/db/adding.py @@ -8,7 +8,7 @@ __copyright__ = '2013, Kovid Goyal ' import os, time, re from collections import defaultdict -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from contextlib import contextmanager from functools import partial @@ -69,7 +69,7 @@ def metadata_extensions(): # but not actually added) global _metadata_extensions if _metadata_extensions is None: - _metadata_extensions = frozenset(map(unicode, BOOK_EXTENSIONS)) | {'opf'} + _metadata_extensions = frozenset(map(unicode_type, BOOK_EXTENSIONS)) | {'opf'} return _metadata_extensions @@ -143,7 +143,7 @@ def find_books_in_directory(dirpath, single_book_per_directory, compiled_rules=( for path in listdir_impl(dirpath, sort_by_mtime=True): key, ext = splitext(path) if allow_path(path, ext, compiled_rules): - books[icu_lower(key) if isinstance(key, unicode) else key.lower()][ext] = path + books[icu_lower(key) if isinstance(key, unicode_type) else key.lower()][ext] = path for formats in books.itervalues(): if formats_ok(formats): diff --git a/src/calibre/db/backend.py b/src/calibre/db/backend.py index aac1880619..c1d7e6b9b1 100644 --- a/src/calibre/db/backend.py +++ b/src/calibre/db/backend.py @@ -12,7 +12,7 @@ import os, shutil, uuid, json, glob, time, hashlib, errno, sys from functools import partial import apsw -from polyglot.builtins import reraise +from polyglot.builtins import unicode_type, reraise from calibre import isbytestring, force_unicode, prints, as_unicode from calibre.constants import (iswindows, filesystem_encoding, @@ -93,7 +93,7 @@ class DBPrefs(dict): # {{{ dict.__setitem__(self, key, val) def raw_to_object(self, raw): - if not isinstance(raw, unicode): + if not isinstance(raw, unicode_type): raw = raw.decode(preferred_encoding) return json.loads(raw, object_hook=from_json) @@ -561,10 +561,10 @@ class DB(object): prints('found user category case overlap', catmap[uc]) cat = catmap[uc][0] suffix = 1 - while icu_lower((cat + unicode(suffix))) in catmap: + while icu_lower((cat + unicode_type(suffix))) in catmap: suffix += 1 - prints('Renaming user category %s to %s'%(cat, cat+unicode(suffix))) - user_cats[cat + unicode(suffix)] = user_cats[cat] + prints('Renaming user category %s to %s'%(cat, cat+unicode_type(suffix))) + user_cats[cat + unicode_type(suffix)] = user_cats[cat] del user_cats[cat] cats_changed = True if cats_changed: @@ -670,23 +670,23 @@ class DB(object): if d['is_multiple']: if x is None: return [] - if isinstance(x, (str, unicode, bytes)): + if isinstance(x, (str, unicode_type, bytes)): x = x.split(d['multiple_seps']['ui_to_list']) x = [y.strip() for y in x if y.strip()] x = [y.decode(preferred_encoding, 'replace') if not isinstance(y, - unicode) else y for y in x] + unicode_type) else y for y in x] return [u' '.join(y.split()) for y in x] else: - return x if x is None or isinstance(x, unicode) else \ + return x if x is None or isinstance(x, unicode_type) else \ x.decode(preferred_encoding, 'replace') def adapt_datetime(x, d): - if isinstance(x, (str, unicode, bytes)): + if isinstance(x, (str, unicode_type, bytes)): x = parse_date(x, assume_utc=False, as_utc=False) return x def adapt_bool(x, d): - if isinstance(x, (str, unicode, bytes)): + if isinstance(x, (str, unicode_type, bytes)): x = x.lower() if x == 'true': x = True @@ -707,7 +707,7 @@ class DB(object): def adapt_number(x, d): if x is None: return None - if isinstance(x, (str, unicode, bytes)): + if isinstance(x, (str, unicode_type, bytes)): if x.lower() == 'none': return None if d['datatype'] == 'int': @@ -1239,7 +1239,7 @@ class DB(object): return self._library_id_ def fset(self, val): - self._library_id_ = unicode(val) + self._library_id_ = unicode_type(val) self.execute(''' DELETE FROM library_id; INSERT INTO library_id (uuid) VALUES (?); @@ -1715,7 +1715,7 @@ class DB(object): [(book_id, fmt.upper()) for book_id in book_ids]) def set_conversion_options(self, options, fmt): - options = [(book_id, fmt.upper(), buffer(pickle_binary_string(data.encode('utf-8') if isinstance(data, unicode) else data))) + options = [(book_id, fmt.upper(), buffer(pickle_binary_string(data.encode('utf-8') if isinstance(data, unicode_type) else data))) for book_id, data in options.iteritems()] self.executemany('INSERT OR REPLACE INTO conversion_options(book,format,data) VALUES (?,?,?)', options) @@ -1754,7 +1754,7 @@ class DB(object): copyfile_using_links(src, dest, dest_is_dir=False) old_files.add(src) x = path_map[x] - if not isinstance(x, unicode): + if not isinstance(x, unicode_type): x = x.decode(filesystem_encoding, 'replace') progress(x, i+1, total) diff --git a/src/calibre/db/cache.py b/src/calibre/db/cache.py index 50de272d47..b1cd08af24 100644 --- a/src/calibre/db/cache.py +++ b/src/calibre/db/cache.py @@ -11,7 +11,7 @@ import os, traceback, random, shutil, operator from io import BytesIO from collections import defaultdict, Set, MutableSet from functools import wraps, partial -from polyglot.builtins import zip +from polyglot.builtins import unicode_type, zip from time import time from calibre import isbytestring, as_unicode @@ -528,14 +528,14 @@ class Cache(object): @read_api def get_item_id(self, field, item_name): ' Return the item id for item_name (case-insensitive) ' - rmap = {icu_lower(v) if isinstance(v, unicode) else v:k for k, v in self.fields[field].table.id_map.iteritems()} - return rmap.get(icu_lower(item_name) if isinstance(item_name, unicode) else item_name, None) + rmap = {icu_lower(v) if isinstance(v, unicode_type) else v:k for k, v in self.fields[field].table.id_map.iteritems()} + return rmap.get(icu_lower(item_name) if isinstance(item_name, unicode_type) else item_name, None) @read_api def get_item_ids(self, field, item_names): ' Return the item id for item_name (case-insensitive) ' - rmap = {icu_lower(v) if isinstance(v, unicode) else v:k for k, v in self.fields[field].table.id_map.iteritems()} - return {name:rmap.get(icu_lower(name) if isinstance(name, unicode) else name, None) for name in item_names} + rmap = {icu_lower(v) if isinstance(v, unicode_type) else v:k for k, v in self.fields[field].table.id_map.iteritems()} + return {name:rmap.get(icu_lower(name) if isinstance(name, unicode_type) else name, None) for name in item_names} @read_api def author_data(self, author_ids=None): diff --git a/src/calibre/db/categories.py b/src/calibre/db/categories.py index 22bb84694e..377eab54ba 100644 --- a/src/calibre/db/categories.py +++ b/src/calibre/db/categories.py @@ -9,7 +9,7 @@ __docformat__ = 'restructuredtext en' import copy from functools import partial -from polyglot.builtins import map +from polyglot.builtins import unicode_type, map from calibre.ebooks.metadata import author_to_author_sort from calibre.utils.config_base import tweaks @@ -47,7 +47,7 @@ class Tag(object): return u'%s:%s:%s:%s:%s'%(self.name, self.count, self.id, self.state, self.category) def __str__(self): - return unicode(self).encode('utf-8') + return unicode_type(self).encode('utf-8') def __repr__(self): return str(self) @@ -101,8 +101,8 @@ def clean_user_categories(dbcache): if len(comps) == 0: i = 1 while True: - if unicode(i) not in user_cats: - new_cats[unicode(i)] = user_cats[k] + if unicode_type(i) not in user_cats: + new_cats[unicode_type(i)] = user_cats[k] break i += 1 else: diff --git a/src/calibre/db/cli/cmd_list_categories.py b/src/calibre/db/cli/cmd_list_categories.py index 5fc526de35..0280455f66 100644 --- a/src/calibre/db/cli/cmd_list_categories.py +++ b/src/calibre/db/cli/cmd_list_categories.py @@ -10,6 +10,7 @@ from textwrap import TextWrapper from io import BytesIO from calibre import prints +from polyglot.builtins import unicode_type readonly = True version = 0 # change this if you change signature of implementation() @@ -79,7 +80,7 @@ def do_list(fields, data, opts): widths = list(map(lambda x: 0, fields)) for i in data: for j, field in enumerate(fields): - widths[j] = max(widths[j], max(len(field), len(unicode(i[field])))) + widths[j] = max(widths[j], max(len(field), len(unicode_type(i[field])))) screen_width = geometry()[0] if not screen_width: @@ -110,7 +111,7 @@ def do_list(fields, data, opts): for record in data: text = [ - wrappers[i].wrap(unicode(record[field])) + wrappers[i].wrap(unicode_type(record[field])) for i, field in enumerate(fields) ] lines = max(map(len, text)) @@ -129,7 +130,7 @@ def do_csv(fields, data, opts): for d in data: row = [d[f] for f in fields] csv_print.writerow([ - x if isinstance(x, bytes) else unicode(x).encode('utf-8') for x in row + x if isinstance(x, bytes) else unicode_type(x).encode('utf-8') for x in row ]) print(buf.getvalue()) @@ -164,11 +165,11 @@ def main(opts, args, dbctx): is_rating = category_metadata(category)['datatype'] == 'rating' for tag in category_data[category]: if is_rating: - tag.name = unicode(len(tag.name)) + tag.name = unicode_type(len(tag.name)) data.append({ 'category': category, 'tag_name': tag.name, - 'count': unicode(tag.count), + 'count': unicode_type(tag.count), 'rating': fmtr(tag.avg_rating), }) else: @@ -176,7 +177,7 @@ def main(opts, args, dbctx): data.append({ 'category': category, 'tag_name': _('CATEGORY ITEMS'), - 'count': unicode(len(category_data[category])), + 'count': unicode_type(len(category_data[category])), 'rating': '' }) diff --git a/src/calibre/db/cli/cmd_set_metadata.py b/src/calibre/db/cli/cmd_set_metadata.py index 89a19a1ac0..18a09bafb9 100644 --- a/src/calibre/db/cli/cmd_set_metadata.py +++ b/src/calibre/db/cli/cmd_set_metadata.py @@ -11,6 +11,7 @@ from calibre.ebooks.metadata.book.base import field_from_string from calibre.ebooks.metadata.book.serialize import read_cover from calibre.ebooks.metadata.opf import get_metadata from calibre.srv.changes import metadata +from polyglot.builtins import unicode_type readonly = False version = 0 # change this if you change signature of implementation() @@ -181,5 +182,5 @@ def main(opts, args, dbctx): if not final_mi: raise SystemExit(_('No book with id: %s in the database') % book_id) - prints(unicode(final_mi)) + prints(unicode_type(final_mi)) return 0 diff --git a/src/calibre/db/cli/cmd_show_metadata.py b/src/calibre/db/cli/cmd_show_metadata.py index 8bba0688ba..a0a84f71d4 100644 --- a/src/calibre/db/cli/cmd_show_metadata.py +++ b/src/calibre/db/cli/cmd_show_metadata.py @@ -9,6 +9,7 @@ import sys from calibre import prints from calibre.ebooks.metadata.opf2 import OPFCreator +from polyglot.builtins import unicode_type readonly = True version = 0 # change this if you change signature of implementation() @@ -52,6 +53,6 @@ def main(opts, args, dbctx): mi = OPFCreator(os.getcwdu(), mi) mi.render(sys.stdout) else: - prints(unicode(mi)) + prints(unicode_type(mi)) return 0 diff --git a/src/calibre/db/lazy.py b/src/calibre/db/lazy.py index 25ea870ba8..79c552d8db 100644 --- a/src/calibre/db/lazy.py +++ b/src/calibre/db/lazy.py @@ -15,6 +15,7 @@ from copy import deepcopy from calibre.ebooks.metadata.book.base import Metadata, SIMPLE_GET, TOP_LEVEL_IDENTIFIERS, NULL_VALUES, ALL_METADATA_FIELDS from calibre.ebooks.metadata.book.formatter import SafeFormat from calibre.utils.date import utcnow +from polyglot.builtins import unicode_type # Lazy format metadata retrieval {{{ ''' @@ -46,7 +47,7 @@ class MutableBase(object): @resolved def __unicode__(self): - return unicode(self._values) + return unicode_type(self._values) @resolved def __len__(self): diff --git a/src/calibre/db/schema_upgrades.py b/src/calibre/db/schema_upgrades.py index decb6278bc..7ad9d2d7c9 100644 --- a/src/calibre/db/schema_upgrades.py +++ b/src/calibre/db/schema_upgrades.py @@ -11,6 +11,7 @@ import os from calibre import prints from calibre.utils.date import isoformat, DEFAULT_DATE +from polyglot.builtins import unicode_type class SchemaUpgrade(object): @@ -601,7 +602,7 @@ class SchemaUpgrade(object): id_ = str(id_) fname = custom_recipe_filename(id_, title) custom_recipes[id_] = (title, fname) - if isinstance(script, unicode): + if isinstance(script, unicode_type): script = script.encode('utf-8') with open(os.path.join(bdir, fname), 'wb') as f: f.write(script) diff --git a/src/calibre/db/search.py b/src/calibre/db/search.py index 947429d2de..175cd36d6e 100644 --- a/src/calibre/db/search.py +++ b/src/calibre/db/search.py @@ -19,6 +19,7 @@ from calibre.utils.date import parse_date, UNDEFINED_DATE, now, dt_as_local from calibre.utils.icu import primary_contains, sort_key from calibre.utils.localization import lang_map, canonicalize_lang from calibre.utils.search_query_parser import SearchQueryParser, ParseException +from polyglot.builtins import unicode_type CONTAINS_MATCH = 0 EQUALS_MATCH = 1 @@ -148,7 +149,7 @@ class DateSearch(object): # {{{ if query == 'false': for v, book_ids in field_iter(): - if isinstance(v, (str, unicode)): + if isinstance(v, (str, unicode_type)): v = parse_date(v) if v is None or v <= UNDEFINED_DATE: matches |= book_ids @@ -156,7 +157,7 @@ class DateSearch(object): # {{{ if query == 'true': for v, book_ids in field_iter(): - if isinstance(v, (str, unicode)): + if isinstance(v, (str, unicode_type)): v = parse_date(v) if v is not None and v > UNDEFINED_DATE: matches |= book_ids @@ -198,7 +199,7 @@ class DateSearch(object): # {{{ field_count = query.count('/') + 1 for v, book_ids in field_iter(): - if isinstance(v, (str, unicode)): + if isinstance(v, (str, unicode_type)): v = parse_date(v) if v is not None and relop(dt_as_local(v), qd, field_count): matches |= book_ids @@ -407,7 +408,7 @@ class SavedSearchQueries(object): # {{{ return self._db() def force_unicode(self, x): - if not isinstance(x, unicode): + if not isinstance(x, unicode_type): x = x.decode(preferred_encoding, 'replace') return x diff --git a/src/calibre/db/utils.py b/src/calibre/db/utils.py index b60d0e9420..99f281ad59 100644 --- a/src/calibre/db/utils.py +++ b/src/calibre/db/utils.py @@ -9,7 +9,7 @@ __copyright__ = '2013, Kovid Goyal ' import os, errno, cPickle, sys, re from locale import localeconv from collections import OrderedDict, namedtuple -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from threading import Lock from calibre import as_unicode, prints @@ -19,7 +19,7 @@ from calibre.utils.localization import canonicalize_lang def force_to_bool(val): - if isinstance(val, (str, unicode)): + if isinstance(val, (str, unicode_type)): try: val = icu_lower(val) if not val: diff --git a/src/calibre/db/view.py b/src/calibre/db/view.py index ebe04aaac7..585d84d6cd 100644 --- a/src/calibre/db/view.py +++ b/src/calibre/db/view.py @@ -10,7 +10,7 @@ __docformat__ = 'restructuredtext en' import weakref, operator from functools import partial from itertools import izip, imap -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from calibre.ebooks.metadata import title_sort from calibre.utils.config_base import tweaks, prefs @@ -374,7 +374,7 @@ class View(object): self.marked_ids = dict.fromkeys(id_dict, u'true') else: # Ensure that all the items in the dict are text - self.marked_ids = dict(izip(id_dict.iterkeys(), imap(unicode, + self.marked_ids = dict(izip(id_dict.iterkeys(), imap(unicode_type, id_dict.itervalues()))) # This invalidates all searches in the cache even though the cache may # be shared by multiple views. This is not ideal, but... @@ -432,4 +432,3 @@ class View(object): self._map_filtered = ids + self._map_filtered if prefs['mark_new_books']: self.toggle_marked_ids(ids) - diff --git a/src/calibre/db/write.py b/src/calibre/db/write.py index 3c7e09e24f..dc8caace86 100644 --- a/src/calibre/db/write.py +++ b/src/calibre/db/write.py @@ -10,18 +10,15 @@ __docformat__ = 'restructuredtext en' import re from functools import partial from datetime import datetime -from polyglot.builtins import zip +from polyglot.builtins import unicode_type, zip -from calibre.constants import preferred_encoding, ispy3 +from calibre.constants import preferred_encoding from calibre.ebooks.metadata import author_to_author_sort, title_sort from calibre.utils.date import ( parse_only_date, parse_date, UNDEFINED_DATE, isoformat, is_date_undefined) from calibre.utils.localization import canonicalize_lang from calibre.utils.icu import strcmp -if ispy3: - unicode = str - # Convert data into values suitable for the db {{{ @@ -32,7 +29,7 @@ def sqlite_datetime(x): def single_text(x): if x is None: return x - if not isinstance(x, unicode): + if not isinstance(x, unicode_type): x = x.decode(preferred_encoding, 'replace') x = x.strip() return x if x else None @@ -60,7 +57,7 @@ def multiple_text(sep, ui_sep, x): return () if isinstance(x, bytes): x = x.decode(preferred_encoding, 'replace') - if isinstance(x, unicode): + if isinstance(x, unicode_type): x = x.split(sep) else: x = (y.decode(preferred_encoding, 'replace') if isinstance(y, bytes) @@ -72,7 +69,7 @@ def multiple_text(sep, ui_sep, x): def adapt_datetime(x): - if isinstance(x, (unicode, bytes)): + if isinstance(x, (unicode_type, bytes)): x = parse_date(x, assume_utc=False, as_utc=False) if x and is_date_undefined(x): x = UNDEFINED_DATE @@ -80,7 +77,7 @@ def adapt_datetime(x): def adapt_date(x): - if isinstance(x, (unicode, bytes)): + if isinstance(x, (unicode_type, bytes)): x = parse_only_date(x) if x is None or is_date_undefined(x): x = UNDEFINED_DATE @@ -90,14 +87,14 @@ def adapt_date(x): def adapt_number(typ, x): if x is None: return None - if isinstance(x, (unicode, bytes)): + if isinstance(x, (unicode_type, bytes)): if not x or x.lower() == 'none': return None return typ(x) def adapt_bool(x): - if isinstance(x, (unicode, bytes)): + if isinstance(x, (unicode_type, bytes)): x = x.lower() if x == 'true': x = True diff --git a/src/calibre/devices/jetbook/driver.py b/src/calibre/devices/jetbook/driver.py index ffceb338e8..e6fedf3589 100644 --- a/src/calibre/devices/jetbook/driver.py +++ b/src/calibre/devices/jetbook/driver.py @@ -14,6 +14,7 @@ import sys from calibre.devices.usbms.driver import USBMS from calibre.ebooks.metadata import string_to_authors +from polyglot.builtins import unicode_type class JETBOOK(USBMS): @@ -64,7 +65,7 @@ class JETBOOK(USBMS): def check_unicode(txt): txt = txt.replace('_', ' ') - if not isinstance(txt, unicode): + if not isinstance(txt, unicode_type): return txt.decode(sys.getfilesystemencoding(), 'replace') return txt diff --git a/src/calibre/devices/kindle/driver.py b/src/calibre/devices/kindle/driver.py index 6358c96a09..2d713c1177 100644 --- a/src/calibre/devices/kindle/driver.py +++ b/src/calibre/devices/kindle/driver.py @@ -15,6 +15,7 @@ from calibre.constants import DEBUG from calibre.devices.kindle.bookmark import Bookmark from calibre.devices.usbms.driver import USBMS from calibre import strftime, fsync, prints +from polyglot.builtins import unicode_type ''' Notes on collections: @@ -113,7 +114,7 @@ class KINDLE(USBMS): match = cls.WIRELESS_FILE_NAME_PATTERN.match(os.path.basename(path)) if match is not None: mi.title = match.group('title') - if not isinstance(mi.title, unicode): + if not isinstance(mi.title, unicode_type): mi.title = mi.title.decode(sys.getfilesystemencoding(), 'replace') return mi @@ -291,9 +292,9 @@ class KINDLE(USBMS): hrTag['class'] = 'annotations_divider' user_notes_soup.insert(0, hrTag) - mi.comments += unicode(user_notes_soup.prettify()) + mi.comments += unicode_type(user_notes_soup.prettify()) else: - mi.comments = unicode(user_notes_soup.prettify()) + mi.comments = unicode_type(user_notes_soup.prettify()) # Update library comments db.set_comment(db_id, mi.comments) @@ -547,7 +548,7 @@ class KINDLE2(KINDLE): cust_col_name = opts.extra_customization[self.OPT_APNX_METHOD_COL] if cust_col_name: try: - temp = unicode(metadata.get(cust_col_name)).lower() + temp = unicode_type(metadata.get(cust_col_name)).lower() if temp in self.EXTRA_CUSTOMIZATION_CHOICES[self.OPT_APNX_METHOD]: method = temp else: diff --git a/src/calibre/devices/kobo/books.py b/src/calibre/devices/kobo/books.py index 3307e6b83d..91d50c115d 100644 --- a/src/calibre/devices/kobo/books.py +++ b/src/calibre/devices/kobo/books.py @@ -14,6 +14,7 @@ from calibre.devices.usbms.books import CollectionsBookList from calibre.utils.config_base import prefs from calibre.devices.usbms.driver import debug_print from calibre.ebooks.metadata import author_to_author_sort +from polyglot.builtins import unicode_type class Book(Book_): @@ -95,7 +96,7 @@ class Book(Book_): ans = [u"Kobo metadata:"] def fmt(x, y): - ans.append(u'%-20s: %s'%(unicode(x), unicode(y))) + ans.append(u'%-20s: %s'%(unicode_type(x), unicode_type(y))) if self.contentID: fmt('Content ID', self.contentID) diff --git a/src/calibre/devices/kobo/driver.py b/src/calibre/devices/kobo/driver.py index 57de76ec7c..7586f5c73a 100644 --- a/src/calibre/devices/kobo/driver.py +++ b/src/calibre/devices/kobo/driver.py @@ -32,6 +32,7 @@ from calibre import prints, fsync from calibre.ptempfile import PersistentTemporaryFile from calibre.constants import DEBUG from calibre.utils.config_base import prefs +from polyglot.builtins import unicode_type EPUB_EXT = '.epub' KEPUB_EXT = '.kepub' @@ -43,7 +44,7 @@ def qhash(inputstr): instr = b"" if isinstance(inputstr, bytes): instr = inputstr - elif isinstance(inputstr, unicode): + elif isinstance(inputstr, unicode_type): instr = inputstr.encode("utf8") else: return -1 @@ -1323,9 +1324,9 @@ class KOBO(USBMS): hrTag['class'] = 'annotations_divider' user_notes_soup.insert(0, hrTag) - mi.comments += unicode(user_notes_soup.prettify()) + mi.comments += unicode_type(user_notes_soup.prettify()) else: - mi.comments = unicode(user_notes_soup.prettify()) + mi.comments = unicode_type(user_notes_soup.prettify()) # Update library comments db.set_comment(db_id, mi.comments) @@ -1824,7 +1825,7 @@ class KOBOTOUCH(KOBO): bookshelves.append(row['ShelfName']) cursor.close() -# debug_print("KoboTouch:get_bookshelvesforbook - count bookshelves=" + unicode(count_bookshelves)) +# debug_print("KoboTouch:get_bookshelvesforbook - count bookshelves=" + unicode_type(count_bookshelves)) return bookshelves self.debug_index = 0 @@ -2394,7 +2395,7 @@ class KOBOTOUCH(KOBO): if self.manage_collections: if collections: - # debug_print("KoboTouch:update_device_database_collections - length collections=" + unicode(len(collections))) + # debug_print("KoboTouch:update_device_database_collections - length collections=" + unicode_type(len(collections))) # Need to reset the collections outside the particular loops # otherwise the last item will not be removed @@ -2834,7 +2835,7 @@ class KOBOTOUCH(KOBO): # count_bookshelves = i + 1 cursor.close() -# debug_print("KoboTouch:get_bookshelflist - count bookshelves=" + unicode(count_bookshelves)) +# debug_print("KoboTouch:get_bookshelflist - count bookshelves=" + unicode_type(count_bookshelves)) return bookshelves @@ -2918,7 +2919,7 @@ class KOBOTOUCH(KOBO): cursor.execute(addquery, add_values) elif result['_IsDeleted'] == 'true': debug_print("KoboTouch:check_for_bookshelf - Shelf '%s' is deleted - undeleting. result['_IsDeleted']='%s'" % ( - bookshelf_name, unicode(result['_IsDeleted']))) + bookshelf_name, unicode_type(result['_IsDeleted']))) cursor.execute(updatequery, test_values) cursor.close() diff --git a/src/calibre/devices/kobo/kobotouch_config.py b/src/calibre/devices/kobo/kobotouch_config.py index f9fdac53c6..ac7d9482c8 100644 --- a/src/calibre/devices/kobo/kobotouch_config.py +++ b/src/calibre/devices/kobo/kobotouch_config.py @@ -16,6 +16,7 @@ from calibre.gui2.device_drivers.tabbed_device_config import TabbedDeviceConfig, from calibre.devices.usbms.driver import debug_print from calibre.gui2 import error_dialog from calibre.gui2.dialogs.template_dialog import TemplateDialog +from polyglot.builtins import unicode_type def wrap_msg(msg): @@ -122,7 +123,7 @@ class KOBOTOUCHConfig(TabbedDeviceConfig): p['support_newer_firmware'] = self.support_newer_firmware p['debugging_title'] = self.debugging_title - p['driver_version'] = '.'.join([unicode(i) for i in self.device.version]) + p['driver_version'] = '.'.join([unicode_type(i) for i in self.device.version]) return p @@ -397,7 +398,7 @@ class AdvancedGroupBox(DeviceOptionsGroupBox): 'to perform full read-write functionality - Here be Dragons!! ' 'Enable only if you are comfortable with restoring your kobo ' 'to factory defaults and testing software. ' - 'This driver supports firmware V2.x.x and DBVersion up to ') + unicode( + 'This driver supports firmware V2.x.x and DBVersion up to ') + unicode_type( device.supported_dbversion), device.get_pref('support_newer_firmware') ) @@ -555,7 +556,7 @@ class TemplateConfig(QWidget): # {{{ @property def template(self): - return unicode(self.t.text()).strip() + return unicode_type(self.t.text()).strip() @template.setter def template(self, template): @@ -577,7 +578,7 @@ class TemplateConfig(QWidget): # {{{ except Exception as err: error_dialog(self, _('Invalid template'), '

'+_('The template "%s" is invalid:')%tmpl + - '
'+unicode(err), show=True) + '
'+unicode_type(err), show=True) return False # }}} diff --git a/src/calibre/devices/mtp/driver.py b/src/calibre/devices/mtp/driver.py index 272bca30e1..9f6383d546 100644 --- a/src/calibre/devices/mtp/driver.py +++ b/src/calibre/devices/mtp/driver.py @@ -18,6 +18,7 @@ from calibre.devices.mtp.base import debug from calibre.devices.mtp.defaults import DeviceDefaults from calibre.ptempfile import SpooledTemporaryFile, PersistentTemporaryDirectory from calibre.utils.filenames import shorten_components_to +from polyglot.builtins import unicode_type BASE = importlib.import_module('calibre.devices.mtp.%s.driver'%( 'windows' if iswindows else 'unix')).MTP_DEVICE @@ -75,7 +76,7 @@ class MTP_DEVICE(BASE): def is_folder_ignored(self, storage_or_storage_id, path, ignored_folders=None): - storage_id = unicode(getattr(storage_or_storage_id, 'object_id', + storage_id = unicode_type(getattr(storage_or_storage_id, 'object_id', storage_or_storage_id)) lpath = tuple(icu_lower(name) for name in path) if ignored_folders is None: @@ -166,14 +167,14 @@ class MTP_DEVICE(BASE): traceback.print_exc() dinfo = {} if dinfo.get('device_store_uuid', None) is None: - dinfo['device_store_uuid'] = unicode(uuid.uuid4()) + dinfo['device_store_uuid'] = unicode_type(uuid.uuid4()) if dinfo.get('device_name', None) is None: dinfo['device_name'] = self.current_friendly_name if name is not None: dinfo['device_name'] = name dinfo['location_code'] = location_code dinfo['last_library_uuid'] = getattr(self, 'current_library_uuid', None) - dinfo['calibre_version'] = '.'.join([unicode(i) for i in numeric_version]) + dinfo['calibre_version'] = '.'.join([unicode_type(i) for i in numeric_version]) dinfo['date_last_connected'] = isoformat(now()) dinfo['mtp_prefix'] = storage.storage_prefix raw = json.dumps(dinfo, default=to_json) diff --git a/src/calibre/devices/mtp/filesystem_cache.py b/src/calibre/devices/mtp/filesystem_cache.py index 4451540eea..f5a3ef690d 100644 --- a/src/calibre/devices/mtp/filesystem_cache.py +++ b/src/calibre/devices/mtp/filesystem_cache.py @@ -10,7 +10,7 @@ __docformat__ = 'restructuredtext en' import weakref, sys, json from collections import deque from operator import attrgetter -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from datetime import datetime from calibre import human_readable, prints, force_unicode @@ -74,7 +74,7 @@ class FileOrFolder(object): def __repr__(self): name = 'Folder' if self.is_folder else 'File' try: - path = unicode(self.full_path) + path = unicode_type(self.full_path) except: path = '' datum = 'size=%s'%(self.size) @@ -250,5 +250,3 @@ class FilesystemCache(object): return self.id_map[object_id] except KeyError: raise ValueError('No object found with MTP path: %s'%path) - - diff --git a/src/calibre/devices/mtp/unix/driver.py b/src/calibre/devices/mtp/unix/driver.py index 17284dd259..bff84a6320 100644 --- a/src/calibre/devices/mtp/unix/driver.py +++ b/src/calibre/devices/mtp/unix/driver.py @@ -17,6 +17,7 @@ from calibre.constants import plugins, islinux, isosx, ispy3 from calibre.ptempfile import SpooledTemporaryFile from calibre.devices.errors import OpenFailed, DeviceError, BlacklistedDevice, OpenActionNeeded from calibre.devices.mtp.base import MTPDeviceBase, synchronous, debug +from polyglot.builtins import unicode_type MTPDevice = namedtuple('MTPDevice', 'busnum devnum vendor_id product_id ' 'bcd serial manufacturer product') @@ -321,7 +322,7 @@ class MTP_DEVICE(MTPDeviceBase): storage.append({'id':sid, 'size':capacity, 'is_folder':True, 'name':name, 'can_delete':False, 'is_system':True}) - self._currently_getting_sid = unicode(sid) + self._currently_getting_sid = unicode_type(sid) items, errs = self.dev.get_filesystem(sid, partial(self._filesystem_callback, {})) all_items.extend(items), all_errs.extend(errs) @@ -373,7 +374,7 @@ class MTP_DEVICE(MTPDeviceBase): e = parent.folder_named(name) if e is not None: return e - ename = name.encode('utf-8') if isinstance(name, unicode) else name + ename = name.encode('utf-8') if isinstance(name, unicode_type) else name sid, pid = parent.storage_id, parent.object_id if pid == sid: pid = 0 @@ -396,7 +397,7 @@ class MTP_DEVICE(MTPDeviceBase): raise ValueError('Cannot upload file %s, it already exists'%( e.full_path,)) self.delete_file_or_folder(e) - ename = name.encode('utf-8') if isinstance(name, unicode) else name + ename = name.encode('utf-8') if isinstance(name, unicode_type) else name sid, pid = parent.storage_id, parent.object_id if pid == sid: pid = 0xFFFFFFFF diff --git a/src/calibre/devices/mtp/windows/driver.py b/src/calibre/devices/mtp/windows/driver.py index 859ff99ffa..23c445570b 100644 --- a/src/calibre/devices/mtp/windows/driver.py +++ b/src/calibre/devices/mtp/windows/driver.py @@ -9,7 +9,7 @@ __docformat__ = 'restructuredtext en' import time, threading, traceback from functools import wraps, partial -from polyglot.builtins import zip +from polyglot.builtins import unicode_type, zip from itertools import chain from calibre import as_unicode, prints, force_unicode @@ -264,7 +264,7 @@ class MTP_DEVICE(MTPDeviceBase): break storage = {'id':storage_id, 'size':capacity, 'name':name, 'is_folder':True, 'can_delete':False, 'is_system':True} - self._currently_getting_sid = unicode(storage_id) + self._currently_getting_sid = unicode_type(storage_id) id_map = self.dev.get_filesystem(storage_id, partial( self._filesystem_callback, {})) for x in id_map.itervalues(): @@ -441,5 +441,3 @@ class MTP_DEVICE(MTPDeviceBase): ans = self.dev.put_file(pid, name, stream, size, callback) ans['storage_id'] = sid return parent.add_child(ans) - - diff --git a/src/calibre/devices/prst1/driver.py b/src/calibre/devices/prst1/driver.py index 4d65f1ca6f..12120249d3 100644 --- a/src/calibre/devices/prst1/driver.py +++ b/src/calibre/devices/prst1/driver.py @@ -24,6 +24,7 @@ from calibre.devices.usbms.books import CollectionsBookList from calibre.devices.usbms.books import BookList from calibre.ebooks.metadata import authors_to_sort_string, authors_to_string from calibre.constants import islinux +from polyglot.builtins import unicode_type DBPATH = 'Sony_Reader/database/books.db' THUMBPATH = 'Sony_Reader/database/cache/books/%s/thumbnail/main_thumbnail.jpg' @@ -170,7 +171,7 @@ class PRST1(USBMS): with closing(sqlite.connect(dbpath)) as connection: # Replace undecodable characters in the db instead of erroring out - connection.text_factory = lambda x: unicode(x, "utf-8", "replace") + connection.text_factory = lambda x: unicode_type(x, "utf-8", "replace") cursor = connection.cursor() # Query collections diff --git a/src/calibre/devices/smart_device_app/driver.py b/src/calibre/devices/smart_device_app/driver.py index 83c38a0df2..9619a82f04 100644 --- a/src/calibre/devices/smart_device_app/driver.py +++ b/src/calibre/devices/smart_device_app/driver.py @@ -38,6 +38,7 @@ from calibre.utils.filenames import ascii_filename as sanitize, shorten_componen from calibre.utils.mdns import (publish as publish_zeroconf, unpublish as unpublish_zeroconf, get_all_ips) from calibre.utils.socket_inheritance import set_socket_inherit +from polyglot.builtins import unicode_type def synchronous(tlockname): @@ -397,7 +398,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): if isinstance(a, dict): printable = {} for k,v in a.iteritems(): - if isinstance(v, (str, unicode)) and len(v) > 50: + if isinstance(v, (str, unicode_type)) and len(v) > 50: printable[k] = 'too long' else: printable[k] = v @@ -418,14 +419,14 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): if not isinstance(dinfo, dict): dinfo = {} if dinfo.get('device_store_uuid', None) is None: - dinfo['device_store_uuid'] = unicode(uuid.uuid4()) + dinfo['device_store_uuid'] = unicode_type(uuid.uuid4()) if dinfo.get('device_name') is None: dinfo['device_name'] = self.get_gui_name() if name is not None: dinfo['device_name'] = name dinfo['location_code'] = location_code dinfo['last_library_uuid'] = getattr(self, 'current_library_uuid', None) - dinfo['calibre_version'] = '.'.join([unicode(i) for i in numeric_version]) + dinfo['calibre_version'] = '.'.join([unicode_type(i) for i in numeric_version]) dinfo['date_last_connected'] = isoformat(now()) dinfo['prefix'] = self.PREFIX return dinfo @@ -478,7 +479,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): from calibre.library.save_to_disk import get_components from calibre.library.save_to_disk import config opts = config().parse() - if not isinstance(template, unicode): + if not isinstance(template, unicode_type): template = template.decode('utf-8') app_id = str(getattr(mdata, 'application_id', '')) id_ = mdata.get('id', fname) @@ -726,7 +727,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin): from calibre.utils.date import now, parse_date try: key = self._make_metadata_cache_key(uuid, ext_or_lpath) - if isinstance(lastmod, unicode): + if isinstance(lastmod, unicode_type): if lastmod == 'None': return None lastmod = parse_date(lastmod) diff --git a/src/calibre/devices/udisks.py b/src/calibre/devices/udisks.py index 70e924eac5..7240444f2a 100644 --- a/src/calibre/devices/udisks.py +++ b/src/calibre/devices/udisks.py @@ -8,6 +8,7 @@ __docformat__ = 'restructuredtext en' import os, re +from polyglot.builtins import unicode_type def node_mountpoint(node): @@ -48,7 +49,7 @@ class UDisks(object): def mount(self, device_node_path): d = self.device(device_node_path) try: - return unicode(d.FilesystemMount('', + return unicode_type(d.FilesystemMount('', ['auth_no_user_interaction', 'rw', 'noexec', 'nosuid', 'nodev', 'uid=%d'%os.geteuid(), 'gid=%d'%os.getegid()])) except: @@ -131,7 +132,7 @@ class UDisks2(object): mount_options = ['rw', 'noexec', 'nosuid', 'nodev', 'uid=%d'%os.geteuid(), 'gid=%d'%os.getegid()] try: - return unicode(d.Mount( + return unicode_type(d.Mount( { 'auth.no_user_interaction':True, 'options':','.join(mount_options) diff --git a/src/calibre/devices/usbms/deviceconfig.py b/src/calibre/devices/usbms/deviceconfig.py index e0208081eb..2f65ac09fb 100644 --- a/src/calibre/devices/usbms/deviceconfig.py +++ b/src/calibre/devices/usbms/deviceconfig.py @@ -5,6 +5,7 @@ __copyright__ = '2009, John Schember ' __docformat__ = 'restructuredtext en' from calibre.utils.config_base import Config, ConfigProxy +from polyglot.builtins import unicode_type class DeviceConfig(object): @@ -107,15 +108,15 @@ class DeviceConfig(object): if hasattr(config_widget.opt_extra_customization[i], 'isChecked'): ec.append(config_widget.opt_extra_customization[i].isChecked()) elif hasattr(config_widget.opt_extra_customization[i], 'currentText'): - ec.append(unicode(config_widget.opt_extra_customization[i].currentText()).strip()) + ec.append(unicode_type(config_widget.opt_extra_customization[i].currentText()).strip()) else: - ec.append(unicode(config_widget.opt_extra_customization[i].text()).strip()) + ec.append(unicode_type(config_widget.opt_extra_customization[i].text()).strip()) else: - ec = unicode(config_widget.opt_extra_customization.text()).strip() + ec = unicode_type(config_widget.opt_extra_customization.text()).strip() if not ec: ec = None proxy['extra_customization'] = ec - st = unicode(config_widget.opt_save_template.text()) + st = unicode_type(config_widget.opt_save_template.text()) proxy['save_template'] = st @classmethod diff --git a/src/calibre/devices/usbms/driver.py b/src/calibre/devices/usbms/driver.py index abd9228f75..ee5ec6452e 100644 --- a/src/calibre/devices/usbms/driver.py +++ b/src/calibre/devices/usbms/driver.py @@ -20,6 +20,7 @@ from calibre.devices.usbms.cli import CLI from calibre.devices.usbms.device import Device from calibre.devices.usbms.books import BookList, Book from calibre.ebooks.metadata.book.json_codec import JsonCodec +from polyglot.builtins import unicode_type BASE_TIME = None @@ -105,14 +106,14 @@ class USBMS(CLI, Device): if not isinstance(dinfo, dict): dinfo = {} if dinfo.get('device_store_uuid', None) is None: - dinfo['device_store_uuid'] = unicode(uuid.uuid4()) + dinfo['device_store_uuid'] = unicode_type(uuid.uuid4()) if dinfo.get('device_name', None) is None: dinfo['device_name'] = self.get_gui_name() if name is not None: dinfo['device_name'] = name dinfo['location_code'] = location_code dinfo['last_library_uuid'] = getattr(self, 'current_library_uuid', None) - dinfo['calibre_version'] = '.'.join([unicode(i) for i in numeric_version]) + dinfo['calibre_version'] = '.'.join([unicode_type(i) for i in numeric_version]) dinfo['date_last_connected'] = isoformat(now()) dinfo['prefix'] = prefix.replace('\\', '/') return dinfo diff --git a/src/calibre/devices/utils.py b/src/calibre/devices/utils.py index 8cd540ca02..506527c668 100644 --- a/src/calibre/devices/utils.py +++ b/src/calibre/devices/utils.py @@ -11,6 +11,7 @@ import os, time, re from functools import partial from calibre.devices.errors import DeviceError, WrongDestinationError, FreeSpaceError +from polyglot.builtins import unicode_type def sanity_check(on_card, files, card_prefixes, free_space): @@ -97,7 +98,7 @@ def create_upload_path(mdata, fname, template, sanitize, ext = path_type.splitext(fname)[1] opts = config().parse() - if not isinstance(template, unicode): + if not isinstance(template, unicode_type): template = template.decode('utf-8') app_id = str(getattr(mdata, 'application_id', '')) id_ = mdata.get('id', fname) diff --git a/src/calibre/ebooks/__init__.py b/src/calibre/ebooks/__init__.py index 2240def4b7..874aa90bbd 100644 --- a/src/calibre/ebooks/__init__.py +++ b/src/calibre/ebooks/__init__.py @@ -9,6 +9,7 @@ from various formats. import traceback, os, re from calibre import CurrentDir, prints +from polyglot.builtins import unicode_type class ConversionError(Exception): @@ -113,7 +114,7 @@ def extract_calibre_cover(raw, base, log): if matches is None: body = soup.find('body') if body is not None: - text = u''.join(map(unicode, body.findAll(text=True))) + text = u''.join(map(unicode_type, body.findAll(text=True))) if text.strip(): # Body has text, abort return @@ -210,7 +211,7 @@ def check_ebook_format(stream, current_guess): def normalize(x): - if isinstance(x, unicode): + if isinstance(x, unicode_type): import unicodedata x = unicodedata.normalize('NFC', x) return x diff --git a/src/calibre/ebooks/chardet.py b/src/calibre/ebooks/chardet.py index fd919d3c01..2d0dd7efe2 100644 --- a/src/calibre/ebooks/chardet.py +++ b/src/calibre/ebooks/chardet.py @@ -8,6 +8,7 @@ __copyright__ = '2009, Kovid Goyal ' __docformat__ = 'restructuredtext en' import re, codecs +from polyglot.builtins import unicode_type ENCODING_PATS = [ # XML declaration @@ -92,7 +93,7 @@ def force_encoding(raw, verbose, assume_utf8=False): def detect_xml_encoding(raw, verbose=False, assume_utf8=False): - if not raw or isinstance(raw, unicode): + if not raw or isinstance(raw, unicode_type): return raw, None for x in ('utf8', 'utf-16-le', 'utf-16-be'): bom = getattr(codecs, 'BOM_'+x.upper().replace('-16', '16').replace( @@ -135,7 +136,7 @@ def xml_to_unicode(raw, verbose=False, strip_encoding_pats=False, return '', None raw, encoding = detect_xml_encoding(raw, verbose=verbose, assume_utf8=assume_utf8) - if not isinstance(raw, unicode): + if not isinstance(raw, unicode_type): raw = raw.decode(encoding, 'replace') if strip_encoding_pats: diff --git a/src/calibre/ebooks/chm/reader.py b/src/calibre/ebooks/chm/reader.py index 5a82c3544d..fc65685273 100644 --- a/src/calibre/ebooks/chm/reader.py +++ b/src/calibre/ebooks/chm/reader.py @@ -14,6 +14,7 @@ from calibre.utils.chm.chm import CHMFile from calibre.constants import plugins from calibre.ebooks.metadata.toc import TOC from calibre.ebooks.chardet import xml_to_unicode +from polyglot.builtins import unicode_type chmlib, chmlib_err = plugins['chmlib'] @@ -48,7 +49,7 @@ class CHMReader(CHMFile): def __init__(self, input, log, input_encoding=None): CHMFile.__init__(self) - if isinstance(input, unicode): + if isinstance(input, unicode_type): input = input.encode(filesystem_encoding) if not self.LoadCHM(input): raise CHMError("Unable to open CHM file '%s'"%(input,)) @@ -113,7 +114,7 @@ class CHMReader(CHMFile): enc = 'cp1252' for path in self.Contents(): fpath = path - if not isinstance(path, unicode): + if not isinstance(path, unicode_type): fpath = path.decode(enc) lpath = os.path.join(output_dir, fpath) self._ensure_dir(lpath) @@ -146,7 +147,7 @@ class CHMReader(CHMFile): with open(lpath, 'r+b') as f: data = f.read() data = self._reformat(data, lpath) - if isinstance(data, unicode): + if isinstance(data, unicode_type): data = data.encode('utf-8') f.seek(0) f.truncate() diff --git a/src/calibre/ebooks/comic/input.py b/src/calibre/ebooks/comic/input.py index 49ccf2ccac..a636069fbb 100755 --- a/src/calibre/ebooks/comic/input.py +++ b/src/calibre/ebooks/comic/input.py @@ -16,6 +16,7 @@ from calibre.ptempfile import PersistentTemporaryDirectory from calibre.utils.icu import numeric_sort_key from calibre.utils.ipc.server import Server from calibre.utils.ipc.job import ParallelJob +from polyglot.builtins import unicode_type # If the specified screen has either dimension larger than this value, no image # rescaling is done (we assume that it is a tablet output profile) @@ -27,7 +28,7 @@ def extract_comic(path_to_comic_file): Un-archive the comic file. ''' tdir = PersistentTemporaryDirectory(suffix='_comic_extract') - if not isinstance(tdir, unicode): + if not isinstance(tdir, unicode_type): # Needed in case the zip file has wrongly encoded unicode file/dir # names tdir = tdir.decode(filesystem_encoding) @@ -273,6 +274,3 @@ def process_pages(pages, opts, update, tdir): ans += pages failures += failures_ return ans, failures - - - diff --git a/src/calibre/ebooks/conversion/config.py b/src/calibre/ebooks/conversion/config.py index cde5aecf59..2d9c708cbe 100644 --- a/src/calibre/ebooks/conversion/config.py +++ b/src/calibre/ebooks/conversion/config.py @@ -13,6 +13,7 @@ from calibre.utils.lock import ExclusiveFile from calibre import sanitize_file_name from calibre.customize.conversion import OptionRecommendation from calibre.customize.ui import available_output_formats +from polyglot.builtins import unicode_type config_dir = os.path.join(config_dir, 'conversion') @@ -85,7 +86,7 @@ class GuiRecommendations(dict): def serialize(self): ans = json.dumps(self, indent=2, ensure_ascii=False) - if isinstance(ans, unicode): + if isinstance(ans, unicode_type): ans = ans.encode('utf-8') return b'json:' + ans diff --git a/src/calibre/ebooks/conversion/plugins/chm_input.py b/src/calibre/ebooks/conversion/plugins/chm_input.py index 178a9ffb24..fc0af0552f 100644 --- a/src/calibre/ebooks/conversion/plugins/chm_input.py +++ b/src/calibre/ebooks/conversion/plugins/chm_input.py @@ -8,6 +8,7 @@ import os from calibre.customize.conversion import InputFormatPlugin from calibre.ptempfile import TemporaryDirectory from calibre.constants import filesystem_encoding +from polyglot.builtins import unicode_type class CHMInput(InputFormatPlugin): @@ -34,7 +35,7 @@ class CHMInput(InputFormatPlugin): log.debug('Processing CHM...') with TemporaryDirectory('_chm2oeb') as tdir: - if not isinstance(tdir, unicode): + if not isinstance(tdir, unicode_type): tdir = tdir.decode(filesystem_encoding) html_input = plugin_for_input_format('html') for opt in html_input.options: @@ -125,7 +126,7 @@ class CHMInput(InputFormatPlugin): base = os.path.dirname(os.path.abspath(htmlpath)) def unquote(x): - if isinstance(x, unicode): + if isinstance(x, unicode_type): x = x.encode('utf-8') return _unquote(x).decode('utf-8') diff --git a/src/calibre/ebooks/conversion/plugins/epub_input.py b/src/calibre/ebooks/conversion/plugins/epub_input.py index 54327864da..a0216ac9f3 100644 --- a/src/calibre/ebooks/conversion/plugins/epub_input.py +++ b/src/calibre/ebooks/conversion/plugins/epub_input.py @@ -7,6 +7,7 @@ import os, re, posixpath from itertools import cycle from calibre.customize.conversion import InputFormatPlugin, OptionRecommendation +from polyglot.builtins import unicode_type ADOBE_OBFUSCATION = 'http://ns.adobe.com/pdf/enc#RC' IDPF_OBFUSCATION = 'http://www.idpf.org/2008/embedding' @@ -367,7 +368,7 @@ class EPUBInput(InputFormatPlugin): def add_from_li(li, parent): href = text = None for x in li.iterchildren(XHTML('a'), XHTML('span')): - text = etree.tostring(x, method='text', encoding=unicode, with_tail=False).strip() or ' '.join(x.xpath('descendant-or-self::*/@title')).strip() + text = etree.tostring(x, method='text', encoding=unicode_type, with_tail=False).strip() or ' '.join(x.xpath('descendant-or-self::*/@title')).strip() href = x.get('href') if href: if href.startswith('#'): diff --git a/src/calibre/ebooks/conversion/plugins/epub_output.py b/src/calibre/ebooks/conversion/plugins/epub_output.py index 829227599e..a6967a8645 100644 --- a/src/calibre/ebooks/conversion/plugins/epub_output.py +++ b/src/calibre/ebooks/conversion/plugins/epub_output.py @@ -13,6 +13,7 @@ from calibre.customize.conversion import (OutputFormatPlugin, from calibre.ptempfile import TemporaryDirectory from calibre import CurrentDir from calibre.constants import filesystem_encoding +from polyglot.builtins import unicode_type block_level_tags = ( 'address', @@ -225,8 +226,8 @@ class EPUBOutput(OutputFormatPlugin): identifiers = oeb.metadata['identifier'] uuid = None for x in identifiers: - if x.get(OPF('scheme'), None).lower() == 'uuid' or unicode(x).startswith('urn:uuid:'): - uuid = unicode(x).split(':')[-1] + if x.get(OPF('scheme'), None).lower() == 'uuid' or unicode_type(x).startswith('urn:uuid:'): + uuid = unicode_type(x).split(':')[-1] break encrypted_fonts = getattr(input_plugin, 'encrypted_fonts', []) @@ -241,7 +242,7 @@ class EPUBOutput(OutputFormatPlugin): # for some absurd reason, or it will throw a hissy fit and refuse # to use the obfuscated fonts. for x in identifiers: - if unicode(x) == uuid: + if unicode_type(x) == uuid: x.content = 'urn:uuid:'+uuid with TemporaryDirectory(u'_epub_output') as tdir: @@ -325,7 +326,7 @@ class EPUBOutput(OutputFormatPlugin): fonts = [] for uri in list(uris.keys()): path = uris[uri] - if isinstance(path, unicode): + if isinstance(path, unicode_type): path = path.encode(filesystem_encoding) if not os.path.exists(path): uris.pop(uri) @@ -339,7 +340,7 @@ class EPUBOutput(OutputFormatPlugin): f.write(chr(ord(data[i]) ^ key[i%16])) else: self.log.warn('Font', path, 'is invalid, ignoring') - if not isinstance(uri, unicode): + if not isinstance(uri, unicode_type): uri = uri.decode('utf-8') fonts.append(u''' diff --git a/src/calibre/ebooks/conversion/plugins/fb2_input.py b/src/calibre/ebooks/conversion/plugins/fb2_input.py index 53a05049af..879836aa85 100644 --- a/src/calibre/ebooks/conversion/plugins/fb2_input.py +++ b/src/calibre/ebooks/conversion/plugins/fb2_input.py @@ -8,6 +8,7 @@ import os, re from calibre.customize.conversion import InputFormatPlugin, OptionRecommendation from calibre import guess_type +from polyglot.builtins import unicode_type FB2NS = 'http://www.gribuser.ru/xml/fictionbook/2.0' FB21NS = 'http://www.gribuser.ru/xml/fictionbook/2.1' @@ -70,7 +71,7 @@ class FB2Input(InputFormatPlugin): stylesheets = doc.xpath('//*[local-name() = "stylesheet" and @type="text/css"]') css = '' for s in stylesheets: - css += etree.tostring(s, encoding=unicode, method='text', + css += etree.tostring(s, encoding=unicode_type, method='text', with_tail=False) + '\n\n' if css: import css_parser, logging @@ -82,7 +83,7 @@ class FB2Input(InputFormatPlugin): log.debug('Parsing stylesheet...') stylesheet = parser.parseString(text) stylesheet.namespaces['h'] = XHTML_NS - css = unicode(stylesheet.cssText).replace('h|style', 'h|span') + css = unicode_type(stylesheet.cssText).replace('h|style', 'h|span') css = re.sub(r'name\s*=\s*', 'class=', css) self.extract_embedded_content(doc) log.debug('Converting XML to HTML...') diff --git a/src/calibre/ebooks/conversion/plugins/html_input.py b/src/calibre/ebooks/conversion/plugins/html_input.py index 03903cbf01..fa5e211e4d 100644 --- a/src/calibre/ebooks/conversion/plugins/html_input.py +++ b/src/calibre/ebooks/conversion/plugins/html_input.py @@ -17,6 +17,7 @@ from calibre.customize.conversion import (InputFormatPlugin, from calibre.utils.localization import get_lang from calibre.utils.filenames import ascii_filename from calibre.utils.imghdr import what +from polyglot.builtins import unicode_type def sanitize_file_name(x): @@ -225,7 +226,7 @@ class HTMLInput(InputFormatPlugin): def link_to_local_path(self, link_, base=None): from calibre.ebooks.html.input import Link - if not isinstance(link_, unicode): + if not isinstance(link_, unicode_type): try: link_ = link_.decode('utf-8', 'error') except: @@ -289,7 +290,7 @@ class HTMLInput(InputFormatPlugin): # bhref refers to an already existing file. The read() method of # DirContainer will call unquote on it before trying to read the # file, therefore we quote it here. - if isinstance(bhref, unicode): + if isinstance(bhref, unicode_type): bhref = bhref.encode('utf-8') item.html_input_href = quote(bhref).decode('utf-8') if guessed in self.OEB_STYLES: diff --git a/src/calibre/ebooks/conversion/plugins/html_output.py b/src/calibre/ebooks/conversion/plugins/html_output.py index 4ea5f630e4..4c82974460 100644 --- a/src/calibre/ebooks/conversion/plugins/html_output.py +++ b/src/calibre/ebooks/conversion/plugins/html_output.py @@ -9,6 +9,7 @@ from os.path import dirname, abspath, relpath as _relpath, exists, basename from calibre.customize.conversion import OutputFormatPlugin, OptionRecommendation from calibre import CurrentDir from calibre.ptempfile import PersistentTemporaryDirectory +from polyglot.builtins import unicode_type def relpath(*args): @@ -135,7 +136,7 @@ class HTMLOutput(OutputFormatPlugin): toc=html_toc, meta=meta, nextLink=nextLink, tocUrl=tocUrl, cssLink=cssLink, firstContentPageLink=nextLink) - if isinstance(t, unicode): + if isinstance(t, unicode_type): t = t.encode('utf-8') f.write(t) diff --git a/src/calibre/ebooks/conversion/plugins/htmlz_output.py b/src/calibre/ebooks/conversion/plugins/htmlz_output.py index 48ec94ac86..cdb74077ae 100644 --- a/src/calibre/ebooks/conversion/plugins/htmlz_output.py +++ b/src/calibre/ebooks/conversion/plugins/htmlz_output.py @@ -13,6 +13,7 @@ from cStringIO import StringIO from calibre.customize.conversion import OutputFormatPlugin, \ OptionRecommendation from calibre.ptempfile import TemporaryDirectory +from polyglot.builtins import unicode_type class HTMLZOutput(OutputFormatPlugin): @@ -81,9 +82,9 @@ class HTMLZOutput(OutputFormatPlugin): fname = u'index' if opts.htmlz_title_filename: from calibre.utils.filenames import shorten_components_to - fname = shorten_components_to(100, (ascii_filename(unicode(oeb_book.metadata.title[0])),))[0] + fname = shorten_components_to(100, (ascii_filename(unicode_type(oeb_book.metadata.title[0])),))[0] with open(os.path.join(tdir, fname+u'.html'), 'wb') as tf: - if isinstance(html, unicode): + if isinstance(html, unicode_type): html = html.encode('utf-8') tf.write(html) @@ -100,7 +101,7 @@ class HTMLZOutput(OutputFormatPlugin): for item in oeb_book.manifest: if item.media_type in OEB_IMAGES and item.href in images: if item.media_type == SVG_MIME: - data = unicode(etree.tostring(item.data, encoding=unicode)) + data = unicode_type(etree.tostring(item.data, encoding=unicode_type)) else: data = item.data fname = os.path.join(tdir, u'images', images[item.href]) diff --git a/src/calibre/ebooks/conversion/plugins/lrf_output.py b/src/calibre/ebooks/conversion/plugins/lrf_output.py index 3e99766e66..d743a1de74 100644 --- a/src/calibre/ebooks/conversion/plugins/lrf_output.py +++ b/src/calibre/ebooks/conversion/plugins/lrf_output.py @@ -10,6 +10,7 @@ import sys, os from calibre.customize.conversion import OutputFormatPlugin from calibre.customize.conversion import OptionRecommendation +from polyglot.builtins import unicode_type class LRFOptions(object): @@ -17,7 +18,7 @@ class LRFOptions(object): def __init__(self, output, opts, oeb): def f2s(f): try: - return unicode(f[0]) + return unicode_type(f[0]) except: return '' m = oeb.metadata @@ -31,13 +32,13 @@ class LRFOptions(object): self.title_sort = self.author_sort = '' for x in m.creator: if x.role == 'aut': - self.author = unicode(x) - fa = unicode(getattr(x, 'file_as', '')) + self.author = unicode_type(x) + fa = unicode_type(getattr(x, 'file_as', '')) if fa: self.author_sort = fa for x in m.title: - if unicode(x.file_as): - self.title_sort = unicode(x.file_as) + if unicode_type(x.file_as): + self.title_sort = unicode_type(x.file_as) self.freetext = f2s(m.description) self.category = f2s(m.subject) self.cover = None diff --git a/src/calibre/ebooks/conversion/plugins/mobi_input.py b/src/calibre/ebooks/conversion/plugins/mobi_input.py index 4c5845d255..8c42e8345d 100644 --- a/src/calibre/ebooks/conversion/plugins/mobi_input.py +++ b/src/calibre/ebooks/conversion/plugins/mobi_input.py @@ -6,6 +6,7 @@ __docformat__ = 'restructuredtext en' import os from calibre.customize.conversion import InputFormatPlugin +from polyglot.builtins import unicode_type class MOBIInput(InputFormatPlugin): @@ -49,7 +50,7 @@ class MOBIInput(InputFormatPlugin): raw = parse_cache.pop('calibre_raw_mobi_markup', False) if raw: - if isinstance(raw, unicode): + if isinstance(raw, unicode_type): raw = raw.encode('utf-8') open(u'debug-raw.html', 'wb').write(raw) from calibre.ebooks.oeb.base import close_self_closing_tags diff --git a/src/calibre/ebooks/conversion/plugins/mobi_output.py b/src/calibre/ebooks/conversion/plugins/mobi_output.py index 83d8730760..ee939f26be 100644 --- a/src/calibre/ebooks/conversion/plugins/mobi_output.py +++ b/src/calibre/ebooks/conversion/plugins/mobi_output.py @@ -8,6 +8,7 @@ __docformat__ = 'restructuredtext en' from calibre.customize.conversion import (OutputFormatPlugin, OptionRecommendation) +from polyglot.builtins import unicode_type def remove_html_cover(oeb, log): @@ -121,7 +122,7 @@ class MOBIOutput(OutputFormatPlugin): if not found: from calibre.ebooks import generate_masthead self.oeb.log.debug('No masthead found in manifest, generating default mastheadImage...') - raw = generate_masthead(unicode(self.oeb.metadata['title'][0])) + raw = generate_masthead(unicode_type(self.oeb.metadata['title'][0])) id, href = self.oeb.manifest.generate('masthead', 'masthead') self.oeb.manifest.add(id, href, 'image/gif', data=raw) self.oeb.guide.add('masthead', 'Masthead Image', href) @@ -165,7 +166,7 @@ class MOBIOutput(OutputFormatPlugin): sec.nodes.remove(a) root = TOC(klass='periodical', href=self.oeb.spine[0].href, - title=unicode(self.oeb.metadata.title[0])) + title=unicode_type(self.oeb.metadata.title[0])) for s in sections: if articles[id(s)]: diff --git a/src/calibre/ebooks/conversion/plugins/pdf_output.py b/src/calibre/ebooks/conversion/plugins/pdf_output.py index dc344e6422..b0b4ad6bae 100644 --- a/src/calibre/ebooks/conversion/plugins/pdf_output.py +++ b/src/calibre/ebooks/conversion/plugins/pdf_output.py @@ -14,6 +14,7 @@ from calibre.constants import iswindows from calibre.customize.conversion import (OutputFormatPlugin, OptionRecommendation) from calibre.ptempfile import TemporaryDirectory +from polyglot.builtins import unicode_type UNITS = ['millimeter', 'centimeter', 'point', 'inch' , 'pica' , 'didot', 'cicero', 'devicepixel'] @@ -202,8 +203,8 @@ class PDFOutput(OutputFormatPlugin): def get_cover_data(self): oeb = self.oeb - if (oeb.metadata.cover and unicode(oeb.metadata.cover[0]) in oeb.manifest.ids): - cover_id = unicode(oeb.metadata.cover[0]) + if (oeb.metadata.cover and unicode_type(oeb.metadata.cover[0]) in oeb.manifest.ids): + cover_id = unicode_type(oeb.metadata.cover[0]) item = oeb.manifest.ids[cover_id] self.cover_data = item.data diff --git a/src/calibre/ebooks/conversion/plugins/pml_output.py b/src/calibre/ebooks/conversion/plugins/pml_output.py index 0604764c49..20bf1dc18d 100644 --- a/src/calibre/ebooks/conversion/plugins/pml_output.py +++ b/src/calibre/ebooks/conversion/plugins/pml_output.py @@ -9,6 +9,7 @@ import os, cStringIO from calibre.customize.conversion import (OutputFormatPlugin, OptionRecommendation) from calibre.ptempfile import TemporaryDirectory +from polyglot.builtins import unicode_type class PMLOutput(OutputFormatPlugin): @@ -40,7 +41,7 @@ class PMLOutput(OutputFormatPlugin): with TemporaryDirectory('_pmlz_output') as tdir: pmlmlizer = PMLMLizer(log) - pml = unicode(pmlmlizer.extract_content(oeb_book, opts)) + pml = unicode_type(pmlmlizer.extract_content(oeb_book, opts)) with open(os.path.join(tdir, 'index.pml'), 'wb') as out: out.write(pml.encode(opts.pml_output_encoding, 'replace')) diff --git a/src/calibre/ebooks/conversion/plugins/recipe_input.py b/src/calibre/ebooks/conversion/plugins/recipe_input.py index 477c4a434c..26577a5e60 100644 --- a/src/calibre/ebooks/conversion/plugins/recipe_input.py +++ b/src/calibre/ebooks/conversion/plugins/recipe_input.py @@ -11,6 +11,7 @@ import os from calibre.customize.conversion import InputFormatPlugin, OptionRecommendation from calibre.constants import numeric_version from calibre import walk +from polyglot.builtins import unicode_type class RecipeDisabled(Exception): @@ -161,6 +162,6 @@ class RecipeInput(InputFormatPlugin): def save_download(self, zf): raw = self.recipe_source - if isinstance(raw, unicode): + if isinstance(raw, unicode_type): raw = raw.encode('utf-8') zf.writestr('download.recipe', raw) diff --git a/src/calibre/ebooks/conversion/plugins/snb_output.py b/src/calibre/ebooks/conversion/plugins/snb_output.py index 4248822bb4..3861286a96 100644 --- a/src/calibre/ebooks/conversion/plugins/snb_output.py +++ b/src/calibre/ebooks/conversion/plugins/snb_output.py @@ -9,6 +9,7 @@ import os, string from calibre.customize.conversion import OutputFormatPlugin, OptionRecommendation from calibre.ptempfile import TemporaryDirectory from calibre.constants import __appname__, __version__ +from polyglot.builtins import unicode_type class SNBOutput(OutputFormatPlugin): @@ -73,20 +74,20 @@ class SNBOutput(OutputFormatPlugin): # Process Meta data meta = oeb_book.metadata if meta.title: - title = unicode(meta.title[0]) + title = unicode_type(meta.title[0]) else: title = '' - authors = [unicode(x) for x in meta.creator if x.role == 'aut'] + authors = [unicode_type(x) for x in meta.creator if x.role == 'aut'] if meta.publisher: - publishers = unicode(meta.publisher[0]) + publishers = unicode_type(meta.publisher[0]) else: publishers = '' if meta.language: - lang = unicode(meta.language[0]).upper() + lang = unicode_type(meta.language[0]).upper() else: lang = '' if meta.description: - abstract = unicode(meta.description[0]) + abstract = unicode_type(meta.description[0]) else: abstract = '' diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py index a81af21e0d..e3cf965787 100644 --- a/src/calibre/ebooks/conversion/plumber.py +++ b/src/calibre/ebooks/conversion/plumber.py @@ -18,6 +18,7 @@ from calibre.utils.zipfile import ZipFile from calibre import (extract, walk, isbytestring, filesystem_encoding, get_types_map) from calibre.constants import __version__ +from polyglot.builtins import unicode_type DEBUG_README=u''' This debug directory contains snapshots of the e-book as it passes through the @@ -794,7 +795,7 @@ OptionRecommendation(name='search_replace', def unarchive(self, path, tdir): extract(path, tdir) files = list(walk(tdir)) - files = [f if isinstance(f, unicode) else f.decode(filesystem_encoding) + files = [f if isinstance(f, unicode_type) else f.decode(filesystem_encoding) for f in files] from calibre.customize.ui import available_input_formats fmts = set(available_input_formats()) @@ -915,7 +916,7 @@ OptionRecommendation(name='search_replace', try: val = parse_date(val, assume_utc=x=='timestamp') except: - self.log.exception(_('Failed to parse date/time') + ' ' + unicode(val)) + self.log.exception(_('Failed to parse date/time') + ' ' + unicode_type(val)) continue setattr(mi, x, val) diff --git a/src/calibre/ebooks/conversion/preprocess.py b/src/calibre/ebooks/conversion/preprocess.py index d92cc2aa1f..f6230269fa 100644 --- a/src/calibre/ebooks/conversion/preprocess.py +++ b/src/calibre/ebooks/conversion/preprocess.py @@ -9,6 +9,7 @@ __docformat__ = 'restructuredtext en' import functools, re, json from calibre import entity_to_unicode, as_unicode +from polyglot.builtins import unicode_type XMLDECL_RE = re.compile(r'^\s*<[?]xml.*?[?]>') SVG_NS = 'http://www.w3.org/2000/svg' @@ -218,8 +219,8 @@ class Dehyphenator(object): wraptags = match.group('wraptags') except: wraptags = '' - hyphenated = unicode(firsthalf) + "-" + unicode(secondhalf) - dehyphenated = unicode(firsthalf) + unicode(secondhalf) + hyphenated = unicode_type(firsthalf) + "-" + unicode_type(secondhalf) + dehyphenated = unicode_type(firsthalf) + unicode_type(secondhalf) if self.suffixes.match(secondhalf) is None: lookupword = self.removesuffixes.sub('', dehyphenated) else: @@ -315,7 +316,7 @@ class CSSPreProcessor(object): # are commented lines before the first @import or @charset rule. Since # the conversion will remove all stylesheets anyway, we don't lose # anything - data = re.sub(unicode(r'/\*.*?\*/'), u'', data, flags=re.DOTALL) + data = re.sub(unicode_type(r'/\*.*?\*/'), u'', data, flags=re.DOTALL) ans, namespaced = [], False for line in data.splitlines(): diff --git a/src/calibre/ebooks/conversion/utils.py b/src/calibre/ebooks/conversion/utils.py index 886c9a97be..cdae26aed9 100644 --- a/src/calibre/ebooks/conversion/utils.py +++ b/src/calibre/ebooks/conversion/utils.py @@ -10,6 +10,7 @@ from math import ceil from calibre.ebooks.conversion.preprocess import DocAnalysis, Dehyphenator from calibre.utils.logging import default_log from calibre.utils.wordcount import get_wordcount_obj +from polyglot.builtins import unicode_type class HeuristicProcessor(object): @@ -50,8 +51,8 @@ class HeuristicProcessor(object): title = match.group('title') if not title: self.html_preprocess_sections = self.html_preprocess_sections + 1 - self.log.debug("marked " + unicode(self.html_preprocess_sections) + - " chapters. - " + unicode(chap)) + self.log.debug("marked " + unicode_type(self.html_preprocess_sections) + + " chapters. - " + unicode_type(chap)) return '

'+chap+'

\n' else: delete_whitespace = re.compile('^\\s*(?P.*?)\\s*$') @@ -59,16 +60,16 @@ class HeuristicProcessor(object): txt_chap = delete_quotes.sub('', delete_whitespace.sub('\\g', html2text(chap))) txt_title = delete_quotes.sub('', delete_whitespace.sub('\\g', html2text(title))) self.html_preprocess_sections = self.html_preprocess_sections + 1 - self.log.debug("marked " + unicode(self.html_preprocess_sections) + - " chapters & titles. - " + unicode(chap) + ", " + unicode(title)) + self.log.debug("marked " + unicode_type(self.html_preprocess_sections) + + " chapters & titles. - " + unicode_type(chap) + ", " + unicode_type(title)) return '

'+chap+'

\n

'+title+'

\n' def chapter_break(self, match): chap = match.group('section') styles = match.group('styles') self.html_preprocess_sections = self.html_preprocess_sections + 1 - self.log.debug("marked " + unicode(self.html_preprocess_sections) + - " section markers based on punctuation. - " + unicode(chap)) + self.log.debug("marked " + unicode_type(self.html_preprocess_sections) + + " section markers based on punctuation. - " + unicode_type(chap)) return '<'+styles+' style="page-break-before:always">'+chap def analyze_title_matches(self, match): @@ -111,8 +112,8 @@ class HeuristicProcessor(object): line_end = line_end_ere.findall(raw) tot_htm_ends = len(htm_end) tot_ln_fds = len(line_end) - # self.log.debug("There are " + unicode(tot_ln_fds) + " total Line feeds, and " + - # unicode(tot_htm_ends) + " marked up endings") + # self.log.debug("There are " + unicode_type(tot_ln_fds) + " total Line feeds, and " + + # unicode_type(tot_htm_ends) + " marked up endings") if percent > 1: percent = 1 @@ -120,7 +121,7 @@ class HeuristicProcessor(object): percent = 0 min_lns = tot_ln_fds * percent - # self.log.debug("There must be fewer than " + unicode(min_lns) + " unmarked lines to add markup") + # self.log.debug("There must be fewer than " + unicode_type(min_lns) + " unmarked lines to add markup") return min_lns > tot_htm_ends def dump(self, raw, where): @@ -157,17 +158,17 @@ class HeuristicProcessor(object): ] ITALICIZE_STYLE_PATS = [ - unicode(r'(?msu)(?<=[\s>"“\'‘])_\*/(?P[^\*_]+)/\*_'), - unicode(r'(?msu)(?<=[\s>"“\'‘])~~(?P[^~]+)~~'), - unicode(r'(?msu)(?<=[\s>"“\'‘])_/(?P[^/_]+)/_'), - unicode(r'(?msu)(?<=[\s>"“\'‘])_\*(?P[^\*_]+)\*_'), - unicode(r'(?msu)(?<=[\s>"“\'‘])\*/(?P[^/\*]+)/\*'), - unicode(r'(?msu)(?<=[\s>"“\'‘])/:(?P[^:/]+):/'), - unicode(r'(?msu)(?<=[\s>"“\'‘])\|:(?P[^:\|]+):\|'), - unicode(r'(?msu)(?<=[\s>"“\'‘])\*(?P[^\*]+)\*'), - unicode(r'(?msu)(?<=[\s>"“\'‘])~(?P[^~]+)~'), - unicode(r'(?msu)(?<=[\s>"“\'‘])/(?P[^/\*><]+)/'), - unicode(r'(?msu)(?<=[\s>"“\'‘])_(?P[^_]+)_'), + unicode_type(r'(?msu)(?<=[\s>"“\'‘])_\*/(?P[^\*_]+)/\*_'), + unicode_type(r'(?msu)(?<=[\s>"“\'‘])~~(?P[^~]+)~~'), + unicode_type(r'(?msu)(?<=[\s>"“\'‘])_/(?P[^/_]+)/_'), + unicode_type(r'(?msu)(?<=[\s>"“\'‘])_\*(?P[^\*_]+)\*_'), + unicode_type(r'(?msu)(?<=[\s>"“\'‘])\*/(?P[^/\*]+)/\*'), + unicode_type(r'(?msu)(?<=[\s>"“\'‘])/:(?P[^:/]+):/'), + unicode_type(r'(?msu)(?<=[\s>"“\'‘])\|:(?P[^:\|]+):\|'), + unicode_type(r'(?msu)(?<=[\s>"“\'‘])\*(?P[^\*]+)\*'), + unicode_type(r'(?msu)(?<=[\s>"“\'‘])~(?P[^~]+)~'), + unicode_type(r'(?msu)(?<=[\s>"“\'‘])/(?P[^/\*><]+)/'), + unicode_type(r'(?msu)(?<=[\s>"“\'‘])_(?P[^_]+)_'), ] for word in ITALICIZE_WORDS: @@ -177,10 +178,10 @@ class HeuristicProcessor(object): search_text = re.sub(r'<[^>]*>', '', search_text) for pat in ITALICIZE_STYLE_PATS: for match in re.finditer(pat, search_text): - ital_string = unicode(match.group('words')) - # self.log.debug("italicising "+unicode(match.group(0))+" with "+ital_string+"") + ital_string = unicode_type(match.group('words')) + # self.log.debug("italicising "+unicode_type(match.group(0))+" with "+ital_string+"") try: - html = re.sub(re.escape(unicode(match.group(0))), '%s' % ital_string, html) + html = re.sub(re.escape(unicode_type(match.group(0))), '%s' % ital_string, html) except OverflowError: # match.group(0) was too large to be compiled into a regex continue @@ -205,10 +206,10 @@ class HeuristicProcessor(object): if wordcount > 200000: typical_chapters = 15000. self.min_chapters = int(ceil(wordcount / typical_chapters)) - self.log.debug("minimum chapters required are: "+unicode(self.min_chapters)) + self.log.debug("minimum chapters required are: "+unicode_type(self.min_chapters)) heading = re.compile(']*>', re.IGNORECASE) self.html_preprocess_sections = len(heading.findall(html)) - self.log.debug("found " + unicode(self.html_preprocess_sections) + " pre-existing headings") + self.log.debug("found " + unicode_type(self.html_preprocess_sections) + " pre-existing headings") # Build the Regular Expressions in pieces init_lookahead = "(?=<(p|div))" @@ -295,7 +296,7 @@ class HeuristicProcessor(object): if n_lookahead_req: n_lookahead = re.sub("(ou|in|cha)", "lookahead_", full_chapter_line) if not analyze: - self.log.debug("Marked " + unicode(self.html_preprocess_sections) + " headings, " + log_message) + self.log.debug("Marked " + unicode_type(self.html_preprocess_sections) + " headings, " + log_message) chapter_marker = arg_ignorecase+init_lookahead+full_chapter_line+blank_lines+lp_n_lookahead_open+n_lookahead+lp_n_lookahead_close+ \ lp_opt_title_open+title_line_open+title_header_open+lp_title+title_header_close+title_line_close+lp_opt_title_close @@ -308,9 +309,9 @@ class HeuristicProcessor(object): if float(self.chapters_with_title) / float(hits) > .5: title_req = True strict_title = False - self.log.debug(unicode(type_name)+" had "+unicode(hits)+" hits - "+unicode(self.chapters_no_title)+" chapters with no title, "+ - unicode(self.chapters_with_title)+" chapters with titles, "+ - unicode(float(self.chapters_with_title) / float(hits))+" percent. ") + self.log.debug(unicode_type(type_name)+" had "+unicode_type(hits)+" hits - "+unicode_type(self.chapters_no_title)+" chapters with no title, "+ + unicode_type(self.chapters_with_title)+" chapters with titles, "+ + unicode_type(float(self.chapters_with_title) / float(hits))+" percent. ") if type_name == 'common': analysis_result.append([chapter_type, n_lookahead_req, strict_title, ignorecase, title_req, log_message, type_name]) elif self.min_chapters <= hits < max_chapters or self.min_chapters < 3 > hits: @@ -327,8 +328,8 @@ class HeuristicProcessor(object): words_per_chptr = wordcount if words_per_chptr > 0 and self.html_preprocess_sections > 0: words_per_chptr = wordcount / self.html_preprocess_sections - self.log.debug("Total wordcount is: "+ unicode(wordcount)+", Average words per section is: "+ - unicode(words_per_chptr)+", Marked up "+unicode(self.html_preprocess_sections)+" chapters") + self.log.debug("Total wordcount is: "+ unicode_type(wordcount)+", Average words per section is: "+ + unicode_type(words_per_chptr)+", Marked up "+unicode_type(self.html_preprocess_sections)+" chapters") return html def punctuation_unwrap(self, length, content, format): @@ -358,8 +359,8 @@ class HeuristicProcessor(object): # define the pieces of the regex # (?)?\\s*()?" blanklines = "\\s*(?P<(p|span|div)[^>]*>\\s*(<(p|span|div)[^>]*>\\s*\\s*)\\s*){0,3}\\s*" @@ -419,18 +420,18 @@ class HeuristicProcessor(object): return html def fix_nbsp_indents(self, html): - txtindent = re.compile(unicode(r'<(?Pp|div)(?P[^>]*)>\s*(?P(]*>\s*)+)?\s*(\u00a0){2,}'), re.IGNORECASE) + txtindent = re.compile(unicode_type(r'<(?Pp|div)(?P[^>]*)>\s*(?P(]*>\s*)+)?\s*(\u00a0){2,}'), re.IGNORECASE) html = txtindent.sub(self.insert_indent, html) if self.found_indents > 1: - self.log.debug("replaced "+unicode(self.found_indents)+ " nbsp indents with inline styles") + self.log.debug("replaced "+unicode_type(self.found_indents)+ " nbsp indents with inline styles") return html def cleanup_markup(self, html): # remove remaining non-breaking spaces - html = re.sub(unicode(r'\u00a0'), ' ', html) + html = re.sub(unicode_type(r'\u00a0'), ' ', html) # Get rid of various common microsoft specific tags which can cause issues later # Get rid of empty tags to simplify other processing - html = re.sub(unicode(r'\s*\s*'), ' ', html) + html = re.sub(unicode_type(r'\s*\s*'), ' ', html) # Delete microsoft 'smart' tags html = re.sub('(?i)', '', html) # Re-open self closing paragraph tags @@ -470,8 +471,8 @@ class HeuristicProcessor(object): blanklines = self.blankreg.findall(html) lines = self.linereg.findall(html) if len(lines) > 1: - self.log.debug("There are " + unicode(len(blanklines)) + " blank lines. " + - unicode(float(len(blanklines)) / float(len(lines))) + " percent blank") + self.log.debug("There are " + unicode_type(len(blanklines)) + " blank lines. " + + unicode_type(float(len(blanklines)) / float(len(lines))) + " percent blank") if float(len(blanklines)) / float(len(lines)) > 0.40: return True @@ -493,11 +494,11 @@ class HeuristicProcessor(object): lines = float(len(self.single_blank.findall(to_merge))) - 1. em = base_em + (em_per_line * lines) if to_merge.find('whitespace'): - newline = self.any_multi_blank.sub('\n

', match.group(0)) + newline = self.any_multi_blank.sub('\n

', match.group(0)) else: - newline = self.any_multi_blank.sub('\n

', match.group(0)) + newline = self.any_multi_blank.sub('\n

', match.group(0)) return newline html = self.any_multi_blank.sub(merge_matches, html) @@ -518,9 +519,9 @@ class HeuristicProcessor(object): top_margin = '' bottom_margin = '' if initblanks is not None: - top_margin = 'margin-top:'+unicode(len(self.single_blank.findall(initblanks)))+'em;' + top_margin = 'margin-top:'+unicode_type(len(self.single_blank.findall(initblanks)))+'em;' if endblanks is not None: - bottom_margin = 'margin-bottom:'+unicode(len(self.single_blank.findall(endblanks)))+'em;' + bottom_margin = 'margin-bottom:'+unicode_type(len(self.single_blank.findall(endblanks)))+'em;' if initblanks is None and endblanks is None: return content @@ -597,7 +598,7 @@ class HeuristicProcessor(object): else: replacement_break = re.sub('(?i)(width=\\d+\\%?|width:\\s*\\d+(\\%|px|pt|em)?;?)', '', replacement_break) divpercent = (100 - width) / 2 - hr_open = re.sub('45', unicode(divpercent), hr_open) + hr_open = re.sub('45', unicode_type(divpercent), hr_open) scene_break = hr_open+replacement_break+'' else: scene_break = hr_open+'
' @@ -657,12 +658,12 @@ class HeuristicProcessor(object): else: styles = match.group('styles').split(';') is_paragraph = self.check_paragraph(content) - # print "styles for this line are: "+unicode(styles) + # print "styles for this line are: "+unicode_type(styles) split_styles = [] for style in styles: - # print "style is: "+unicode(style) + # print "style is: "+unicode_type(style) newstyle = style.split(':') - # print "newstyle is: "+unicode(newstyle) + # print "newstyle is: "+unicode_type(newstyle) split_styles.append(newstyle) styles = split_styles for style, setting in styles: @@ -673,7 +674,7 @@ class HeuristicProcessor(object): if 9 < setting < 14: text_indent = indented_text else: - text_indent = style+':'+unicode(setting)+'pt;' + text_indent = style+':'+unicode_type(setting)+'pt;' if style == 'padding': setting = re.sub('pt', '', setting).split(' ') if int(setting[1]) < 16 and int(setting[3]) < 16: @@ -694,23 +695,23 @@ class HeuristicProcessor(object): blockquote_open_loop = blockquote_open if debugabby: self.log.debug('\n\n******\n') - self.log.debug('padding top is: '+unicode(setting[0])) - self.log.debug('padding right is:' +unicode(setting[1])) - self.log.debug('padding bottom is: ' + unicode(setting[2])) - self.log.debug('padding left is: ' +unicode(setting[3])) + self.log.debug('padding top is: '+unicode_type(setting[0])) + self.log.debug('padding right is:' +unicode_type(setting[1])) + self.log.debug('padding bottom is: ' + unicode_type(setting[2])) + self.log.debug('padding left is: ' +unicode_type(setting[3])) - # print "text-align is: "+unicode(text_align) - # print "\n***\nline is:\n "+unicode(match.group(0))+'\n' + # print "text-align is: "+unicode_type(text_align) + # print "\n***\nline is:\n "+unicode_type(match.group(0))+'\n' if debugabby: - # print "this line is a paragraph = "+unicode(is_paragraph)+", previous line was "+unicode(self.previous_was_paragraph) + # print "this line is a paragraph = "+unicode_type(is_paragraph)+", previous line was "+unicode_type(self.previous_was_paragraph) self.log.debug("styles for this line were:", styles) self.log.debug('newline is:') self.log.debug(blockquote_open_loop+blockquote_close_loop+ paragraph_before+'

'+content+'

'+paragraph_after+'\n\n\n\n\n') - # print "is_paragraph is "+unicode(is_paragraph)+", previous_was_paragraph is "+unicode(self.previous_was_paragraph) + # print "is_paragraph is "+unicode_type(is_paragraph)+", previous_was_paragraph is "+unicode_type(self.previous_was_paragraph) self.previous_was_paragraph = is_paragraph - # print "previous_was_paragraph is now set to "+unicode(self.previous_was_paragraph)+"\n\n\n" + # print "previous_was_paragraph is now set to "+unicode_type(self.previous_was_paragraph)+"\n\n\n" return blockquote_open_loop+blockquote_close_loop+paragraph_before+'

'+content+'

'+paragraph_after html = abbyy_line.sub(convert_styles, html) @@ -793,12 +794,12 @@ class HeuristicProcessor(object): # more of the lines break in the same region of the document then unwrapping is required docanalysis = DocAnalysis(format, html) hardbreaks = docanalysis.line_histogram(.50) - self.log.debug("Hard line breaks check returned "+unicode(hardbreaks)) + self.log.debug("Hard line breaks check returned "+unicode_type(hardbreaks)) # Calculate Length unwrap_factor = getattr(self.extra_opts, 'html_unwrap_factor', 0.4) length = docanalysis.line_length(unwrap_factor) - self.log.debug("Median line length is " + unicode(length) + ", calculated with " + format + " format") + self.log.debug("Median line length is " + unicode_type(length) + ", calculated with " + format + " format") # ##### Unwrap lines ###### if getattr(self.extra_opts, 'unwrap_lines', False): @@ -820,7 +821,7 @@ class HeuristicProcessor(object): # If still no sections after unwrapping mark split points on lines with no punctuation if self.html_preprocess_sections < self.min_chapters and getattr(self.extra_opts, 'markup_chapter_headings', False): self.log.debug("Looking for more split points based on punctuation," - " currently have " + unicode(self.html_preprocess_sections)) + " currently have " + unicode_type(self.html_preprocess_sections)) chapdetect3 = re.compile( r'<(?P(p|div)[^>]*)>\s*(?P
(]*>)?\s*(?!([\W]+\s*)+)(<[ibu][^>]*>){0,2}\s*(]*>)?\s*(<[ibu][^>]*>){0,2}\s*(]*>)?\s*.?(?=[a-z#\-*\s]+<)([a-z#-*]+\s*){1,5}\s*\s*()?(){0,2}\s*()?\s*(){0,2}\s*()?\s*)', re.IGNORECASE) # noqa html = chapdetect3.sub(self.chapter_break, html) diff --git a/src/calibre/ebooks/docx/container.py b/src/calibre/ebooks/docx/container.py index 448ceb97c7..8ba8b2ff83 100644 --- a/src/calibre/ebooks/docx/container.py +++ b/src/calibre/ebooks/docx/container.py @@ -20,6 +20,7 @@ from calibre.utils.localization import canonicalize_lang from calibre.utils.logging import default_log from calibre.utils.zipfile import ZipFile from calibre.ebooks.oeb.parse_utils import RECOVER_PARSER +from polyglot.builtins import unicode_type def fromstring(raw, parser=RECOVER_PARSER): @@ -56,7 +57,7 @@ def read_doc_props(raw, mi, XPath): desc = XPath('//dc:description')(root) if desc: - raw = etree.tostring(desc[0], method='text', encoding=unicode) + raw = etree.tostring(desc[0], method='text', encoding=unicode_type) raw = raw.replace('_x000d_', '') # Word 2007 mangles newlines in the summary mi.comments = raw.strip() diff --git a/src/calibre/ebooks/docx/fonts.py b/src/calibre/ebooks/docx/fonts.py index f92519ddb7..c21c202045 100644 --- a/src/calibre/ebooks/docx/fonts.py +++ b/src/calibre/ebooks/docx/fonts.py @@ -14,6 +14,7 @@ from calibre.utils.filenames import ascii_filename from calibre.utils.fonts.scanner import font_scanner, NoFonts from calibre.utils.fonts.utils import panose_to_css_generic_family, is_truetype_font from calibre.utils.icu import ord_string +from polyglot.builtins import codepoint_to_chr Embed = namedtuple('Embed', 'name key subsetted') @@ -124,7 +125,7 @@ def do_map(m, points): if base < p < limit: yield m[p - base] else: - yield unichr(p) + yield codepoint_to_chr(p) def map_symbol_text(text, font): diff --git a/src/calibre/ebooks/docx/index.py b/src/calibre/ebooks/docx/index.py index b4bd00b792..a4e8e0ec60 100644 --- a/src/calibre/ebooks/docx/index.py +++ b/src/calibre/ebooks/docx/index.py @@ -11,6 +11,7 @@ from operator import itemgetter from lxml import etree from calibre.utils.icu import partition_by_first_letter, sort_key +from polyglot.builtins import unicode_type def get_applicable_xe_fields(index, xe_fields, XPath, expand): @@ -246,7 +247,7 @@ def polish_index_markup(index, blocks): a = block.xpath('descendant::a[1]') text = '' if a: - text = etree.tostring(a[0], method='text', with_tail=False, encoding=unicode).strip() + text = etree.tostring(a[0], method='text', with_tail=False, encoding=unicode_type).strip() if ':' in text: path_map[block] = parts = filter(None, (x.strip() for x in text.split(':'))) if len(parts) > 1: diff --git a/src/calibre/ebooks/docx/tables.py b/src/calibre/ebooks/docx/tables.py index cd73562630..b2cb4b2346 100644 --- a/src/calibre/ebooks/docx/tables.py +++ b/src/calibre/ebooks/docx/tables.py @@ -504,8 +504,6 @@ class Table(object): def resolve_cell_style(self, tc, overrides, row, col, rows, cols_in_row): cs = CellStyle(self.namespace) - # from lxml.etree import tostring - # txt = tostring(tc, method='text', encoding=unicode) for o in overrides: if o in self.overrides: ovr = self.overrides[o] @@ -699,4 +697,3 @@ class Tables(object): table = self.para_map.get(p, None) if table is not None: return table.style_map.get(p, (None, None))[1] - diff --git a/src/calibre/ebooks/docx/toc.py b/src/calibre/ebooks/docx/toc.py index ad262904f0..239efb9baa 100644 --- a/src/calibre/ebooks/docx/toc.py +++ b/src/calibre/ebooks/docx/toc.py @@ -13,6 +13,7 @@ from lxml.etree import tostring from calibre.ebooks.metadata.toc import TOC from calibre.ebooks.oeb.polish.toc import elem_to_toc_text +from polyglot.builtins import unicode_type def from_headings(body, log, namespace): @@ -93,7 +94,7 @@ def link_to_txt(a, styles, object_map): if rs.css.get('display', None) == 'none': a.remove(child) - return tostring(a, method='text', with_tail=False, encoding=unicode).strip() + return tostring(a, method='text', with_tail=False, encoding=unicode_type).strip() def from_toc(docx, link_map, styles, object_map, log, namespace): diff --git a/src/calibre/ebooks/docx/writer/from_html.py b/src/calibre/ebooks/docx/writer/from_html.py index 93743fda5a..fb2997b672 100644 --- a/src/calibre/ebooks/docx/writer/from_html.py +++ b/src/calibre/ebooks/docx/writer/from_html.py @@ -19,6 +19,7 @@ from calibre.ebooks.docx.writer.lists import ListsManager from calibre.ebooks.oeb.stylizer import Stylizer as Sz, Style as St from calibre.ebooks.oeb.base import XPath, barename from calibre.utils.localization import lang_as_iso639_1 +from polyglot.builtins import unicode_type def lang_for_tag(tag): @@ -439,8 +440,8 @@ class Convert(object): if self.add_toc: self.links_manager.process_toc_links(self.oeb) - if self.add_cover and self.oeb.metadata.cover and unicode(self.oeb.metadata.cover[0]) in self.oeb.manifest.ids: - cover_id = unicode(self.oeb.metadata.cover[0]) + if self.add_cover and self.oeb.metadata.cover and unicode_type(self.oeb.metadata.cover[0]) in self.oeb.manifest.ids: + cover_id = unicode_type(self.oeb.metadata.cover[0]) item = self.oeb.manifest.ids[cover_id] self.cover_img = self.images_manager.read_image(item.href) diff --git a/src/calibre/ebooks/docx/writer/styles.py b/src/calibre/ebooks/docx/writer/styles.py index 9c532cdb2f..e57b558a30 100644 --- a/src/calibre/ebooks/docx/writer/styles.py +++ b/src/calibre/ebooks/docx/writer/styles.py @@ -14,6 +14,7 @@ from lxml import etree from calibre.ebooks import parse_css_length from calibre.ebooks.docx.writer.utils import convert_color, int_or_zero from calibre.utils.localization import lang_as_iso639_1 +from polyglot.builtins import unicode_type from tinycss.css21 import CSS21Parser css_parser = CSS21Parser() @@ -45,7 +46,7 @@ def bmap(x): def is_dropcaps(html_tag, tag_style): - return len(html_tag) < 2 and len(etree.tostring(html_tag, method='text', encoding=unicode, with_tail=False)) < 5 and tag_style['float'] == 'left' + return len(html_tag) < 2 and len(etree.tostring(html_tag, method='text', encoding=unicode_type, with_tail=False)) < 5 and tag_style['float'] == 'left' class CombinedStyle(object): diff --git a/src/calibre/ebooks/epub/cfi/tests.py b/src/calibre/ebooks/epub/cfi/tests.py index 969e69536d..a47074b54d 100644 --- a/src/calibre/ebooks/epub/cfi/tests.py +++ b/src/calibre/ebooks/epub/cfi/tests.py @@ -10,6 +10,7 @@ import unittest from polyglot.builtins import map from calibre.ebooks.epub.cfi.parse import parser, cfi_sort_key, decode_cfi +from polyglot.builtins import unicode_type class Tests(unittest.TestCase): @@ -60,7 +61,7 @@ class Tests(unittest.TestCase): if after is not None: ta['after'] = after if params: - ta['params'] = {unicode(k):(v,) if isinstance(v, unicode) else v for k, v in params.iteritems()} + ta['params'] = {unicode_type(k):(v,) if isinstance(v, unicode_type) else v for k, v in params.iteritems()} if ta: step['text_assertion'] = ta return ans diff --git a/src/calibre/ebooks/epub/periodical.py b/src/calibre/ebooks/epub/periodical.py index 3422fd6e60..8b39cfe681 100644 --- a/src/calibre/ebooks/epub/periodical.py +++ b/src/calibre/ebooks/epub/periodical.py @@ -11,6 +11,7 @@ import time from calibre.constants import __appname__, __version__ from calibre import strftime, prepare_string_for_xml as xml from calibre.utils.date import parse_date +from polyglot.builtins import unicode_type SONY_METADATA = u'''\ @@ -81,21 +82,21 @@ SONY_ATOM_ENTRY = u'''\ def sony_metadata(oeb): m = oeb.metadata - title = short_title = unicode(m.title[0]) + title = short_title = unicode_type(m.title[0]) publisher = __appname__ + ' ' + __version__ try: - pt = unicode(oeb.metadata.publication_type[0]) + pt = unicode_type(oeb.metadata.publication_type[0]) short_title = u':'.join(pt.split(':')[2:]) except: pass try: - date = parse_date(unicode(m.date[0]), + date = parse_date(unicode_type(m.date[0]), as_utc=False).strftime('%Y-%m-%d') except: date = strftime('%Y-%m-%d') try: - language = unicode(m.language[0]).replace('_', '-') + language = unicode_type(m.language[0]).replace('_', '-') except: language = 'en' short_title = xml(short_title, True) @@ -113,7 +114,7 @@ def sony_metadata(oeb): return True try: - base_id = unicode(list(filter(cal_id, m.identifier))[0]) + base_id = unicode_type(list(filter(cal_id, m.identifier))[0]) except: base_id = str(uuid4()) @@ -128,7 +129,7 @@ def sony_metadata(oeb): for x in toc: section.nodes.append(x) toc = TOC(klass='periodical', href=oeb.spine[2].href, - title=unicode(oeb.metadata.title[0])) + title=unicode_type(oeb.metadata.title[0])) toc.nodes.append(section) entries = [] @@ -188,4 +189,3 @@ def sony_metadata(oeb): id=xml(base_id)).encode('utf-8') return metadata, atom - diff --git a/src/calibre/ebooks/fb2/fb2ml.py b/src/calibre/ebooks/fb2/fb2ml.py index d01dd494d3..6fac9fdd84 100644 --- a/src/calibre/ebooks/fb2/fb2ml.py +++ b/src/calibre/ebooks/fb2/fb2ml.py @@ -19,6 +19,7 @@ from calibre.constants import __appname__, __version__ from calibre.utils.localization import lang_as_iso639_1 from calibre.utils.img import save_cover_data_to from calibre.ebooks.oeb.base import urlnormalize +from polyglot.builtins import unicode_type class FB2MLizer(object): @@ -64,7 +65,7 @@ class FB2MLizer(object): output = self.clean_text(u''.join(output)) if self.opts.pretty_print: - return u'\n%s' % etree.tostring(etree.fromstring(output), encoding=unicode, pretty_print=True) + return u'\n%s' % etree.tostring(etree.fromstring(output), encoding=unicode_type, pretty_print=True) else: return u'' + output @@ -140,7 +141,7 @@ class FB2MLizer(object): metadata['author'] = u'' metadata['keywords'] = u'' - tags = list(map(unicode, self.oeb_book.metadata.subject)) + tags = list(map(unicode_type, self.oeb_book.metadata.subject)) if tags: tags = ', '.join(prepare_string_for_xml(x) for x in tags) metadata['keywords'] = '%s'%tags @@ -155,8 +156,8 @@ class FB2MLizer(object): year = publisher = isbn = u'' identifiers = self.oeb_book.metadata['identifier'] for x in identifiers: - if x.get(OPF('scheme'), None).lower() == 'uuid' or unicode(x).startswith('urn:uuid:'): - metadata['id'] = unicode(x).split(':')[-1] + if x.get(OPF('scheme'), None).lower() == 'uuid' or unicode_type(x).startswith('urn:uuid:'): + metadata['id'] = unicode_type(x).split(':')[-1] break if metadata['id'] is None: self.log.warn('No UUID identifier found') @@ -229,8 +230,8 @@ class FB2MLizer(object): cover_href = None # Get the raster cover if it's available. - if self.oeb_book.metadata.cover and unicode(self.oeb_book.metadata.cover[0]) in self.oeb_book.manifest.ids: - id = unicode(self.oeb_book.metadata.cover[0]) + if self.oeb_book.metadata.cover and unicode_type(self.oeb_book.metadata.cover[0]) in self.oeb_book.manifest.ids: + id = unicode_type(self.oeb_book.metadata.cover[0]) cover_item = self.oeb_book.manifest.ids[id] if cover_item.media_type in OEB_RASTER_IMAGES: cover_href = cover_item.href diff --git a/src/calibre/ebooks/html/input.py b/src/calibre/ebooks/html/input.py index 3ee912cf0e..723fcc3688 100644 --- a/src/calibre/ebooks/html/input.py +++ b/src/calibre/ebooks/html/input.py @@ -19,6 +19,7 @@ from calibre.ebooks.oeb.base import urlunquote from calibre.ebooks.chardet import detect_xml_encoding from calibre.constants import iswindows from calibre import unicode_path, as_unicode, replace_entities +from polyglot.builtins import unicode_type class Link(object): @@ -46,7 +47,7 @@ class Link(object): :param base: The base directory that relative URLs are with respect to. Must be a unicode string. ''' - assert isinstance(url, unicode) and isinstance(base, unicode) + assert isinstance(url, unicode_type) and isinstance(base, unicode_type) self.url = url self.parsed_url = urlparse(self.url) self.is_local = self.parsed_url.scheme in ('', 'file') @@ -248,6 +249,3 @@ def get_filelist(htmlfile, dir, opts, log): for f in filelist: log.debug('\t\t', f) return filelist - - - diff --git a/src/calibre/ebooks/html/to_zip.py b/src/calibre/ebooks/html/to_zip.py index f6d6d53aff..56263ca7aa 100644 --- a/src/calibre/ebooks/html/to_zip.py +++ b/src/calibre/ebooks/html/to_zip.py @@ -11,6 +11,7 @@ import textwrap, os, glob from calibre.customize import FileTypePlugin from calibre.constants import numeric_version +from polyglot.builtins import unicode_type class HTML2ZIP(FileTypePlugin): @@ -114,10 +115,9 @@ every time you add an HTML file to the library.\ config_dialog.exec_() if config_dialog.result() == QDialog.Accepted: - sc = unicode(sc.text()).strip() + sc = unicode_type(sc.text()).strip() if bf.isChecked(): sc += '|bf' customize_plugin(self, sc) return config_dialog.result() - diff --git a/src/calibre/ebooks/htmlz/oeb2html.py b/src/calibre/ebooks/htmlz/oeb2html.py index cacaa6cc07..5797d31ae4 100644 --- a/src/calibre/ebooks/htmlz/oeb2html.py +++ b/src/calibre/ebooks/htmlz/oeb2html.py @@ -22,6 +22,7 @@ from calibre.ebooks.oeb.base import ( XHTML, XHTML_NS, barename, namespace, OEB_IMAGES, XLINK, rewrite_links, urlnormalize) from calibre.ebooks.oeb.stylizer import Stylizer from calibre.utils.logging import default_log +from polyglot.builtins import unicode_type SELF_CLOSING_TAGS = {'area', 'base', 'basefont', 'br', 'hr', 'input', 'img', 'link', 'meta'} @@ -46,7 +47,7 @@ class OEB2HTML(object): self.log.info('Converting OEB book to HTML...') self.opts = opts try: - self.book_title = unicode(oeb_book.metadata.title[0]) + self.book_title = unicode_type(oeb_book.metadata.title[0]) except Exception: self.book_title = _('Unknown') self.links = {} diff --git a/src/calibre/ebooks/lit/reader.py b/src/calibre/ebooks/lit/reader.py index adb3c7de72..276b97c9ff 100644 --- a/src/calibre/ebooks/lit/reader.py +++ b/src/calibre/ebooks/lit/reader.py @@ -22,6 +22,7 @@ from calibre.ebooks.oeb.base import urlnormalize, xpath from calibre.ebooks.oeb.reader import OEBReader from calibre.ebooks import DRMError from calibre import plugins +from polyglot.builtins import codepoint_to_chr, unicode_type lzx, lxzerror = plugins['lzx'] msdes, msdeserror = plugins['msdes'] @@ -110,7 +111,7 @@ def read_utf8_char(bytes, pos): raise LitError( 'Invalid UTF8 character: %s' % repr(bytes[pos:pos+i])) c = (c << 6) | (b & 0x3F) - return unichr(c), pos+elsize + return codepoint_to_chr(c), pos+elsize def consume_sized_utf8_string(bytes, zpad=False): @@ -125,7 +126,7 @@ def consume_sized_utf8_string(bytes, zpad=False): def encode(string): - return unicode(string).encode('ascii', 'xmlcharrefreplace') + return unicode_type(string).encode('ascii', 'xmlcharrefreplace') class UnBinary(object): @@ -243,9 +244,9 @@ class UnBinary(object): else: dynamic_tag += 1 errors += 1 - tag_name = '?'+unichr(tag)+'?' + tag_name = '?'+codepoint_to_chr(tag)+'?' current_map = self.tag_to_attr_map[tag] - print('WARNING: tag %s unknown' % unichr(tag)) + print('WARNING: tag %s unknown' % codepoint_to_chr(tag)) buf.write(encode(tag_name)) elif flags & FLAG_CLOSING: if depth == 0: @@ -947,4 +948,3 @@ class LitReader(OEBReader): item.media_type = 'application/xhtml+xml' item.data = item._parse_xhtml(etree.tostring(item.data)) super(LitReader, self)._spine_from_opf(opf) - diff --git a/src/calibre/ebooks/lit/writer.py b/src/calibre/ebooks/lit/writer.py index 3200f02fbe..64db77db9f 100644 --- a/src/calibre/ebooks/lit/writer.py +++ b/src/calibre/ebooks/lit/writer.py @@ -31,6 +31,7 @@ import calibre from calibre import plugins msdes, msdeserror = plugins['msdes'] import calibre.ebooks.lit.mssha1 as mssha1 +from polyglot.builtins import codepoint_to_chr, unicode_type __all__ = ['LitWriter'] @@ -163,9 +164,9 @@ class ReBinary(object): for value in values: if isinstance(value, (int, long)): try: - value = unichr(value) + value = codepoint_to_chr(value) except OverflowError: - self.logger.warn('Unicode overflow for integer:', value) + self.logger.warn('unicode_type overflow for integer:', value) value = u'?' self.buf.write(value.encode('utf-8')) @@ -216,9 +217,9 @@ class ReBinary(object): path, frag = urldefrag(value) if self.item: path = self.item.abshref(path) - prefix = unichr(3) + prefix = codepoint_to_chr(3) if path in self.manifest.hrefs: - prefix = unichr(2) + prefix = codepoint_to_chr(2) value = self.manifest.hrefs[path].id if frag: value = '#'.join((value, frag)) @@ -281,9 +282,9 @@ class ReBinary(object): self.logger.warn("More than six anchors in file %r. " "Some links may not work properly." % self.item.href) data = StringIO() - data.write(unichr(len(self.anchors)).encode('utf-8')) + data.write(codepoint_to_chr(len(self.anchors)).encode('utf-8')) for anchor, offset in self.anchors: - data.write(unichr(len(anchor)).encode('utf-8')) + data.write(codepoint_to_chr(len(anchor)).encode('utf-8')) data.write(anchor) data.write(pack(' 0 and self.link_level <= self.link_levels: for path in paths: @@ -336,7 +337,7 @@ class HTMLConverter(object): markupMassage=nmassage) except ConversionError as err: if 'Failed to coerce to unicode' in str(err): - raw = unicode(raw, 'utf8', 'replace') + raw = unicode_type(raw, 'utf8', 'replace') soup = BeautifulSoup(raw, convertEntities=BeautifulSoup.XHTML_ENTITIES, markupMassage=nmassage) @@ -359,7 +360,7 @@ class HTMLConverter(object): os.makedirs(tdir) try: dump = open(os.path.join(tdir, 'html2lrf-verbose.html'), 'wb') - dump.write(unicode(soup).encode('utf-8')) + dump.write(unicode_type(soup).encode('utf-8')) self.log.info(_('Written preprocessed HTML to ')+dump.name) dump.close() except: @@ -394,7 +395,7 @@ class HTMLConverter(object): self.log.info(_('\tConverting to BBeB...')) self.current_style = {} self.page_break_found = False - if not isinstance(path, unicode): + if not isinstance(path, unicode_type): path = path.decode(sys.getfilesystemencoding()) self.target_prefix = path self.previous_text = '\n' @@ -589,7 +590,7 @@ class HTMLConverter(object): if isinstance(c, HTMLConverter.IGNORED_TAGS): continue if isinstance(c, NavigableString): - text += unicode(c) + text += unicode_type(c) elif isinstance(c, Tag): if c.name.lower() == 'img' and c.has_key('alt'): # noqa alt_text += c['alt'] @@ -644,7 +645,7 @@ class HTMLConverter(object): para, text, path, fragment = link['para'], link['text'], link['path'], link['fragment'] ascii_text = text - if not isinstance(path, unicode): + if not isinstance(path, unicode_type): path = path.decode(sys.getfilesystemencoding()) if path in self.processed_files: if path+fragment in self.targets.keys(): @@ -1323,7 +1324,7 @@ class HTMLConverter(object): bl = str(self.current_block.blockStyle.attrs['blockwidth'])+'px' if 'em' in tag_css['text-indent']: bl = '10pt' - indent = self.unit_convert(unicode(tag_css['text-indent']), pts=True, base_length=bl) + indent = self.unit_convert(unicode_type(tag_css['text-indent']), pts=True, base_length=bl) if not indent: indent = 0 if indent > 0 and indent < 10 * self.minimum_indent: @@ -1482,7 +1483,7 @@ class HTMLConverter(object): enc = sys.getfilesystemencoding() if not enc: enc = 'utf8' - if isinstance(path, unicode): + if isinstance(path, unicode_type): path = path.encode(enc, 'replace') if os.access(path, os.R_OK) and os.path.isfile(path): if ext in ['png', 'jpg', 'bmp', 'jpeg']: @@ -1526,7 +1527,7 @@ class HTMLConverter(object): elif tagname in ['style', 'link']: ncss, npcss = {}, {} if tagname == 'style': - text = ''.join([unicode(i) for i in tag.findAll(text=True)]) + text = ''.join([unicode_type(i) for i in tag.findAll(text=True)]) css, pcss = self.parse_css(text) ncss.update(css) npcss.update(pcss) @@ -1559,7 +1560,7 @@ class HTMLConverter(object): if tag.contents: c = tag.contents[0] if isinstance(c, NavigableString): - c = unicode(c).replace('\r\n', '\n').replace('\r', '\n') + c = unicode_type(c).replace('\r\n', '\n').replace('\r', '\n') if c.startswith('\n'): c = c[1:] tag.contents[0] = NavigableString(c) @@ -1759,7 +1760,7 @@ class HTMLConverter(object): except Exception as err: self.log.warning(_('An error occurred while processing a table: %s. Ignoring table markup.')%repr(err)) self.log.exception('') - self.log.debug(_('Bad table:\n%s')%unicode(tag)[:300]) + self.log.debug(_('Bad table:\n%s')%unicode_type(tag)[:300]) self.in_table = False self.process_children(tag, tag_css, tag_pseudo_css) finally: @@ -1810,7 +1811,7 @@ class HTMLConverter(object): def process_file(path, options, logger): - if not isinstance(path, unicode): + if not isinstance(path, unicode_type): path = path.decode(sys.getfilesystemencoding()) path = os.path.abspath(path) default_title = filename_to_utf8(os.path.splitext(os.path.basename(path))[0]) @@ -1857,9 +1858,9 @@ def process_file(path, options, logger): for prop in ('author', 'author_sort', 'title', 'title_sort', 'publisher', 'freetext'): val = getattr(options, prop, None) - if val and not isinstance(val, unicode): + if val and not isinstance(val, unicode_type): soup = BeautifulSoup(val) - setattr(options, prop, unicode(soup)) + setattr(options, prop, unicode_type(soup)) title = (options.title, options.title_sort) author = (options.author, options.author_sort) @@ -1903,7 +1904,7 @@ def process_file(path, options, logger): options.force_page_break = fpb options.link_exclude = le options.page_break = pb - if not isinstance(options.chapter_regex, unicode): + if not isinstance(options.chapter_regex, unicode_type): options.chapter_regex = options.chapter_regex.decode(preferred_encoding) options.chapter_regex = re.compile(options.chapter_regex, re.IGNORECASE) fpba = options.force_page_break_attr.split(',') diff --git a/src/calibre/ebooks/lrf/html/table_as_image.py b/src/calibre/ebooks/lrf/html/table_as_image.py index d8dcd40fee..22aca5b0f8 100644 --- a/src/calibre/ebooks/lrf/html/table_as_image.py +++ b/src/calibre/ebooks/lrf/html/table_as_image.py @@ -11,6 +11,8 @@ from PyQt5.Qt import QUrl, QApplication, QSize, QEventLoop, \ QPainter, QImage, QObject, Qt from PyQt5.QtWebKitWidgets import QWebPage +from polyglot.builtins import unicode_type + class HTMLTableRenderer(QObject): @@ -67,7 +69,7 @@ class HTMLTableRenderer(QObject): def render_table(soup, table, css, base_dir, width, height, dpi, factor=1.0): head = '' for e in soup.findAll(['link', 'style']): - head += unicode(e)+'\n\n' + head += unicode_type(e)+'\n\n' style = '' for key, val in css.items(): style += key + ':%s;'%val @@ -83,7 +85,7 @@ def render_table(soup, table, css, base_dir, width, height, dpi, factor=1.0): %s - '''%(head, width-10, style, unicode(table)) + '''%(head, width-10, style, unicode_type(table)) images, tdir = do_render(html, base_dir, width, height, dpi, factor) atexit.register(shutil.rmtree, tdir) return images diff --git a/src/calibre/ebooks/lrf/lrfparser.py b/src/calibre/ebooks/lrf/lrfparser.py index 7315316eeb..1760de269a 100644 --- a/src/calibre/ebooks/lrf/lrfparser.py +++ b/src/calibre/ebooks/lrf/lrfparser.py @@ -10,6 +10,7 @@ from calibre.utils.filenames import ascii_filename from calibre.ebooks.lrf.meta import LRFMetaFile from calibre.ebooks.lrf.objects import get_object, PageTree, StyleObject, \ Font, Text, TOCObject, BookAttr, ruby_tags +from polyglot.builtins import unicode_type class LRFDocument(LRFMetaFile): @@ -112,7 +113,7 @@ class LRFDocument(LRFMetaFile): pages += u'\n'%(page_tree.id,) close = u'\n' for page in page_tree: - pages += unicode(page) + pages += unicode_type(page) pages += close traversed_objects = [int(i) for i in re.findall(r'objid="(\w+)"', pages)] + [pt_id] @@ -125,9 +126,9 @@ class LRFDocument(LRFMetaFile): if isinstance(obj, (Font, Text, TOCObject)): continue if isinstance(obj, StyleObject): - styles += unicode(obj) + styles += unicode_type(obj) else: - objects += unicode(obj) + objects += unicode_type(obj) styles += '\n' objects += '\n' if write_files: diff --git a/src/calibre/ebooks/lrf/meta.py b/src/calibre/ebooks/lrf/meta.py index 4f890c7c73..49e944a70d 100644 --- a/src/calibre/ebooks/lrf/meta.py +++ b/src/calibre/ebooks/lrf/meta.py @@ -20,6 +20,7 @@ import xml.dom.minidom as dom from functools import wraps from calibre.ebooks.metadata import MetaInformation, string_to_authors +from polyglot.builtins import unicode_type BYTE = "\n'%(self.style_id, self.id) for i in self: - s += unicode(i) + s += unicode_type(i) s += '\n\n' return s def __str__(self): - return unicode(self) + return unicode_type(self) def to_html(self): s = u'' @@ -619,7 +620,7 @@ class Block(LRFStream, TextCSS): s += '%s="%s" '%(attr, self.attrs[attr]) if self.name != 'ImageBlock': s = s.rstrip()+'>\n' - s += unicode(self.content) + s += unicode_type(self.content) s += '\n'%(self.name,) return s return s.rstrip() + ' />\n' @@ -717,7 +718,7 @@ class Text(LRFStream): lineposition_map = {1:'before', 2:'after'} def add_text(self, text): - s = unicode(text, "utf-16-le") + s = unicode_type(text, "utf-16-le") if s: s = s.translate(self.text_map) self.content.append(self.entity_pattern.sub(entity_to_unicode, s)) @@ -888,7 +889,7 @@ class Text(LRFStream): p = open_containers.pop() s += u''%(p.name,) else: - s += unicode(c) + s += unicode_type(c) if not c.self_closing: open_containers.append(c) @@ -1001,7 +1002,7 @@ class Canvas(LRFStream): s += '%s="%s" '%(attr, self.attrs[attr]) s = s.rstrip() + '>\n' for po in self: - s += unicode(po) + '\n' + s += unicode_type(po) + '\n' s += '\n'%(self.__class__.__name__,) return s @@ -1198,7 +1199,7 @@ class BookAttr(StyleObject, LRFObject): s += u'\n'%\ (self.binding_map[doc.binding], doc.dpi, doc.width, doc.height, doc.color_depth) for font in self._document.font_map.values(): - s += unicode(font) + s += unicode_type(font) s += '\n' return s @@ -1239,7 +1240,7 @@ class TOCObject(LRFStream): def __unicode__(self): s = u'\n' for i in self: - s += unicode(i) + s += unicode_type(i) return s + '\n' @@ -1288,5 +1289,3 @@ def get_object(document, stream, id, offset, size, scramble_key): return object_map[obj_type](document, stream, obj_id, scramble_key, offset+size-Tag.tags[0][0]) raise LRFParseError("Unknown object type: %02X!" % obj_type) - - diff --git a/src/calibre/ebooks/lrf/pylrs/elements.py b/src/calibre/ebooks/lrf/pylrs/elements.py index b727b9dd5b..08316eaa7d 100644 --- a/src/calibre/ebooks/lrf/pylrs/elements.py +++ b/src/calibre/ebooks/lrf/pylrs/elements.py @@ -1,5 +1,7 @@ """ elements.py -- replacements and helpers for ElementTree """ +from polyglot.builtins import unicode_type + class ElementWriter(object): @@ -21,9 +23,9 @@ class ElementWriter(object): return text def _writeAttribute(self, f, name, value): - f.write(u' %s="' % unicode(name)) + f.write(u' %s="' % unicode_type(name)) if not isinstance(value, basestring): - value = unicode(value) + value = unicode_type(value) value = self._encodeCdata(value) value = value.replace('"', '"') f.write(value) @@ -34,7 +36,7 @@ class ElementWriter(object): f.write(text) def _write(self, f, e): - f.write(u'<' + unicode(e.tag)) + f.write(u'<' + unicode_type(e.tag)) attributes = e.items() attributes.sort() @@ -72,6 +74,3 @@ class ElementWriter(object): f.write(u'\n' % self.outputEncodingName) self._write(f, self.e) - - - diff --git a/src/calibre/ebooks/lrf/tags.py b/src/calibre/ebooks/lrf/tags.py index 1767f1888a..f557a8886d 100644 --- a/src/calibre/ebooks/lrf/tags.py +++ b/src/calibre/ebooks/lrf/tags.py @@ -5,6 +5,7 @@ __copyright__ = '2008, Kovid Goyal ' import struct from calibre.ebooks.lrf import LRFParseError +from polyglot.builtins import unicode_type class Tag(object): @@ -246,7 +247,7 @@ class Tag(object): @classmethod def string_parser(self, stream): size = struct.unpack("''', r'<\1>', raw) doc = etree.fromstring(raw) return doc diff --git a/src/calibre/ebooks/metadata/imp.py b/src/calibre/ebooks/metadata/imp.py index 4e8c87c93a..d8991c8ea0 100644 --- a/src/calibre/ebooks/metadata/imp.py +++ b/src/calibre/ebooks/metadata/imp.py @@ -6,6 +6,7 @@ __copyright__ = '2008, Ashish Kulkarni ' import sys from calibre.ebooks.metadata import MetaInformation, string_to_authors +from polyglot.builtins import unicode_type MAGIC = ['\x00\x01BOOKDOUG', '\x00\x02BOOKDOUG'] @@ -43,6 +44,6 @@ def get_metadata(stream): if category: mi.category = category except Exception as err: - msg = u'Couldn\'t read metadata from imp: %s with error %s'%(mi.title, unicode(err)) + msg = u'Couldn\'t read metadata from imp: %s with error %s'%(mi.title, unicode_type(err)) print(msg.encode('utf8'), file=sys.stderr) return mi diff --git a/src/calibre/ebooks/metadata/kdl.py b/src/calibre/ebooks/metadata/kdl.py index e5b5847b35..c84eae04fa 100644 --- a/src/calibre/ebooks/metadata/kdl.py +++ b/src/calibre/ebooks/metadata/kdl.py @@ -14,11 +14,12 @@ from calibre.ebooks.metadata.book.base import Metadata from calibre import browser from calibre.ebooks.BeautifulSoup import BeautifulSoup from calibre.ebooks.chardet import xml_to_unicode +from polyglot.builtins import codepoint_to_chr, unicode_type URL = \ "http://ww2.kdl.org/libcat/WhatsNext.asp?AuthorLastName={0}&AuthorFirstName=&SeriesName=&BookTitle={1}&CategoryID=0&cmdSearch=Search&Search=1&grouping=" -_ignore_starts = u'\'"'+u''.join(unichr(x) for x in range(0x2018, 0x201e)+[0x2032, 0x2033]) +_ignore_starts = u'\'"'+u''.join(codepoint_to_chr(x) for x in range(0x2018, 0x201e)+[0x2032, 0x2033]) def get_series(title, authors, timeout=60): @@ -28,7 +29,7 @@ def get_series(title, authors, timeout=60): title = re.sub(r'^(A|The|An)\s+', '', title).strip() if not title: return mi - if isinstance(title, unicode): + if isinstance(title, unicode_type): title = title.encode('utf-8') title = urllib.quote_plus(title) @@ -73,7 +74,7 @@ def get_series(title, authors, timeout=60): mi.series = series ns = ss.nextSibling if ns.contents: - raw = unicode(ns.contents[0]) + raw = unicode_type(ns.contents[0]) raw = raw.partition('.')[0].strip() try: mi.series_index = int(raw) @@ -85,4 +86,3 @@ def get_series(title, authors, timeout=60): if __name__ == '__main__': import sys print(get_series(sys.argv[-2], [sys.argv[-1]])) - diff --git a/src/calibre/ebooks/metadata/kfx.py b/src/calibre/ebooks/metadata/kfx.py index 72625eea0b..d427c0a111 100644 --- a/src/calibre/ebooks/metadata/kfx.py +++ b/src/calibre/ebooks/metadata/kfx.py @@ -18,6 +18,7 @@ from calibre.utils.config_base import tweaks from calibre.utils.date import parse_only_date from calibre.utils.localization import canonicalize_lang from calibre.utils.imghdr import identify +from polyglot.builtins import unicode_type class InvalidKFX(ValueError): @@ -356,4 +357,4 @@ if __name__ == '__main__': from calibre import prints with open(sys.argv[-1], 'rb') as f: mi = read_metadata_kfx(f) - prints(unicode(mi)) + prints(unicode_type(mi)) diff --git a/src/calibre/ebooks/metadata/mobi.py b/src/calibre/ebooks/metadata/mobi.py index 71e1b3bfc6..26dcbe4793 100644 --- a/src/calibre/ebooks/metadata/mobi.py +++ b/src/calibre/ebooks/metadata/mobi.py @@ -21,6 +21,7 @@ from calibre.ebooks.mobi.langcodes import iana2mobi from calibre.utils.date import now as nowf from calibre.utils.imghdr import what from calibre.utils.localization import canonicalize_lang, lang_as_iso639_1 +from polyglot.builtins import unicode_type def is_image(ss): @@ -223,7 +224,7 @@ class MetadataUpdater(object): def create_exth(self, new_title=None, exth=None): # Add an EXTH block to record 0, rewrite the stream - if isinstance(new_title, unicode): + if isinstance(new_title, unicode_type): new_title = new_title.encode(self.codec, 'replace') # Fetch the existing title diff --git a/src/calibre/ebooks/metadata/opf2.py b/src/calibre/ebooks/metadata/opf2.py index 4089c9a6a2..0af4a40724 100644 --- a/src/calibre/ebooks/metadata/opf2.py +++ b/src/calibre/ebooks/metadata/opf2.py @@ -25,6 +25,7 @@ from calibre.utils.localization import get_lang, canonicalize_lang from calibre import prints, guess_type from calibre.utils.cleantext import clean_ascii_chars, clean_xml_chars from calibre.utils.config import tweaks +from polyglot.builtins import unicode_type pretty_print_opf = False @@ -82,7 +83,7 @@ class Resource(object): # {{{ self._href = href_or_path else: pc = url[2] - if isinstance(pc, unicode): + if isinstance(pc, unicode_type): pc = pc.encode('utf-8') pc = pc.decode('utf-8') self.path = os.path.abspath(os.path.join(basedir, pc.replace('/', os.sep))) @@ -103,7 +104,7 @@ class Resource(object): # {{{ basedir = os.getcwdu() if self.path is None: return self._href - f = self.fragment.encode('utf-8') if isinstance(self.fragment, unicode) else self.fragment + f = self.fragment.encode('utf-8') if isinstance(self.fragment, unicode_type) else self.fragment frag = '#'+f if self.fragment else '' if self.path == basedir: return ''+frag @@ -111,7 +112,7 @@ class Resource(object): # {{{ rpath = os.path.relpath(self.path, basedir) except ValueError: # On windows path and basedir could be on different drives rpath = self.path - if isinstance(rpath, unicode): + if isinstance(rpath, unicode_type): rpath = rpath.encode('utf-8') return rpath.replace(os.sep, '/')+frag @@ -206,10 +207,10 @@ class ManifestItem(Resource): # {{{ return u''%(self.id, self.href(), self.media_type) def __str__(self): - return unicode(self).encode('utf-8') + return unicode_type(self).encode('utf-8') def __repr__(self): - return unicode(self) + return unicode_type(self) def __getitem__(self, index): if index == 0: @@ -410,7 +411,7 @@ class Guide(ResourceCollection): # {{{ class MetadataField(object): def __init__(self, name, is_dc=True, formatter=None, none_is=None, - renderer=lambda x: unicode(x)): + renderer=lambda x: unicode_type(x)): self.name = name self.is_dc = is_dc self.formatter = formatter @@ -791,7 +792,7 @@ class OPF(object): # {{{ def unquote_urls(self): def get_href(item): raw = unquote(item.get('href', '')) - if not isinstance(raw, unicode): + if not isinstance(raw, unicode_type): raw = raw.decode('utf-8') return raw for item in self.itermanifest(): @@ -820,7 +821,7 @@ class OPF(object): # {{{ titles = () if val: title = titles[0] if titles else self.create_metadata_element('title') - title.text = re.sub(r'\s+', ' ', unicode(val)) + title.text = re.sub(r'\s+', ' ', unicode_type(val)) return property(fget=fget, fset=fset) @@ -869,7 +870,7 @@ class OPF(object): # {{{ for key in matches[0].attrib: if key.endswith('file-as'): matches[0].attrib.pop(key) - matches[0].set('{%s}file-as'%self.NAMESPACES['opf'], unicode(val)) + matches[0].set('{%s}file-as'%self.NAMESPACES['opf'], unicode_type(val)) return property(fget=fget, fset=fset) @@ -889,7 +890,7 @@ class OPF(object): # {{{ tag.getparent().remove(tag) for tag in val: elem = self.create_metadata_element('subject') - self.set_text(elem, unicode(tag)) + self.set_text(elem, unicode_type(tag)) return property(fget=fget, fset=fset) @@ -900,7 +901,7 @@ class OPF(object): # {{{ ans = None for match in self.pubdate_path(self.metadata): try: - val = parse_date(etree.tostring(match, encoding=unicode, + val = parse_date(etree.tostring(match, encoding=unicode_type, method='text', with_tail=False).strip()) except: continue @@ -912,7 +913,7 @@ class OPF(object): # {{{ least_val = least_elem = None for match in self.pubdate_path(self.metadata): try: - cval = parse_date(etree.tostring(match, encoding=unicode, + cval = parse_date(etree.tostring(match, encoding=unicode_type, method='text', with_tail=False).strip()) except: match.getparent().remove(match) @@ -962,7 +963,7 @@ class OPF(object): # {{{ attrib = {'{%s}scheme'%self.NAMESPACES['opf']: 'ISBN'} matches = [self.create_metadata_element('identifier', attrib=attrib)] - self.set_text(matches[0], unicode(val)) + self.set_text(matches[0], unicode_type(val)) return property(fget=fget, fset=fset) @@ -975,7 +976,7 @@ class OPF(object): # {{{ for attr, val in x.attrib.iteritems(): if attr.endswith('scheme'): typ = icu_lower(val) - val = etree.tostring(x, with_tail=False, encoding=unicode, + val = etree.tostring(x, with_tail=False, encoding=unicode_type, method='text').strip() if val and typ not in ('calibre', 'uuid'): if typ == 'isbn' and val.lower().startswith('urn:isbn:'): @@ -984,7 +985,7 @@ class OPF(object): # {{{ found_scheme = True break if not found_scheme: - val = etree.tostring(x, with_tail=False, encoding=unicode, + val = etree.tostring(x, with_tail=False, encoding=unicode_type, method='text').strip() if val.lower().startswith('urn:isbn:'): val = check_isbn(val.split(':')[-1]) @@ -1017,7 +1018,7 @@ class OPF(object): # {{{ for typ, val in identifiers.iteritems(): attrib = {'{%s}scheme'%self.NAMESPACES['opf']: typ.upper()} self.set_text(self.create_metadata_element( - 'identifier', attrib=attrib), unicode(val)) + 'identifier', attrib=attrib), unicode_type(val)) @dynamic_property def application_id(self): @@ -1041,7 +1042,7 @@ class OPF(object): # {{{ if uuid_id and uuid_id in removed_ids: attrib['id'] = uuid_id self.set_text(self.create_metadata_element( - 'identifier', attrib=attrib), unicode(val)) + 'identifier', attrib=attrib), unicode_type(val)) return property(fget=fget, fset=fset) @@ -1058,7 +1059,7 @@ class OPF(object): # {{{ attrib = {'{%s}scheme'%self.NAMESPACES['opf']: 'uuid'} matches = [self.create_metadata_element('identifier', attrib=attrib)] - self.set_text(matches[0], unicode(val)) + self.set_text(matches[0], unicode_type(val)) return property(fget=fget, fset=fset) @@ -1095,7 +1096,7 @@ class OPF(object): # {{{ for lang in val: l = self.create_metadata_element('language') - self.set_text(l, unicode(lang)) + self.set_text(l, unicode_type(lang)) return property(fget=fget, fset=fset) @@ -1118,7 +1119,7 @@ class OPF(object): # {{{ if not matches: matches = [self.create_metadata_element('contributor')] matches[0].set('{%s}role'%self.NAMESPACES['opf'], 'bkp') - self.set_text(matches[0], unicode(val)) + self.set_text(matches[0], unicode_type(val)) return property(fget=fget, fset=fset) def identifier_iter(self): @@ -1701,7 +1702,7 @@ def metadata_to_opf(mi, as_string=True, default_lang=None): metadata[-1].tail = '\n' +(' '*4) if mi.cover: - if not isinstance(mi.cover, unicode): + if not isinstance(mi.cover, unicode_type): mi.cover = mi.cover.decode(filesystem_encoding) guide.text = '\n'+(' '*8) r = guide.makeelement(OPF('reference'), diff --git a/src/calibre/ebooks/metadata/pdf.py b/src/calibre/ebooks/metadata/pdf.py index 47df33c415..01a524afcd 100644 --- a/src/calibre/ebooks/metadata/pdf.py +++ b/src/calibre/ebooks/metadata/pdf.py @@ -12,6 +12,7 @@ from calibre.ptempfile import TemporaryDirectory from calibre.ebooks.metadata import ( MetaInformation, string_to_authors, check_isbn, check_doi) from calibre.utils.ipc.simple_worker import fork_job, WorkerError +from polyglot.builtins import unicode_type def get_tools(): @@ -88,8 +89,8 @@ def page_images(pdfpath, outputdir, first=1, last=1): import win32process as w args['creationflags'] = w.HIGH_PRIORITY_CLASS | w.CREATE_NO_WINDOW try: - subprocess.check_call([pdftoppm, '-cropbox', '-jpeg', '-f', unicode(first), - '-l', unicode(last), pdfpath, + subprocess.check_call([pdftoppm, '-cropbox', '-jpeg', '-f', unicode_type(first), + '-l', unicode_type(last), pdfpath, os.path.join(outputdir, 'page-images')], **args) except subprocess.CalledProcessError as e: raise ValueError('Failed to render PDF, pdftoppm errorcode: %s'%e.returncode) diff --git a/src/calibre/ebooks/metadata/rb.py b/src/calibre/ebooks/metadata/rb.py index f16bad1de9..a193ae44d9 100644 --- a/src/calibre/ebooks/metadata/rb.py +++ b/src/calibre/ebooks/metadata/rb.py @@ -6,6 +6,7 @@ __copyright__ = '2008, Ashish Kulkarni ' import sys, struct from calibre.ebooks.metadata import MetaInformation, string_to_authors +from polyglot.builtins import unicode_type MAGIC = '\xb0\x0c\xb0\x0c\x02\x00NUVO\x00\x00\x00\x00' @@ -47,9 +48,7 @@ def get_metadata(stream): mi.author = value mi.authors = string_to_authors(value) except Exception as err: - msg = u'Couldn\'t read metadata from rb: %s with error %s'%(mi.title, unicode(err)) + msg = u'Couldn\'t read metadata from rb: %s with error %s'%(mi.title, unicode_type(err)) print(msg.encode('utf8'), file=sys.stderr) raise return mi - - diff --git a/src/calibre/ebooks/metadata/rtf.py b/src/calibre/ebooks/metadata/rtf.py index ff89681782..31b36ac850 100644 --- a/src/calibre/ebooks/metadata/rtf.py +++ b/src/calibre/ebooks/metadata/rtf.py @@ -8,6 +8,7 @@ import re, cStringIO, codecs from calibre import force_unicode from calibre.ebooks.metadata import MetaInformation, string_to_authors +from polyglot.builtins import codepoint_to_chr, unicode_type title_pat = re.compile(r'\{\\info.*?\{\\title(.*?)(? 0: wrapper.addprevious(etree.Element(XHTML('br'))) vspace -= 1 - if istate.halign != 'auto' and isinstance(istate.halign, (str, unicode)): + if istate.halign != 'auto' and isinstance(istate.halign, (str, unicode_type)): para.attrib['align'] = istate.halign istate.rendered = True pstate = bstate.istate diff --git a/src/calibre/ebooks/mobi/reader/headers.py b/src/calibre/ebooks/mobi/reader/headers.py index 433e80fbad..20cd94540d 100644 --- a/src/calibre/ebooks/mobi/reader/headers.py +++ b/src/calibre/ebooks/mobi/reader/headers.py @@ -16,6 +16,7 @@ from calibre.ebooks.mobi.langcodes import main_language, sub_language, mobi2iana from calibre.utils.cleantext import clean_ascii_chars, clean_xml_chars from calibre.utils.localization import canonicalize_lang from calibre.utils.config_base import tweaks +from polyglot.builtins import unicode_type NULL_INDEX = 0xffffffff @@ -239,7 +240,7 @@ class BookHeader(object): self.exth_flag, = struct.unpack('>L', raw[0x80:0x84]) self.exth = None - if not isinstance(self.title, unicode): + if not isinstance(self.title, unicode_type): self.title = self.title.decode(self.codec, 'replace') if self.exth_flag & 0x40: try: diff --git a/src/calibre/ebooks/mobi/reader/markup.py b/src/calibre/ebooks/mobi/reader/markup.py index 99cfb9cd53..a40b27838f 100644 --- a/src/calibre/ebooks/mobi/reader/markup.py +++ b/src/calibre/ebooks/mobi/reader/markup.py @@ -10,6 +10,7 @@ __docformat__ = 'restructuredtext en' import re, os from calibre.ebooks.chardet import strip_encoding_declarations +from polyglot.builtins import unicode_type def update_internal_links(mobi8_reader, log): @@ -130,7 +131,7 @@ def update_flow_links(mobi8_reader, resource_map, log): flows.append(flow) continue - if not isinstance(flow, unicode): + if not isinstance(flow, unicode_type): try: flow = flow.decode(mr.header.codec) except UnicodeDecodeError: diff --git a/src/calibre/ebooks/mobi/reader/mobi6.py b/src/calibre/ebooks/mobi/reader/mobi6.py index 8d0f2ce1ee..16b8a938b6 100644 --- a/src/calibre/ebooks/mobi/reader/mobi6.py +++ b/src/calibre/ebooks/mobi/reader/mobi6.py @@ -23,6 +23,7 @@ from calibre.ebooks.metadata.toc import TOC from calibre.ebooks.mobi.reader.headers import BookHeader from calibre.utils.img import save_cover_data_to from calibre.utils.imghdr import what +from polyglot.builtins import unicode_type class TopazError(ValueError): @@ -297,7 +298,7 @@ class MobiReader(object): with open('styles.css', 'wb') as s: s.write(self.base_css_rules + '\n\n') for cls, rule in self.tag_css_rules.items(): - if isinstance(rule, unicode): + if isinstance(rule, unicode_type): rule = rule.encode('utf-8') s.write('.%s { %s }\n\n' % (cls, rule)) diff --git a/src/calibre/ebooks/mobi/utils.py b/src/calibre/ebooks/mobi/utils.py index 899dffe942..69ef8f0b9f 100644 --- a/src/calibre/ebooks/mobi/utils.py +++ b/src/calibre/ebooks/mobi/utils.py @@ -14,6 +14,7 @@ from io import BytesIO from calibre.utils.img import save_cover_data_to, scale_image, image_to_data, image_from_data, resize_image from calibre.utils.imghdr import what from calibre.ebooks import normalize +from polyglot.builtins import unicode_type from tinycss.color3 import parse_color_string IMAGE_MAX_SIZE = 10 * 1024 * 1024 @@ -317,7 +318,7 @@ def utf8_text(text): ''' if text and text.strip(): text = text.strip() - if not isinstance(text, unicode): + if not isinstance(text, unicode_type): text = text.decode('utf-8', 'replace') text = normalize(text).encode('utf-8') else: @@ -625,7 +626,7 @@ def is_guide_ref_start(ref): def convert_color_for_font_tag(val): - rgba = parse_color_string(unicode(val or '')) + rgba = parse_color_string(unicode_type(val or '')) if rgba is None or rgba == 'currentColor': return val clamp = lambda x: min(x, max(0, x), 1) diff --git a/src/calibre/ebooks/mobi/writer2/main.py b/src/calibre/ebooks/mobi/writer2/main.py index 7d9acebb82..9de6427d68 100644 --- a/src/calibre/ebooks/mobi/writer2/main.py +++ b/src/calibre/ebooks/mobi/writer2/main.py @@ -20,6 +20,7 @@ from calibre.ebooks.mobi.writer2 import (PALMDOC, UNCOMPRESSED) from calibre.ebooks.mobi.utils import (encint, encode_trailing_data, align_block, detect_periodical, RECORD_SIZE, create_text_record) from calibre.ebooks.mobi.writer2.indexer import Indexer +from polyglot.builtins import unicode_type # Disabled as I dont care about uncrossable breaks WRITE_UNCROSSABLE_BREAKS = False @@ -52,7 +53,7 @@ class MobiWriter(object): self.log = oeb.log pt = None if oeb.metadata.publication_type: - x = unicode(oeb.metadata.publication_type[0]).split(':') + x = unicode_type(oeb.metadata.publication_type[0]).split(':') if len(x) > 1: pt = x[1].lower() self.publication_type = pt @@ -239,7 +240,7 @@ class MobiWriter(object): 0 # Unused )) # 0 - 15 (0x0 - 0xf) uid = random.randint(0, 0xffffffff) - title = normalize(unicode(metadata.title[0])).encode('utf-8') + title = normalize(unicode_type(metadata.title[0])).encode('utf-8') # 0x0 - 0x3 record0.write(b'MOBI') @@ -459,7 +460,7 @@ class MobiWriter(object): ''' Write the PalmDB header ''' - title = ascii_filename(unicode(self.oeb.metadata.title[0])).replace( + title = ascii_filename(unicode_type(self.oeb.metadata.title[0])).replace( ' ', '_')[:31] title = title + (b'\0' * (32 - len(title))) now = int(time.time()) @@ -476,5 +477,3 @@ class MobiWriter(object): def write_content(self): for record in self.records: self.write(record) - - diff --git a/src/calibre/ebooks/mobi/writer2/resources.py b/src/calibre/ebooks/mobi/writer2/resources.py index 661ffc1f48..ebb0d45c68 100644 --- a/src/calibre/ebooks/mobi/writer2/resources.py +++ b/src/calibre/ebooks/mobi/writer2/resources.py @@ -16,6 +16,7 @@ from calibre.ebooks import generate_masthead from calibre.ebooks.oeb.base import OEB_RASTER_IMAGES from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.imghdr import what +from polyglot.builtins import unicode_type PLACEHOLDER_GIF = b'GIF89a\x01\x00\x01\x00\xf0\x00\x00\x00\x00\x00\xff\xff\xff!\xf9\x04\x01\x00\x00\x00\x00!\xfe calibre-placeholder-gif-for-azw3\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;' # noqa @@ -72,7 +73,7 @@ class Resources(object): self.image_indices.add(0) elif self.is_periodical: # Generate a default masthead - data = generate_masthead(unicode(self.oeb.metadata['title'][0])) + data = generate_masthead(unicode_type(self.oeb.metadata['title'][0])) self.records.append(data) self.used_image_indices.add(0) self.image_indices.add(0) @@ -80,8 +81,8 @@ class Resources(object): cover_href = self.cover_offset = self.thumbnail_offset = None if (oeb.metadata.cover and - unicode(oeb.metadata.cover[0]) in oeb.manifest.ids): - cover_id = unicode(oeb.metadata.cover[0]) + unicode_type(oeb.metadata.cover[0]) in oeb.manifest.ids): + cover_id = unicode_type(oeb.metadata.cover[0]) item = oeb.manifest.ids[cover_id] cover_href = item.href @@ -156,4 +157,3 @@ class Resources(object): def __bool__(self): return bool(self.records) __nonzero__ = __bool__ - diff --git a/src/calibre/ebooks/mobi/writer2/serializer.py b/src/calibre/ebooks/mobi/writer2/serializer.py index 5628cb37de..ab6551d522 100644 --- a/src/calibre/ebooks/mobi/writer2/serializer.py +++ b/src/calibre/ebooks/mobi/writer2/serializer.py @@ -13,6 +13,7 @@ from calibre.ebooks.oeb.base import (OEB_DOCS, XHTML, XHTML_NS, XML_NS, namespace, prefixname, urlnormalize) from calibre.ebooks.mobi.mobiml import MBP_NS from calibre.ebooks.mobi.utils import is_guide_ref_start +from polyglot.builtins import unicode_type from collections import defaultdict from urlparse import urldefrag @@ -220,7 +221,7 @@ class Serializer(object): buf.write('
') else: t = tocref.title - if isinstance(t, unicode): + if isinstance(t, unicode_type): t = t.encode('utf-8') buf.write('

' + t + '

') @@ -240,7 +241,7 @@ class Serializer(object): buf.write('0000000000') buf.write(' >') t = tocitem.title - if isinstance(t, unicode): + if isinstance(t, unicode_type): t = t.encode('utf-8') buf.write(t) buf.write('') @@ -358,7 +359,7 @@ class Serializer(object): text = text.replace(u'\u00AD', '') # Soft-hyphen if quot: text = text.replace('"', '"') - if isinstance(text, unicode): + if isinstance(text, unicode_type): text = unicodedata.normalize('NFC', text) self.buf.write(text.encode('utf-8')) @@ -384,5 +385,3 @@ class Serializer(object): for hoff in hoffs: buf.seek(hoff) buf.write(b'%010d' % ioff) - - diff --git a/src/calibre/ebooks/mobi/writer8/exth.py b/src/calibre/ebooks/mobi/writer8/exth.py index 6a068aec33..300ccf302d 100644 --- a/src/calibre/ebooks/mobi/writer8/exth.py +++ b/src/calibre/ebooks/mobi/writer8/exth.py @@ -15,6 +15,7 @@ from calibre.constants import iswindows, isosx from calibre.ebooks.mobi.utils import (utf8_text, to_base) from calibre.utils.localization import lang_as_iso639_1 from calibre.ebooks.metadata import authors_to_sort_string +from polyglot.builtins import unicode_type EXTH_CODES = { 'creator': 100, @@ -62,14 +63,14 @@ def build_exth(metadata, prefer_author_sort=False, is_periodical=False, items = metadata[term] if term == 'creator': if prefer_author_sort: - creators = [authors_to_sort_string([unicode(c)]) for c in + creators = [authors_to_sort_string([unicode_type(c)]) for c in items] else: - creators = [unicode(c) for c in items] + creators = [unicode_type(c) for c in items] items = creators elif term == 'rights': try: - rights = utf8_text(unicode(metadata.rights[0])) + rights = utf8_text(unicode_type(metadata.rights[0])) except: rights = b'Unknown' exth.write(pack(b'>II', EXTH_CODES['rights'], len(rights) + 8)) @@ -78,7 +79,7 @@ def build_exth(metadata, prefer_author_sort=False, is_periodical=False, continue for item in items: - data = unicode(item) + data = unicode_type(item) if term != 'description': data = COLLAPSE_RE.sub(' ', data) if term == 'identifier': @@ -102,14 +103,14 @@ def build_exth(metadata, prefer_author_sort=False, is_periodical=False, from calibre.ebooks.oeb.base import OPF for x in metadata['identifier']: if (x.get(OPF('scheme'), None).lower() == 'uuid' or - unicode(x).startswith('urn:uuid:')): - uuid = unicode(x).split(':')[-1] + unicode_type(x).startswith('urn:uuid:')): + uuid = unicode_type(x).split(':')[-1] break if uuid is None: from uuid import uuid4 uuid = str(uuid4()) - if isinstance(uuid, unicode): + if isinstance(uuid, unicode_type): uuid = uuid.encode('utf-8') if not share_not_sync: exth.write(pack(b'>II', 113, len(uuid) + 8)) diff --git a/src/calibre/ebooks/mobi/writer8/index.py b/src/calibre/ebooks/mobi/writer8/index.py index 12905d5858..b97f0051b4 100644 --- a/src/calibre/ebooks/mobi/writer8/index.py +++ b/src/calibre/ebooks/mobi/writer8/index.py @@ -11,7 +11,7 @@ __docformat__ = 'restructuredtext en' from collections import namedtuple from struct import pack from io import BytesIO -from polyglot.builtins import zip +from polyglot.builtins import unicode_type, zip from calibre.ebooks.mobi.utils import CNCX, encint, align_block from calibre.ebooks.mobi.writer8.header import Header @@ -146,7 +146,7 @@ class Index(object): # {{{ for i, (index_num, tags) in enumerate(self.entries): control_bytes = self.control_bytes[i] buf.seek(0), buf.truncate(0) - index_num = (index_num.encode('utf-8') if isinstance(index_num, unicode) else index_num) + index_num = (index_num.encode('utf-8') if isinstance(index_num, unicode_type) else index_num) raw = bytearray(index_num) raw.insert(0, len(index_num)) buf.write(bytes(raw)) diff --git a/src/calibre/ebooks/mobi/writer8/main.py b/src/calibre/ebooks/mobi/writer8/main.py index 9749c49a0d..d66ec8b318 100644 --- a/src/calibre/ebooks/mobi/writer8/main.py +++ b/src/calibre/ebooks/mobi/writer8/main.py @@ -31,6 +31,7 @@ from calibre.ebooks.mobi.writer8.index import (NCXIndex, SkelIndex, from calibre.ebooks.mobi.writer8.mobi import KF8Book from calibre.ebooks.mobi.writer8.tbs import apply_trailing_byte_sequences from calibre.ebooks.mobi.writer8.toc import TOCAdder +from polyglot.builtins import unicode_type XML_DOCS = OEB_DOCS | {SVG_MIME} @@ -235,7 +236,7 @@ class KF8Writer(object): root = self.data(item) for svg in XPath('//svg:svg')(root): - raw = etree.tostring(svg, encoding=unicode, with_tail=False) + raw = etree.tostring(svg, encoding=unicode_type, with_tail=False) idx = len(self.flows) self.flows.append(raw) p = svg.getparent() @@ -333,7 +334,7 @@ class KF8Writer(object): self.flows[0] = chunker.text def create_text_records(self): - self.flows = [x.encode('utf-8') if isinstance(x, unicode) else x for x + self.flows = [x.encode('utf-8') if isinstance(x, unicode_type) else x for x in self.flows] text = b''.join(self.flows) self.text_length = len(text) diff --git a/src/calibre/ebooks/mobi/writer8/mobi.py b/src/calibre/ebooks/mobi/writer8/mobi.py index 3aa535424a..c88523b5fc 100644 --- a/src/calibre/ebooks/mobi/writer8/mobi.py +++ b/src/calibre/ebooks/mobi/writer8/mobi.py @@ -16,6 +16,7 @@ from calibre.ebooks.mobi.writer2 import (PALMDOC, UNCOMPRESSED) from calibre.ebooks.mobi.langcodes import iana2mobi from calibre.ebooks.mobi.writer8.exth import build_exth from calibre.utils.filenames import ascii_filename +from polyglot.builtins import unicode_type NULL_INDEX = 0xffffffff FLIS = b'FLIS\0\0\0\x08\0\x41\0\0\0\0\0\0\xff\xff\xff\xff\0\x01\0\x03\0\0\0\x03\0\0\0\x01'+ b'\xff'*4 @@ -282,7 +283,7 @@ class KF8Book(object): # Miscellaneous header fields self.compression = writer.compress self.book_type = 0x101 if writer.opts.mobi_periodical else 2 - self.full_title = utf8_text(unicode(metadata.title[0])) + self.full_title = utf8_text(unicode_type(metadata.title[0])) self.title_length = len(self.full_title) self.extra_data_flags = 0b1 if writer.has_tbs: diff --git a/src/calibre/ebooks/mobi/writer8/skeleton.py b/src/calibre/ebooks/mobi/writer8/skeleton.py index 064a39d522..fd5f943e29 100644 --- a/src/calibre/ebooks/mobi/writer8/skeleton.py +++ b/src/calibre/ebooks/mobi/writer8/skeleton.py @@ -17,6 +17,7 @@ from lxml import etree from calibre.ebooks.oeb.base import XHTML_NS, extract from calibre.constants import ispy3 from calibre.ebooks.mobi.utils import to_base +from polyglot.builtins import unicode_type CHUNK_SIZE = 8192 @@ -72,7 +73,7 @@ def tostring(raw, **kwargs): xml_declaration = kwargs.pop('xml_declaration', False) encoding = kwargs.pop('encoding', 'UTF-8') - kwargs['encoding'] = unicode + kwargs['encoding'] = unicode_type kwargs['xml_declaration'] = False ans = etree.tostring(raw, **kwargs) if xml_declaration: diff --git a/src/calibre/ebooks/odt/input.py b/src/calibre/ebooks/odt/input.py index f2ae22839e..7f02d187b6 100644 --- a/src/calibre/ebooks/odt/input.py +++ b/src/calibre/ebooks/odt/input.py @@ -19,6 +19,7 @@ from odf.namespaces import TEXTNS as odTEXTNS from calibre import CurrentDir, walk from calibre.ebooks.oeb.base import _css_logger +from polyglot.builtins import unicode_type class Extract(ODF2XHTML): @@ -172,7 +173,7 @@ class Extract(ODF2XHTML): css = style.text if css: css, sel_map = self.do_filter_css(css) - if not isinstance(css, unicode): + if not isinstance(css, unicode_type): css = css.decode('utf-8', 'ignore') style.text = css for x in root.xpath('//*[@class]'): diff --git a/src/calibre/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py index 1bd58de4d5..d6a7013f57 100644 --- a/src/calibre/ebooks/oeb/base.py +++ b/src/calibre/ebooks/oeb/base.py @@ -22,6 +22,7 @@ from calibre.ebooks.oeb.parse_utils import (barename, XHTML_NS, RECOVER_PARSER, namespace, XHTML, parse_html, NotHTML) from calibre.utils.cleantext import clean_xml_chars from calibre.utils.short_uuid import uuid4 +from polyglot.builtins import unicode_type XML_NS = 'http://www.w3.org/XML/1998/namespace' OEB_DOC_NS = 'http://openebook.org/namespaces/oeb-document/1.0/' @@ -376,7 +377,7 @@ def xml2unicode(root, pretty_print=False): def xml2text(elem): - return etree.tostring(elem, method='text', encoding=unicode, with_tail=False) + return etree.tostring(elem, method='text', encoding=unicode_type, with_tail=False) def escape_cdata(root): @@ -398,11 +399,11 @@ def serialize(data, media_type, pretty_print=False): # incorrectly by some browser based renderers ans = close_self_closing_tags(ans) return ans - if isinstance(data, unicode): + if isinstance(data, unicode_type): return data.encode('utf-8') if hasattr(data, 'cssText'): data = data.cssText - if isinstance(data, unicode): + if isinstance(data, unicode_type): data = data.encode('utf-8') return data + b'\n' return bytes(data) @@ -421,7 +422,7 @@ def urlquote(href): That is, this function returns valid IRIs not valid URIs. In particular, IRIs can contain non-ascii characters. """ result = [] - unsafe = 0 if isinstance(href, unicode) else 1 + unsafe = 0 if isinstance(href, unicode_type) else 1 unsafe = URL_UNSAFE[unsafe] for char in href: if char in unsafe: @@ -435,7 +436,7 @@ def urlunquote(href, error_handling='strict'): # If it runs on a unicode object, it returns a double encoded unicode # string: unquote(u'%C3%A4') != unquote(b'%C3%A4').decode('utf-8') # and the latter is correct - want_unicode = isinstance(href, unicode) + want_unicode = isinstance(href, unicode_type) if want_unicode: href = href.encode('utf-8') href = unquote(href) @@ -555,7 +556,7 @@ class DirContainer(object): # If it runs on a unicode object, it returns a double encoded unicode # string: unquote(u'%C3%A4') != unquote(b'%C3%A4').decode('utf-8') # and the latter is correct - if isinstance(path, unicode): + if isinstance(path, unicode_type): path = path.encode('utf-8') return urlunquote(path).decode('utf-8') @@ -593,13 +594,13 @@ class DirContainer(object): def namelist(self): names = [] base = self.rootdir - if isinstance(base, unicode): + if isinstance(base, unicode_type): base = base.encode(filesystem_encoding) for root, dirs, files in os.walk(base): for fname in files: fname = os.path.join(root, fname) fname = fname.replace('\\', '/') - if not isinstance(fname, unicode): + if not isinstance(fname, unicode_type): try: fname = fname.decode(filesystem_encoding) except: @@ -745,7 +746,7 @@ class Metadata(object): % (barename(self.term), self.value, self.attrib) def __str__(self): - return unicode(self.value).encode('ascii', 'xmlcharrefreplace') + return unicode_type(self.value).encode('ascii', 'xmlcharrefreplace') def __unicode__(self): return as_unicode(self.value) @@ -914,7 +915,7 @@ class Manifest(object): def __init__(self, oeb, id, href, media_type, fallback=None, loader=str, data=None): if href: - href = unicode(href) + href = unicode_type(href) self.oeb = oeb self.id = id self.href = self.path = urlnormalize(href) @@ -964,7 +965,7 @@ class Manifest(object): title = self.oeb.metadata.title if title: - title = unicode(title[0]) + title = unicode_type(title[0]) else: title = _('Unknown') @@ -997,7 +998,7 @@ class Manifest(object): self.oeb.logger.warn('CSS import of non-CSS file %r' % path) return (None, None) data = item.data.cssText - enc = None if isinstance(data, unicode) else 'utf-8' + enc = None if isinstance(data, unicode_type) else 'utf-8' return (enc, data) # }}} @@ -1081,11 +1082,11 @@ class Manifest(object): data = self.data if isinstance(data, etree._Element): return xml2unicode(data, pretty_print=self.oeb.pretty_print) - if isinstance(data, unicode): + if isinstance(data, unicode_type): return data if hasattr(data, 'cssText'): return data.cssText - return unicode(data) + return unicode_type(data) def __eq__(self, other): return id(self) == id(other) @@ -1203,7 +1204,7 @@ class Manifest(object): while href.lower() in lhrefs: href = base + str(index) + ext index += 1 - return id, unicode(href) + return id, unicode_type(href) def __iter__(self): for item in self.items: @@ -1436,7 +1437,7 @@ class Guide(object): def add(self, type, title, href): """Add a new reference to the `Guide`.""" if href: - href = unicode(href) + href = unicode_type(href) ref = self.Reference(self.oeb, type, title, href) self.refs[type] = ref return ref @@ -1707,7 +1708,7 @@ class PageList(object): TYPES = {'front', 'normal', 'special'} def __init__(self, name, href, type='normal', klass=None, id=None): - self.name = unicode(name) + self.name = unicode_type(name) self.href = urlnormalize(href) self.type = type if type in self.TYPES else 'normal' self.id = id @@ -1845,7 +1846,7 @@ class OEBBook(object): """Automatically decode :param:`data` into a `unicode` object.""" def fix_data(d): return d.replace('\r\n', '\n').replace('\r', '\n') - if isinstance(data, unicode): + if isinstance(data, unicode_type): return fix_data(data) bom_enc = None if data[:4] in ('\0\0\xfe\xff', '\xff\xfe\0\0'): @@ -1923,14 +1924,14 @@ class OEBBook(object): return def _to_ncx(self): - lang = unicode(self.metadata.language[0]) + lang = unicode_type(self.metadata.language[0]) lang = lang.replace('_', '-') ncx = etree.Element(NCX('ncx'), attrib={'version': '2005-1', XML('lang'): lang}, nsmap={None: NCX_NS}) head = etree.SubElement(ncx, NCX('head')) etree.SubElement(head, NCX('meta'), - name='dtb:uid', content=unicode(self.uid)) + name='dtb:uid', content=unicode_type(self.uid)) etree.SubElement(head, NCX('meta'), name='dtb:depth', content=str(self.toc.depth())) generator = ''.join(['calibre (', __version__, ')']) @@ -1942,7 +1943,7 @@ class OEBBook(object): name='dtb:maxPageNumber', content='0') title = etree.SubElement(ncx, NCX('docTitle')) text = etree.SubElement(title, NCX('text')) - text.text = unicode(self.metadata.title[0]) + text.text = unicode_type(self.metadata.title[0]) navmap = etree.SubElement(ncx, NCX('navMap')) self.toc.to_ncx(navmap) if len(self.pages) > 0: diff --git a/src/calibre/ebooks/oeb/iterator/bookmarks.py b/src/calibre/ebooks/oeb/iterator/bookmarks.py index 9141b7cb46..841d409ccb 100644 --- a/src/calibre/ebooks/oeb/iterator/bookmarks.py +++ b/src/calibre/ebooks/oeb/iterator/bookmarks.py @@ -11,6 +11,7 @@ import os from io import BytesIO from calibre.utils.zipfile import safe_replace +from polyglot.builtins import unicode_type BM_FIELD_SEP = u'*|!|?|*' BM_LEGACY_ESC = u'esc-text-%&*#%(){}ads19-end-esc' @@ -59,10 +60,10 @@ class BookmarksMixin(object): else: pos = bm['pos'] if isinstance(pos, (int, float)): - pos = unicode(pos) + pos = unicode_type(pos) else: pos = pos.replace(u'^', BM_LEGACY_ESC) - rec = BM_FIELD_SEP.join([bm['title'], unicode(bm['spine']), pos]) + rec = BM_FIELD_SEP.join([bm['title'], unicode_type(bm['spine']), pos]) dat.append(rec) return (u'\n'.join(dat) +u'\n') @@ -102,5 +103,3 @@ class BookmarksMixin(object): def set_bookmarks(self, bookmarks): self.bookmarks = bookmarks - - diff --git a/src/calibre/ebooks/oeb/iterator/spine.py b/src/calibre/ebooks/oeb/iterator/spine.py index c102b281bf..f81a2244d0 100644 --- a/src/calibre/ebooks/oeb/iterator/spine.py +++ b/src/calibre/ebooks/oeb/iterator/spine.py @@ -2,7 +2,7 @@ # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai from __future__ import (unicode_literals, division, absolute_import, print_function) -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type __license__ = 'GPL v3' __copyright__ = '2012, Kovid Goyal ' @@ -45,7 +45,7 @@ def all_links(html): return ans -class SpineItem(unicode): +class SpineItem(unicode_type): def __new__(cls, path, mime_type=None, read_anchor_map=True, run_char_count=True, from_epub=False, read_links=True): @@ -149,5 +149,3 @@ def create_indexing_data(spine, toc): start = i.anchor if i.spine_pos == spine_pos else None end = i.end_anchor if i.spine_pos == spine_pos else None spine_item.index_entries.append(ie(i, start, end)) - - diff --git a/src/calibre/ebooks/oeb/parse_utils.py b/src/calibre/ebooks/oeb/parse_utils.py index 8d97b88a7b..94b369471e 100644 --- a/src/calibre/ebooks/oeb/parse_utils.py +++ b/src/calibre/ebooks/oeb/parse_utils.py @@ -14,6 +14,7 @@ from lxml import etree, html from calibre import xml_replace_entities, force_unicode from calibre.constants import filesystem_encoding from calibre.ebooks.chardet import xml_to_unicode, strip_encoding_declarations +from polyglot.builtins import unicode_type RECOVER_PARSER = etree.XMLParser(recover=True, no_network=True) XHTML_NS = 'http://www.w3.org/1999/xhtml' @@ -116,7 +117,7 @@ def _html4_parse(data, prefer_soup=False): for elem in data.iter(tag=etree.Comment): if elem.text: elem.text = elem.text.strip('-') - data = etree.tostring(data, encoding=unicode) + data = etree.tostring(data, encoding=unicode_type) # Setting huge_tree=True causes crashes in windows with large files parser = etree.XMLParser(no_network=True) @@ -173,7 +174,7 @@ def parse_html(data, log=None, decoder=None, preprocessor=None, filename = force_unicode(filename, enc=filesystem_encoding) - if not isinstance(data, unicode): + if not isinstance(data, unicode_type): if decoder is not None: data = decoder(data) else: @@ -258,7 +259,7 @@ def parse_html(data, log=None, decoder=None, preprocessor=None, nroot = etree.fromstring('') has_body = False for child in list(data): - if isinstance(child.tag, (unicode, str)) and barename(child.tag) == 'body': + if isinstance(child.tag, (unicode_type, str)) and barename(child.tag) == 'body': has_body = True break parent = nroot @@ -277,7 +278,7 @@ def parse_html(data, log=None, decoder=None, preprocessor=None, if not namespace(data.tag): log.warn('Forcing', filename, 'into XHTML namespace') data.attrib['xmlns'] = XHTML_NS - data = etree.tostring(data, encoding=unicode) + data = etree.tostring(data, encoding=unicode_type) try: data = etree.fromstring(data, parser=parser) diff --git a/src/calibre/ebooks/oeb/polish/check/parsing.py b/src/calibre/ebooks/oeb/polish/check/parsing.py index eb3c95b7ad..1ffcfd68da 100644 --- a/src/calibre/ebooks/oeb/polish/check/parsing.py +++ b/src/calibre/ebooks/oeb/polish/check/parsing.py @@ -18,6 +18,7 @@ from calibre.ebooks.oeb.polish.pretty import pretty_script_or_style as fix_style from calibre.ebooks.oeb.polish.utils import PositionFinder, guess_type from calibre.ebooks.oeb.polish.check.base import BaseError, WARN, ERROR, INFO from calibre.ebooks.oeb.base import OEB_DOCS, XHTML_NS, urlquote, URL_SAFE, XHTML +from polyglot.builtins import unicode_type HTML_ENTITTIES = frozenset(html5_entities) XML_ENTITIES = {'lt', 'gt', 'amp', 'apos', 'quot'} @@ -444,7 +445,7 @@ class ErrorHandler(object): info = debug = setLevel = getEffectiveLevel = addHandler = removeHandler = __noop def __handle(self, level, *args): - msg = ' '.join(map(unicode, args)) + msg = ' '.join(map(unicode_type, args)) line = col = None for pat in pos_pats: m = pat.search(msg) diff --git a/src/calibre/ebooks/oeb/polish/container.py b/src/calibre/ebooks/oeb/polish/container.py index ece50b23c5..0216a74f27 100644 --- a/src/calibre/ebooks/oeb/polish/container.py +++ b/src/calibre/ebooks/oeb/polish/container.py @@ -14,7 +14,7 @@ import time import unicodedata import uuid from collections import defaultdict -from polyglot.builtins import zip +from polyglot.builtins import unicode_type, zip from io import BytesIO from itertools import count from urlparse import urlparse @@ -167,7 +167,7 @@ class ContainerBase(object): # {{{ """ def fix_data(d): return d.replace('\r\n', '\n').replace('\r', '\n') - if isinstance(data, unicode): + if isinstance(data, unicode_type): return fix_data(data) bom_enc = None if data[:4] in {b'\0\0\xfe\xff', b'\xff\xfe\0\0'}: diff --git a/src/calibre/ebooks/oeb/polish/css.py b/src/calibre/ebooks/oeb/polish/css.py index 5b07a13a6d..ba92f610b1 100644 --- a/src/calibre/ebooks/oeb/polish/css.py +++ b/src/calibre/ebooks/oeb/polish/css.py @@ -18,6 +18,7 @@ from calibre.ebooks.oeb.normalize_css import normalize_filter_css, normalizers from calibre.ebooks.oeb.polish.pretty import pretty_script_or_style, pretty_xml_tree, serialize from calibre.utils.icu import numeric_sort_key from css_selectors import Select, SelectorError +from polyglot.builtins import unicode_type def filter_used_rules(rules, log, select): @@ -343,10 +344,10 @@ def sort_sheet(container, sheet_or_text): ''' Sort the rules in a stylesheet. Note that in the general case this can change the effective styles, but for most common sheets, it should be safe. ''' - sheet = container.parse_css(sheet_or_text) if isinstance(sheet_or_text, unicode) else sheet_or_text + sheet = container.parse_css(sheet_or_text) if isinstance(sheet_or_text, unicode_type) else sheet_or_text def text_sort_key(x): - return numeric_sort_key(unicode(x or '')) + return numeric_sort_key(unicode_type(x or '')) def selector_sort_key(x): return (x.specificity, text_sort_key(x.selectorText)) diff --git a/src/calibre/ebooks/oeb/polish/spell.py b/src/calibre/ebooks/oeb/polish/spell.py index 271c2474fe..4c9864fb2f 100644 --- a/src/calibre/ebooks/oeb/polish/spell.py +++ b/src/calibre/ebooks/oeb/polish/spell.py @@ -17,6 +17,7 @@ from calibre.ebooks.oeb.polish.container import OPF_NAMESPACES, get_container from calibre.ebooks.oeb.polish.parsing import parse from calibre.ebooks.oeb.polish.toc import find_existing_ncx_toc, find_existing_nav_toc from calibre.utils.icu import ord_string +from polyglot.builtins import unicode_type _patterns = None @@ -82,7 +83,7 @@ def filter_words(word): def get_words(text, lang): try: - ans = split_into_words(unicode(text), lang) + ans = split_into_words(unicode_type(text), lang) except (TypeError, ValueError): return () return filter(filter_words, ans) @@ -314,7 +315,7 @@ def merge_locations(locs1, locs2): def replace(text, original_word, new_word, lang): indices = [] - original_word, new_word, text = unicode(original_word), unicode(new_word), unicode(text) + original_word, new_word, text = unicode_type(original_word), unicode_type(new_word), unicode_type(text) q = text offset = 0 while True: diff --git a/src/calibre/ebooks/oeb/polish/stats.py b/src/calibre/ebooks/oeb/polish/stats.py index e6bb98b396..4177835eda 100644 --- a/src/calibre/ebooks/oeb/polish/stats.py +++ b/src/calibre/ebooks/oeb/polish/stats.py @@ -16,6 +16,7 @@ import regex from calibre.ebooks.oeb.base import XHTML from calibre.ebooks.oeb.polish.cascade import iterrules, resolve_styles, iterdeclaration from calibre.utils.icu import ord_string, safe_chr +from polyglot.builtins import unicode_type from tinycss.fonts3 import parse_font_family @@ -23,7 +24,7 @@ def normalize_font_properties(font): w = font.get('font-weight', None) if not w and w != 0: w = 'normal' - w = unicode(w) + w = unicode_type(w) w = {'normal':'400', 'bold':'700'}.get(w, w) if w not in {'100', '200', '300', '400', '500', '600', '700', '800', '900'}: @@ -119,7 +120,7 @@ def get_element_text(elem, resolve_property, resolve_pseudo_property, capitalize if before: ans.append(before) if for_pseudo is not None: - ans.append(tostring(elem, method='text', encoding=unicode, with_tail=False)) + ans.append(tostring(elem, method='text', encoding=unicode_type, with_tail=False)) else: if elem.text: ans.append(elem.text) diff --git a/src/calibre/ebooks/oeb/polish/toc.py b/src/calibre/ebooks/oeb/polish/toc.py index 51aa365b37..b2c39702f0 100644 --- a/src/calibre/ebooks/oeb/polish/toc.py +++ b/src/calibre/ebooks/oeb/polish/toc.py @@ -11,7 +11,7 @@ import re from urlparse import urlparse from collections import Counter, OrderedDict from functools import partial -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from operator import itemgetter from lxml import etree @@ -143,7 +143,7 @@ def add_from_navpoint(container, navpoint, parent, ncx_name): text = '' for txt in child_xpath(nl, 'text'): text += etree.tostring(txt, method='text', - encoding=unicode, with_tail=False) + encoding=unicode_type, with_tail=False) content = child_xpath(navpoint, 'content') if content: content = content[0] @@ -170,11 +170,11 @@ def parse_ncx(container, ncx_name): toc_root.lang = toc_root.uid = None for attr, val in root.attrib.iteritems(): if attr.endswith('lang'): - toc_root.lang = unicode(val) + toc_root.lang = unicode_type(val) break for uid in root.xpath('//*[calibre:lower-case(local-name()) = "meta" and @name="dtb:uid"]/@content'): if uid: - toc_root.uid = unicode(uid) + toc_root.uid = unicode_type(uid) break for pl in root.xpath('//*[calibre:lower-case(local-name()) = "pagelist"]'): for pt in pl.xpath('descendant::*[calibre:lower-case(local-name()) = "pagetarget"]'): @@ -191,7 +191,7 @@ def parse_ncx(container, ncx_name): def add_from_li(container, li, parent, nav_name): dest = frag = text = None for x in li.iterchildren(XHTML('a'), XHTML('span')): - text = etree.tostring(x, method='text', encoding=unicode, with_tail=False).strip() or ' '.join(x.xpath('descendant-or-self::*/@title')).strip() + text = etree.tostring(x, method='text', encoding=unicode_type, with_tail=False).strip() or ' '.join(x.xpath('descendant-or-self::*/@title')).strip() href = x.get('href') if href: dest = nav_name if href.startswith('#') else container.href_to_name(href, base=nav_name) @@ -226,7 +226,7 @@ def parse_nav(container, nav_name): if ol is not None: process_nav_node(container, ol, toc_root, nav_name) for h in nav.iterchildren(*map(XHTML, 'h1 h2 h3 h4 h5 h6'.split())): - text = etree.tostring(h, method='text', encoding=unicode, with_tail=False) or h.get('title') + text = etree.tostring(h, method='text', encoding=unicode_type, with_tail=False) or h.get('title') if text: toc_root.toc_title = text break @@ -324,7 +324,7 @@ def get_nav_landmarks(container): for a in li.iterdescendants(XHTML('a')): href, rtype = a.get('href'), a.get(et) if href: - title = etree.tostring(a, method='text', encoding=unicode, with_tail=False).strip() + title = etree.tostring(a, method='text', encoding=unicode_type, with_tail=False).strip() href, frag = href.partition('#')[::2] name = container.href_to_name(href, nav) if container.has_name(name): @@ -579,7 +579,7 @@ def create_ncx(toc, to_href, btitle, lang, uid): nsmap={None: NCX_NS}) head = etree.SubElement(ncx, NCX('head')) etree.SubElement(head, NCX('meta'), - name='dtb:uid', content=unicode(uid)) + name='dtb:uid', content=unicode_type(uid)) etree.SubElement(head, NCX('meta'), name='dtb:depth', content=str(toc.depth)) generator = ''.join(['calibre (', __version__, ')']) diff --git a/src/calibre/ebooks/oeb/reader.py b/src/calibre/ebooks/oeb/reader.py index 0536834888..1d0f0a444e 100644 --- a/src/calibre/ebooks/oeb/reader.py +++ b/src/calibre/ebooks/oeb/reader.py @@ -30,6 +30,7 @@ from calibre.utils.localization import get_lang from calibre.ptempfile import TemporaryDirectory from calibre.constants import __appname__, __version__ from calibre import guess_type, xml_replace_entities +from polyglot.builtins import unicode_type __all__ = ['OEBReader'] @@ -429,7 +430,7 @@ class OEBReader(object): 'descendant::calibre:meta[@name = "description"]') if descriptionElement: description = etree.tostring(descriptionElement[0], - method='text', encoding=unicode).strip() + method='text', encoding=unicode_type).strip() if not description: description = None else: @@ -454,7 +455,7 @@ class OEBReader(object): ncx = item.data title = ''.join(xpath(ncx, 'ncx:docTitle/ncx:text/text()')) title = COLLAPSE_RE.sub(' ', title.strip()) - title = title or unicode(self.oeb.metadata.title[0]) + title = title or unicode_type(self.oeb.metadata.title[0]) toc = self.oeb.toc toc.title = title navmaps = xpath(ncx, 'ncx:navMap') @@ -641,7 +642,7 @@ class OEBReader(object): def _locate_cover_image(self): if self.oeb.metadata.cover: - id = unicode(self.oeb.metadata.cover[0]) + id = unicode_type(self.oeb.metadata.cover[0]) item = self.oeb.manifest.ids.get(id, None) if item is not None and item.media_type in OEB_IMAGES: return item diff --git a/src/calibre/ebooks/oeb/stylizer.py b/src/calibre/ebooks/oeb/stylizer.py index 0a66340cd9..1e7aaf6343 100644 --- a/src/calibre/ebooks/oeb/stylizer.py +++ b/src/calibre/ebooks/oeb/stylizer.py @@ -20,6 +20,7 @@ from calibre.ebooks import unit_convert from calibre.ebooks.oeb.base import XHTML, XHTML_NS, CSS_MIME, OEB_STYLES, xpath, urlnormalize from calibre.ebooks.oeb.normalize_css import DEFAULTS, normalizers from css_selectors import Select, SelectorError, INAPPROPRIATE_PSEUDO_CLASSES +from polyglot.builtins import unicode_type from tinycss.media3 import CSSMedia3Parser css_parser_log.setLevel(logging.WARN) @@ -237,7 +238,7 @@ class Stylizer(object): for x in elem.iter('*'): if x.text: punctuation_chars = [] - text = unicode(x.text) + text = unicode_type(x.text) while text: category = unicodedata.category(text[0]) if category[0] not in {'P', 'Z'}: @@ -606,12 +607,12 @@ class Style(object): result = base else: result = self._unit_convert(width, base=base) - if isinstance(result, (unicode, str, bytes)): + if isinstance(result, (unicode_type, str, bytes)): result = self._profile.width self._width = result if 'max-width' in self._style: result = self._unit_convert(self._style['max-width'], base=base) - if isinstance(result, (unicode, str, bytes)): + if isinstance(result, (unicode_type, str, bytes)): result = self._width if result < self._width: self._width = result @@ -643,12 +644,12 @@ class Style(object): result = base else: result = self._unit_convert(height, base=base) - if isinstance(result, (unicode, str, bytes)): + if isinstance(result, (unicode_type, str, bytes)): result = self._profile.height self._height = result if 'max-height' in self._style: result = self._unit_convert(self._style['max-height'], base=base) - if isinstance(result, (unicode, str, bytes)): + if isinstance(result, (unicode_type, str, bytes)): result = self._height if result < self._height: self._height = result diff --git a/src/calibre/ebooks/oeb/transforms/cover.py b/src/calibre/ebooks/oeb/transforms/cover.py index 65e96f1491..3165a4ecd3 100644 --- a/src/calibre/ebooks/oeb/transforms/cover.py +++ b/src/calibre/ebooks/oeb/transforms/cover.py @@ -11,6 +11,7 @@ from urllib import unquote from lxml import etree from calibre import guess_type from calibre.utils.imghdr import identify +from polyglot.builtins import unicode_type class CoverManager(object): @@ -90,14 +91,14 @@ class CoverManager(object): return None self.log('Generating default cover') m = self.oeb.metadata - title = unicode(m.title[0]) - authors = [unicode(x) for x in m.creator if x.role == 'aut'] + title = unicode_type(m.title[0]) + authors = [unicode_type(x) for x in m.creator if x.role == 'aut'] try: from calibre.ebooks.covers import create_cover series = series_index = None if m.series: try: - series, series_index = unicode(m.series[0]), m.series_index[0] + series, series_index = unicode_type(m.series[0]), m.series_index[0] except IndexError: pass img_data = create_cover(title, authors, series, series_index) diff --git a/src/calibre/ebooks/oeb/transforms/embed_fonts.py b/src/calibre/ebooks/oeb/transforms/embed_fonts.py index 0810d39de7..9e669bc113 100644 --- a/src/calibre/ebooks/oeb/transforms/embed_fonts.py +++ b/src/calibre/ebooks/oeb/transforms/embed_fonts.py @@ -18,10 +18,11 @@ from calibre.ebooks.oeb.transforms.subset import get_font_properties, find_font_ from calibre.utils.filenames import ascii_filename from calibre.utils.fonts.scanner import font_scanner, NoFonts from calibre.ebooks.oeb.polish.embed import font_key +from polyglot.builtins import unicode_type def font_families_from_style(style): - return [unicode(f) for f in style.get('font-family', []) if unicode(f).lower() not in { + return [unicode_type(f) for f in style.get('font-family', []) if unicode_type(f).lower() not in { 'serif', 'sansserif', 'sans-serif', 'fantasy', 'cursive', 'monospace'}] @@ -39,7 +40,7 @@ def used_font(style, embedded_fonts): ff = font_families_from_style(style) if not ff: return False, None - lnames = {unicode(x).lower() for x in ff} + lnames = {unicode_type(x).lower() for x in ff} matching_set = [] diff --git a/src/calibre/ebooks/oeb/transforms/flatcss.py b/src/calibre/ebooks/oeb/transforms/flatcss.py index d144971af4..6af6fd2559 100644 --- a/src/calibre/ebooks/oeb/transforms/flatcss.py +++ b/src/calibre/ebooks/oeb/transforms/flatcss.py @@ -21,6 +21,7 @@ from calibre.ebooks.oeb.base import (XHTML, XHTML_NS, CSS_MIME, OEB_STYLES, from calibre.ebooks.oeb.stylizer import Stylizer from calibre.utils.filenames import ascii_filename, ascii_text from calibre.utils.icu import numeric_sort_key +from polyglot.builtins import unicode_type COLLAPSE = re.compile(r'[ \t\r\n\v]+') STRIPNUM = re.compile(r'[-0-9]+$') @@ -265,7 +266,7 @@ class CSSFlattener(object): cfont = { u'font-family':u'"%s"'%font['font-family'], - u'panose-1': u' '.join(map(unicode, font['panose'])), + u'panose-1': u' '.join(map(unicode_type, font['panose'])), u'src': u'url(%s)'%item.href, } diff --git a/src/calibre/ebooks/oeb/transforms/jacket.py b/src/calibre/ebooks/oeb/transforms/jacket.py index 53f450ddf2..1859df0e29 100644 --- a/src/calibre/ebooks/oeb/transforms/jacket.py +++ b/src/calibre/ebooks/oeb/transforms/jacket.py @@ -22,6 +22,7 @@ from calibre.utils.date import is_date_undefined, as_local_time from calibre.utils.icu import sort_key from calibre.ebooks.chardet import strip_encoding_declarations from calibre.ebooks.metadata import fmt_sidx, rating_to_stars +from polyglot.builtins import unicode_type JACKET_XPATH = '//h:meta[@name="calibre-content" and @content="jacket"]' @@ -104,17 +105,17 @@ class Jacket(Base): self.log('Inserting metadata into book...') try: - tags = map(unicode, self.oeb.metadata.subject) + tags = map(unicode_type, self.oeb.metadata.subject) except: tags = [] try: - comments = unicode(self.oeb.metadata.description[0]) + comments = unicode_type(self.oeb.metadata.description[0]) except: comments = '' try: - title = unicode(self.oeb.metadata.title[0]) + title = unicode_type(self.oeb.metadata.title[0]) except: title = _('Unknown') @@ -171,7 +172,7 @@ def get_rating(rating, rchar, e_rchar): return ans -class Series(unicode): +class Series(unicode_type): def __new__(self, series, series_index): if series and series_index is not None: @@ -181,7 +182,7 @@ class Series(unicode): escape(series), escape(fmt_sidx(series_index, use_roman=False))) else: combined = roman = escape(series or u'') - s = unicode.__new__(self, combined) + s = unicode_type.__new__(self, combined) s.roman = roman s.name = escape(series or u'') s.number = escape(fmt_sidx(series_index or 1.0, use_roman=False)) @@ -189,11 +190,11 @@ class Series(unicode): return s -class Tags(unicode): +class Tags(unicode_type): def __new__(self, tags, output_profile): tags = [escape(x) for x in tags or ()] - t = unicode.__new__(self, ', '.join(tags)) + t = unicode_type.__new__(self, ', '.join(tags)) t.alphabetical = ', '.join(sorted(tags, key=sort_key)) t.tags_list = tags return t diff --git a/src/calibre/ebooks/oeb/transforms/metadata.py b/src/calibre/ebooks/oeb/transforms/metadata.py index 640da6685e..a405bd8991 100644 --- a/src/calibre/ebooks/oeb/transforms/metadata.py +++ b/src/calibre/ebooks/oeb/transforms/metadata.py @@ -9,6 +9,7 @@ __docformat__ = 'restructuredtext en' import os, re from calibre.utils.date import isoformat, now from calibre import guess_type +from polyglot.builtins import unicode_type def meta_info_to_oeb_metadata(mi, m, log, override_input_metadata=False): @@ -204,7 +205,7 @@ class MergeMetadata(object): for item in affected_items: body = XPath('//h:body')(item.data) if body: - text = etree.tostring(body[0], method='text', encoding=unicode) + text = etree.tostring(body[0], method='text', encoding=unicode_type) else: text = '' text = re.sub(r'\s+', '', text) diff --git a/src/calibre/ebooks/oeb/transforms/rasterize.py b/src/calibre/ebooks/oeb/transforms/rasterize.py index ed5c456105..7b88e77172 100644 --- a/src/calibre/ebooks/oeb/transforms/rasterize.py +++ b/src/calibre/ebooks/oeb/transforms/rasterize.py @@ -18,6 +18,7 @@ from calibre.ebooks.oeb.base import urlnormalize from calibre.ebooks.oeb.stylizer import Stylizer from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.imghdr import what +from polyglot.builtins import unicode_type IMAGE_TAGS = {XHTML('img'), XHTML('object')} KEEP_ATTRS = {'class', 'style', 'width', 'height', 'align'} @@ -222,11 +223,11 @@ class SVGRasterizer(object): covers = self.oeb.metadata.cover if not covers: return - if unicode(covers[0]) not in self.oeb.manifest.ids: + if unicode_type(covers[0]) not in self.oeb.manifest.ids: self.oeb.logger.warn('Cover not in manifest, skipping.') self.oeb.metadata.clear('cover') return - cover = self.oeb.manifest.ids[unicode(covers[0])] + cover = self.oeb.manifest.ids[unicode_type(covers[0])] if not cover.media_type == SVG_MIME: return width = (self.profile.width / 72) * self.profile.dpi diff --git a/src/calibre/ebooks/oeb/transforms/split.py b/src/calibre/ebooks/oeb/transforms/split.py index 19debfd0b5..d58337035c 100644 --- a/src/calibre/ebooks/oeb/transforms/split.py +++ b/src/calibre/ebooks/oeb/transforms/split.py @@ -20,6 +20,7 @@ from calibre.ebooks.epub import rules from calibre.ebooks.oeb.base import (OEB_STYLES, XPNSMAP as NAMESPACES, urldefrag, rewrite_links, urlunquote, XHTML, urlnormalize) from calibre.ebooks.oeb.polish.split import do_split +from polyglot.builtins import unicode_type from css_selectors import Select, SelectorError XPath = functools.partial(_XPath, namespaces=NAMESPACES) @@ -294,7 +295,7 @@ class FlowSplitter(object): if body is None: return False txt = re.sub(u'\\s+|\\xa0', '', - etree.tostring(body, method='text', encoding=unicode)) + etree.tostring(body, method='text', encoding=unicode_type)) if len(txt) > 1: return False for img in root.xpath('//h:img', namespaces=NAMESPACES): diff --git a/src/calibre/ebooks/oeb/transforms/structure.py b/src/calibre/ebooks/oeb/transforms/structure.py index fab67146ee..bf5079b8d0 100644 --- a/src/calibre/ebooks/oeb/transforms/structure.py +++ b/src/calibre/ebooks/oeb/transforms/structure.py @@ -14,6 +14,7 @@ from collections import OrderedDict, Counter from calibre.ebooks.oeb.base import XPNSMAP, TOC, XHTML, xml2text, barename from calibre.ebooks import ConversionError +from polyglot.builtins import unicode_type def XPath(x): @@ -123,7 +124,7 @@ class DetectStructure(object): elem = matches[0] eid = elem.get('id', None) if not eid: - eid = u'start_reading_at_'+unicode(uuid.uuid4()).replace(u'-', u'') + eid = u'start_reading_at_'+unicode_type(uuid.uuid4()).replace(u'-', u'') elem.set('id', eid) if u'text' in self.oeb.guide: self.oeb.guide.remove(u'text') diff --git a/src/calibre/ebooks/oeb/transforms/subset.py b/src/calibre/ebooks/oeb/transforms/subset.py index 030fe4aba0..5e580ed93d 100644 --- a/src/calibre/ebooks/oeb/transforms/subset.py +++ b/src/calibre/ebooks/oeb/transforms/subset.py @@ -11,6 +11,7 @@ from collections import defaultdict from calibre.ebooks.oeb.base import urlnormalize from calibre.utils.fonts.sfnt.subset import subset, NoGlyphs, UnsupportedFont +from polyglot.builtins import unicode_type from tinycss.fonts3 import parse_font_family @@ -35,7 +36,7 @@ def get_font_properties(rule, default=None): except (IndexError, KeyError, AttributeError, TypeError, ValueError): val = None if q in {'src', 'font-family'} else default if q in {'font-weight', 'font-stretch', 'font-style'}: - val = unicode(val).lower() if (val or val == 0) else val + val = unicode_type(val).lower() if (val or val == 0) else val if val == 'inherit': val = default if q == 'font-weight': @@ -236,7 +237,7 @@ class SubsetFonts(object): no match is found (can happen if no family matches). ''' ff = style.get('font-family', []) - lnames = {unicode(x).lower() for x in ff} + lnames = {unicode_type(x).lower() for x in ff} matching_set = [] # Filter on font-family @@ -314,6 +315,3 @@ class SubsetFonts(object): chars = self.find_chars(elem) if chars: font['chars'] |= chars - - - diff --git a/src/calibre/ebooks/pdb/ereader/reader132.py b/src/calibre/ebooks/pdb/ereader/reader132.py index 29a2414360..12dfd896be 100644 --- a/src/calibre/ebooks/pdb/ereader/reader132.py +++ b/src/calibre/ebooks/pdb/ereader/reader132.py @@ -18,6 +18,7 @@ from calibre.ebooks import DRMError from calibre.ebooks.metadata.opf2 import OPFCreator from calibre.ebooks.pdb.ereader import EreaderError from calibre.ebooks.pdb.formatreader import FormatReader +from polyglot.builtins import unicode_type class HeaderRecord(object): @@ -113,7 +114,7 @@ class Reader132(FormatReader): os.makedirs(output_dir) title = self.mi.title - if not isinstance(title, unicode): + if not isinstance(title, unicode_type): title = title.decode('utf-8', 'replace') html = u'%s' % title @@ -217,4 +218,3 @@ class Reader132(FormatReader): name, img = self.get_image(self.header_record.image_data_offset + i) with open(name, 'wb') as imgf: imgf.write(img) - diff --git a/src/calibre/ebooks/pdb/ereader/reader202.py b/src/calibre/ebooks/pdb/ereader/reader202.py index 5d4aa91e1f..9d98a6d640 100644 --- a/src/calibre/ebooks/pdb/ereader/reader202.py +++ b/src/calibre/ebooks/pdb/ereader/reader202.py @@ -14,6 +14,7 @@ from calibre import CurrentDir from calibre.ebooks.metadata.opf2 import OPFCreator from calibre.ebooks.pdb.formatreader import FormatReader from calibre.ebooks.pdb.ereader import EreaderError +from polyglot.builtins import unicode_type class HeaderRecord(object): @@ -94,7 +95,7 @@ class Reader202(FormatReader): pml += self.get_text_page(i) title = self.mi.title - if not isinstance(title, unicode): + if not isinstance(title, unicode_type): title = title.decode('utf-8', 'replace') html = u'%s%s' % \ diff --git a/src/calibre/ebooks/pdb/ereader/writer.py b/src/calibre/ebooks/pdb/ereader/writer.py index 296fef69e7..77c6a0c80a 100644 --- a/src/calibre/ebooks/pdb/ereader/writer.py +++ b/src/calibre/ebooks/pdb/ereader/writer.py @@ -23,6 +23,7 @@ import cStringIO from calibre.ebooks.pdb.formatwriter import FormatWriter from calibre.ebooks.pdb.header import PdbHeaderBuilder from calibre.ebooks.pml.pmlml import PMLMLizer +from polyglot.builtins import unicode_type IDENTITY = 'PNRdPPrs' @@ -39,7 +40,7 @@ class Writer(FormatWriter): def write_content(self, oeb_book, out_stream, metadata=None): pmlmlizer = PMLMLizer(self.log) - pml = unicode(pmlmlizer.extract_content(oeb_book, self.opts)).encode('cp1252', 'replace') + pml = unicode_type(pmlmlizer.extract_content(oeb_book, self.opts)).encode('cp1252', 'replace') text, text_sizes = self._text(pml) chapter_index = self._index_item(r'(?s)\\C(?P[0-4])="(?P.+?)"', pml) @@ -249,4 +250,3 @@ class Writer(FormatWriter): record += struct.pack('>H', 0) # [54:132] return record - diff --git a/src/calibre/ebooks/pdb/plucker/reader.py b/src/calibre/ebooks/pdb/plucker/reader.py index acdce617eb..9a0d3a0180 100644 --- a/src/calibre/ebooks/pdb/plucker/reader.py +++ b/src/calibre/ebooks/pdb/plucker/reader.py @@ -17,6 +17,7 @@ from calibre.ebooks.pdb.formatreader import FormatReader from calibre.ebooks.compression.palmdoc import decompress_doc from calibre.utils.imghdr import identify from calibre.utils.img import save_cover_data_to, Canvas, image_from_data +from polyglot.builtins import codepoint_to_chr DATATYPE_PHTML = 0 DATATYPE_PHTML_COMPRESSED = 1 @@ -716,7 +717,7 @@ class Reader(FormatReader): elif c == 0xa0: html += ' ' else: - html += unichr(c) + html += codepoint_to_chr(c) offset += 1 if offset in paragraph_offsets: need_set_p_id = True diff --git a/src/calibre/ebooks/pdf/reflow.py b/src/calibre/ebooks/pdf/reflow.py index e2f4541220..ceb4e67dea 100644 --- a/src/calibre/ebooks/pdf/reflow.py +++ b/src/calibre/ebooks/pdf/reflow.py @@ -10,6 +10,8 @@ import sys, os from lxml import etree +from polyglot.builtins import unicode_type + class Font(object): @@ -73,10 +75,10 @@ class Text(Element): text.tail = '' self.text_as_string = etree.tostring(text, method='text', - encoding=unicode) + encoding=unicode_type) self.raw = text.text if text.text else u'' for x in text.iterchildren(): - self.raw += etree.tostring(x, method='xml', encoding=unicode) + self.raw += etree.tostring(x, method='xml', encoding=unicode_type) self.average_character_width = self.width/len(self.text_as_string) def coalesce(self, other, page_number): @@ -695,7 +697,3 @@ class PDFDocument(object): raw = (u'\n'.join(html)).replace('', '') with open('index.html', 'wb') as f: f.write(raw.encode('utf-8')) - - - - diff --git a/src/calibre/ebooks/pdf/render/common.py b/src/calibre/ebooks/pdf/render/common.py index 70f242542f..6b8200fa68 100644 --- a/src/calibre/ebooks/pdf/render/common.py +++ b/src/calibre/ebooks/pdf/render/common.py @@ -14,6 +14,7 @@ from binascii import hexlify from calibre.constants import plugins, ispy3 from calibre.utils.logging import default_log +from polyglot.builtins import unicode_type pdf_float = plugins['speedup'][0].pdf_float @@ -55,16 +56,11 @@ PAPER_SIZES = {k:globals()[k.upper()] for k in ('a0 a1 a2 a3 a4 a5 a6 b0 b1 b2' # }}} -# Basic PDF datatypes {{{ - -ic = str if ispy3 else unicode -icb = (lambda x: str(x).encode('ascii')) if ispy3 else bytes - def fmtnum(o): if isinstance(o, float): return pdf_float(o) - return ic(o) + return unicode_type(o) def serialize(o, stream): @@ -74,7 +70,7 @@ def serialize(o, stream): # Must check bool before int as bools are subclasses of int stream.write_raw(b'true' if o else b'false') elif isinstance(o, (int, long)): - stream.write_raw(icb(o)) + stream.write_raw(str(o).encode('ascii') if ispy3 else bytes(o)) elif hasattr(o, 'pdf_serialize'): o.pdf_serialize(stream) elif o is None: @@ -88,7 +84,7 @@ def serialize(o, stream): raise ValueError('Unknown object: %r'%o) -class Name(unicode): +class Name(unicode_type): def pdf_serialize(self, stream): raw = self.encode('ascii') @@ -122,7 +118,7 @@ def escape_pdf_string(bytestring): return bytes(ba) -class String(unicode): +class String(unicode_type): def pdf_serialize(self, stream): try: @@ -134,7 +130,7 @@ class String(unicode): stream.write(b'('+escape_pdf_string(raw)+b')') -class UTF16String(unicode): +class UTF16String(unicode_type): def pdf_serialize(self, stream): raw = codecs.BOM_UTF16_BE + self.encode('utf-16-be') diff --git a/src/calibre/ebooks/pdf/render/engine.py b/src/calibre/ebooks/pdf/render/engine.py index 9c3faef867..ac823c2328 100644 --- a/src/calibre/ebooks/pdf/render/engine.py +++ b/src/calibre/ebooks/pdf/render/engine.py @@ -20,6 +20,7 @@ from calibre.ebooks.pdf.render.common import inch, A4, fmtnum from calibre.ebooks.pdf.render.graphics import convert_path, Graphics from calibre.utils.fonts.sfnt.container import Sfnt, UnsupportedFont from calibre.utils.fonts.sfnt.metrics import FontMetrics +from polyglot.builtins import codepoint_to_chr Point = namedtuple('Point', 'x y') ColorState = namedtuple('ColorState', 'color opacity do') @@ -258,7 +259,7 @@ class PdfEngine(QPaintEngine): ans.ignore_glyphs = set() for uc, glyph_id in enumerate(glyph_map): if glyph_id not in gm: - gm[glyph_id] = unichr(uc) + gm[glyph_id] = codepoint_to_chr(uc) if uc in (0xad, 0x200b): ans.ignore_glyphs.add(glyph_id) ans.full_glyph_map = gm diff --git a/src/calibre/ebooks/pdf/render/from_html.py b/src/calibre/ebooks/pdf/render/from_html.py index b3e81f0a12..1365c22d72 100644 --- a/src/calibre/ebooks/pdf/render/from_html.py +++ b/src/calibre/ebooks/pdf/render/from_html.py @@ -25,6 +25,7 @@ from calibre.ebooks.pdf.render.common import (inch, cm, mm, pica, cicero, from calibre.ebooks.pdf.render.engine import PdfDevice from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.resources import load_hyphenator_dicts +from polyglot.builtins import unicode_type def get_page_size(opts, for_comic=False): # {{{ @@ -91,10 +92,10 @@ class Page(QWebPage): # {{{ self.longjs_counter = 0 def javaScriptConsoleMessage(self, msg, lineno, msgid): - self.log.debug(u'JS:', unicode(msg)) + self.log.debug(u'JS:', unicode_type(msg)) def javaScriptAlert(self, frame, msg): - self.log(unicode(msg)) + self.log(unicode_type(msg)) @pyqtSlot(result=bool) def shouldInterruptJavaScript(self): @@ -128,19 +129,19 @@ def draw_image_page(page_rect, painter, p, preserve_aspect_ratio=True): class PDFWriter(QObject): - @pyqtSlot(result=unicode) + @pyqtSlot(result=unicode_type) def title(self): return self.doc_title - @pyqtSlot(result=unicode) + @pyqtSlot(result=unicode_type) def author(self): return self.doc_author - @pyqtSlot(result=unicode) + @pyqtSlot(result=unicode_type) def section(self): return self.current_section - @pyqtSlot(result=unicode) + @pyqtSlot(result=unicode_type) def tl_section(self): return self.current_tl_section @@ -280,7 +281,7 @@ class PDFWriter(QObject): self.loop.exit(1) def render_next(self): - item = unicode(self.render_queue.pop(0)) + item = unicode_type(self.render_queue.pop(0)) self.logger.debug('Processing %s...' % item) self.current_item = item diff --git a/src/calibre/ebooks/pml/pmlml.py b/src/calibre/ebooks/pml/pmlml.py index 7a121cb4de..d024ca7581 100644 --- a/src/calibre/ebooks/pml/pmlml.py +++ b/src/calibre/ebooks/pml/pmlml.py @@ -14,6 +14,7 @@ from lxml import etree from calibre.ebooks.pdb.ereader import image_name from calibre.ebooks.pml import unipmlcode +from polyglot.builtins import unicode_type TAG_MAP = { 'b' : 'B', @@ -134,7 +135,7 @@ class PMLMLizer(object): text = [u''] for item in self.oeb_book.spine: self.log.debug('Converting %s to PML markup...' % item.href) - content = unicode(etree.tostring(item.data, encoding=unicode)) + content = unicode_type(etree.tostring(item.data, encoding=unicode_type)) content = self.prepare_text(content) content = etree.fromstring(content) stylizer = Stylizer(content, item.href, self.oeb_book, self.opts, self.opts.output_profile) @@ -174,7 +175,7 @@ class PMLMLizer(object): def prepare_text(self, text): # Replace empty paragraphs with \c pml codes used to denote emtpy lines. - text = re.sub(unicode(r'(?<=

)\s*]*>[\xc2\xa0\s]*

'), '\\c\n\\c', text) + text = re.sub(unicode_type(r'(?<=

)\s*]*>[\xc2\xa0\s]*

'), '\\c\n\\c', text) return text def clean_text(self, text): @@ -188,7 +189,7 @@ class PMLMLizer(object): text = text.replace('\\Q="%s"' % unused, '') # Remove \Cn tags that are within \x and \Xn tags - text = re.sub(unicode(r'(?msu)(?P\\(x|X[0-4]))(?P.*?)(?P\\C[0-4]\s*=\s*"[^"]*")(?P.*?)(?P=t)'), '\\g\\g\\g\\g', text) + text = re.sub(unicode_type(r'(?msu)(?P\\(x|X[0-4]))(?P.*?)(?P\\C[0-4]\s*=\s*"[^"]*")(?P.*?)(?P=t)'), '\\g\\g\\g\\g', text) # Replace bad characters. text = text.replace(u'\xc2', '') diff --git a/src/calibre/ebooks/readability/htmls.py b/src/calibre/ebooks/readability/htmls.py index 6815df06aa..66a858326d 100644 --- a/src/calibre/ebooks/readability/htmls.py +++ b/src/calibre/ebooks/readability/htmls.py @@ -5,6 +5,7 @@ import lxml.html from calibre.ebooks.readability.cleaners import normalize_spaces, clean_attributes from calibre.ebooks.chardet import xml_to_unicode +from polyglot.builtins import unicode_type def build_doc(page): @@ -119,6 +120,5 @@ def shorten_title(doc): def get_body(doc): [elem.drop_tree() for elem in doc.xpath('.//script | .//link | .//style')] - raw_html = unicode(tostring(doc.body or doc)) + raw_html = unicode_type(tostring(doc.body or doc)) return clean_attributes(raw_html) - diff --git a/src/calibre/ebooks/readability/readability.py b/src/calibre/ebooks/readability/readability.py index 58953a2d80..46ccbc8a14 100644 --- a/src/calibre/ebooks/readability/readability.py +++ b/src/calibre/ebooks/readability/readability.py @@ -6,7 +6,7 @@ from __future__ import (unicode_literals, division, absolute_import, import re, sys from collections import defaultdict -from polyglot.builtins import reraise +from polyglot.builtins import reraise, unicode_type from lxml.etree import tostring from lxml.html import (fragment_fromstring, document_fromstring, @@ -17,7 +17,7 @@ from calibre.ebooks.readability.cleaners import html_cleaner, clean_attributes def tounicode(tree_or_node, **kwargs): - kwargs['encoding'] = unicode + kwargs['encoding'] = unicode_type return htostring(tree_or_node, **kwargs) @@ -315,7 +315,7 @@ class Document: def transform_misused_divs_into_paragraphs(self): for elem in self.tags(self.html, 'div'): # transform
s that do not contain other block elements into

s - if not REGEXES['divToPElementsRe'].search(unicode(''.join(map(tostring, list(elem))))): + if not REGEXES['divToPElementsRe'].search(unicode_type(''.join(map(tostring, list(elem))))): # self.debug("Altering %s to p" % (describe(elem))) elem.tag = "p" # print "Fixed element "+describe(elem) diff --git a/src/calibre/ebooks/rtf/rtfml.py b/src/calibre/ebooks/rtf/rtfml.py index bb602aa4d8..8cb1422dc3 100644 --- a/src/calibre/ebooks/rtf/rtfml.py +++ b/src/calibre/ebooks/rtf/rtfml.py @@ -17,6 +17,7 @@ from lxml import etree from calibre.ebooks.metadata import authors_to_string from calibre.utils.img import save_cover_data_to from calibre.utils.imghdr import identify +from polyglot.builtins import unicode_type TAGS = { 'b': '\\b', @@ -75,7 +76,7 @@ def txt2rtf(text): text = text.replace('}', r'\'7d') text = text.replace('\\', r'\'5c') - if not isinstance(text, unicode): + if not isinstance(text, unicode_type): return text buf = cStringIO.StringIO() @@ -119,7 +120,7 @@ class RTFMLizer(object): self.log.debug('Converting %s to RTF markup...' % item.href) # Removing comments is needed as comments with -- inside them can # cause fromstring() to fail - content = re.sub(u'', u'', etree.tostring(item.data, encoding=unicode), flags=re.DOTALL) + content = re.sub(u'', u'', etree.tostring(item.data, encoding=unicode_type), flags=re.DOTALL) content = self.remove_newlines(content) content = self.remove_tabs(content) content = etree.fromstring(content) diff --git a/src/calibre/ebooks/rtf2xml/tokenize.py b/src/calibre/ebooks/rtf2xml/tokenize.py index e2933fbeb9..6b71f88b77 100755 --- a/src/calibre/ebooks/rtf2xml/tokenize.py +++ b/src/calibre/ebooks/rtf2xml/tokenize.py @@ -15,6 +15,7 @@ import os, re from calibre.ebooks.rtf2xml import copy from calibre.utils.mreplace import MReplace from calibre.ptempfile import better_mktemp +from polyglot.builtins import codepoint_to_chr class Tokenize: @@ -93,7 +94,7 @@ class Tokenize: uni_len = len(match_obj.group(0)) if uni_char < 0: uni_char += 65536 - uni_char = unichr(uni_char).encode('ascii', 'xmlcharrefreplace') + uni_char = codepoint_to_chr(uni_char).encode('ascii', 'xmlcharrefreplace') self.__uc_char = self.__uc_value[-1] # there is only an unicode char if len(token)<= uni_len: diff --git a/src/calibre/ebooks/snb/snbfile.py b/src/calibre/ebooks/snb/snbfile.py index a50eb0a710..6dfe66bc8a 100644 --- a/src/calibre/ebooks/snb/snbfile.py +++ b/src/calibre/ebooks/snb/snbfile.py @@ -8,6 +8,7 @@ __docformat__ = 'restructuredtext en' import sys, struct, zlib, bz2, os from calibre import guess_type +from polyglot.builtins import unicode_type class FileStream: @@ -163,7 +164,7 @@ class SNBFile: f.fileSize = os.path.getsize(os.path.join(tdir,fileName)) f.fileBody = open(os.path.join(tdir,fileName), 'rb').read() f.fileName = fileName.replace(os.sep, '/') - if isinstance(f.fileName, unicode): + if isinstance(f.fileName, unicode_type): f.fileName = f.fileName.encode("ascii", "ignore") self.files.append(f) @@ -173,7 +174,7 @@ class SNBFile: f.fileSize = os.path.getsize(os.path.join(tdir,fileName)) f.fileBody = open(os.path.join(tdir,fileName), 'rb').read() f.fileName = fileName.replace(os.sep, '/') - if isinstance(f.fileName, unicode): + if isinstance(f.fileName, unicode_type): f.fileName = f.fileName.encode("ascii", "ignore") self.files.append(f) diff --git a/src/calibre/ebooks/snb/snbml.py b/src/calibre/ebooks/snb/snbml.py index 89e112ac70..29fdf4210a 100644 --- a/src/calibre/ebooks/snb/snbml.py +++ b/src/calibre/ebooks/snb/snbml.py @@ -12,6 +12,7 @@ import os import re from lxml import etree +from polyglot.builtins import unicode_type def ProcessFileName(fileName): @@ -84,7 +85,7 @@ class SNBMLizer(object): from calibre.ebooks.oeb.stylizer import Stylizer output = [u''] stylizer = Stylizer(self.item.data, self.item.href, self.oeb_book, self.opts, self.opts.output_profile) - content = unicode(etree.tostring(self.item.data.find(XHTML('body')), encoding=unicode)) + content = unicode_type(etree.tostring(self.item.data.find(XHTML('body')), encoding=unicode_type)) # content = self.remove_newlines(content) trees = {} for subitem, subtitle in self.subitems: @@ -127,7 +128,7 @@ class SNBMLizer(object): else: prefix = u'' etree.SubElement(bodyTree, "text").text = \ - etree.CDATA(unicode(prefix + line)) + etree.CDATA(unicode_type(prefix + line)) if self.opts and self.opts.snb_insert_empty_line: etree.SubElement(bodyTree, "text").text = \ etree.CDATA(u'') diff --git a/src/calibre/ebooks/txt/markdownml.py b/src/calibre/ebooks/txt/markdownml.py index 3c35564e8c..7cef2b734b 100644 --- a/src/calibre/ebooks/txt/markdownml.py +++ b/src/calibre/ebooks/txt/markdownml.py @@ -15,6 +15,7 @@ from functools import partial from calibre.ebooks.htmlz.oeb2html import OEB2HTML from calibre.ebooks.oeb.base import XHTML, XHTML_NS, barename, namespace, rewrite_links from calibre.ebooks.oeb.stylizer import Stylizer +from polyglot.builtins import unicode_type class MarkdownMLizer(OEB2HTML): @@ -225,7 +226,7 @@ class MarkdownMLizer(OEB2HTML): text.append('+ ') elif li['name'] == 'ol': li['num'] += 1 - text.append(unicode(li['num']) + '. ') + text.append(unicode_type(li['num']) + '. ') # Process tags that contain text. if hasattr(elem, 'text') and elem.text: diff --git a/src/calibre/ebooks/txt/processor.py b/src/calibre/ebooks/txt/processor.py index 7a729f859e..b21d342aab 100644 --- a/src/calibre/ebooks/txt/processor.py +++ b/src/calibre/ebooks/txt/processor.py @@ -15,6 +15,7 @@ from calibre.ebooks.metadata.opf2 import OPFCreator from calibre.ebooks.conversion.preprocess import DocAnalysis from calibre.utils.cleantext import clean_ascii_chars +from polyglot.builtins import unicode_type HTML_TEMPLATE = u'%s \n%s\n' @@ -59,7 +60,7 @@ def split_txt(txt, epub_split_size_kb=0): ''' # Takes care if there is no point to split if epub_split_size_kb > 0: - if isinstance(txt, unicode): + if isinstance(txt, unicode_type): txt = txt.encode('utf-8') length_byte = len(txt) # Calculating the average chunk value for easy splitting as EPUB (+2 as a safe margin) diff --git a/src/calibre/ebooks/txt/txtml.py b/src/calibre/ebooks/txt/txtml.py index 26da604093..fd653f8b7b 100644 --- a/src/calibre/ebooks/txt/txtml.py +++ b/src/calibre/ebooks/txt/txtml.py @@ -11,6 +11,7 @@ Transform OEB content into plain text import re from lxml import etree +from polyglot.builtins import unicode_type BLOCK_TAGS = [ @@ -72,7 +73,7 @@ class TXTMLizer(object): for x in item.data.iterdescendants(etree.Comment): if x.text and '--' in x.text: x.text = x.text.replace('--', '__') - content = unicode(etree.tostring(item.data, encoding=unicode)) + content = unicode_type(etree.tostring(item.data, encoding=unicode_type)) content = self.remove_newlines(content) content = etree.fromstring(content) stylizer = Stylizer(content, item.href, self.oeb_book, self.opts, self.opts.output_profile) diff --git a/src/calibre/ebooks/unihandecode/__init__.py b/src/calibre/ebooks/unihandecode/__init__.py index dc7b0dad63..1ce7d8e5d2 100644 --- a/src/calibre/ebooks/unihandecode/__init__.py +++ b/src/calibre/ebooks/unihandecode/__init__.py @@ -19,6 +19,8 @@ Tranliterate the string from unicode characters to ASCII in Chinese and others. ''' import unicodedata +from calibre.constants import ispy3 + class Unihandecoder(object): preferred_encoding = None @@ -41,8 +43,7 @@ class Unihandecoder(object): self.decoder = Unidecoder() def decode(self, text): - try: - unicode # python2 + if not ispy3: if not isinstance(text, unicode): try: text = unicode(text) @@ -51,8 +52,6 @@ class Unihandecoder(object): text = text.decode(self.preferred_encoding) except: text = text.decode('utf-8', 'replace') - except: # python3, str is unicode - pass # at first unicode normalize it. (see Unicode standards) ntext = unicodedata.normalize('NFKC', text) return self.decoder.decode(ntext) diff --git a/src/calibre/ebooks/unihandecode/pykakasi/jisyo.py b/src/calibre/ebooks/unihandecode/pykakasi/jisyo.py index 1496eea111..6101817a7b 100644 --- a/src/calibre/ebooks/unihandecode/pykakasi/jisyo.py +++ b/src/calibre/ebooks/unihandecode/pykakasi/jisyo.py @@ -4,6 +4,8 @@ # Copyright 2011 Hiroshi Miura from zlib import decompress +from calibre.constants import ispy3 + class jisyo (object): kanwadict = None @@ -32,10 +34,9 @@ class jisyo (object): P('localization/pykakasi/kanadict2.calibre_msgpack', data=True)) def load_jisyo(self, char): - try: # python2 - key = "%04x"%ord(unicode(char)) - except: # python3 - key = "%04x"%ord(char) + if not ispy3: + char = unicode(char) + key = "%04x"%ord(char) try: # already exist? table = self.jisyo_table[key] diff --git a/src/calibre/ebooks/unihandecode/unidecoder.py b/src/calibre/ebooks/unihandecode/unidecoder.py index e8a4bab22a..74b1229ede 100644 --- a/src/calibre/ebooks/unihandecode/unidecoder.py +++ b/src/calibre/ebooks/unihandecode/unidecoder.py @@ -60,6 +60,7 @@ it under the same terms as Perl itself. ''' import re +from calibre.constants import ispy3 from calibre.ebooks.unihandecode.unicodepoints import CODEPOINTS from calibre.ebooks.unihandecode.zhcodepoints import CODEPOINTS as HANCODES @@ -94,18 +95,15 @@ class Unidecoder(object): Find what group character is a part of. ''' # Code groups withing CODEPOINTS take the form 'xAB' - try: # python2 - return 'x%02x' % (ord(unicode(character)) >> 8) - except: - return 'x%02x' % (ord(character) >> 8) + if not ispy3: + character = unicode(character) + return 'x%02x' % (ord(character) >> 8) def grouped_point(self, character): ''' Return the location the replacement character is in the list for a the group character is a part of. ''' - try: # python2 - return ord(unicode(character)) & 255 - except: - return ord(character) & 255 - + if not ispy3: + character = unicode(character) + return ord(character) & 255 diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index feb75a9770..dc8e3993ae 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -35,6 +35,7 @@ from calibre.utils.config import Config, ConfigProxy, JSONConfig, dynamic from calibre.utils.date import UNDEFINED_DATE from calibre.utils.file_type_icons import EXT_MAP from calibre.utils.localization import get_lang +from polyglot.builtins import unicode_type try: NO_URL_FORMATTING = QUrl.None_ @@ -612,7 +613,7 @@ class FileIconProvider(QFileIconProvider): if fileinfo.isDir(): key = 'dir' else: - ext = unicode(fileinfo.completeSuffix()).lower() + ext = unicode_type(fileinfo.completeSuffix()).lower() key = self.key_from_ext(ext) return self.cached_icon(key) @@ -732,7 +733,7 @@ class Translator(QTranslator): def translate(self, *args, **kwargs): try: - src = unicode(args[1]) + src = unicode_type(args[1]) except: return u'' t = _ @@ -763,7 +764,7 @@ def load_builtin_fonts(): fid = QFontDatabase.addApplicationFontFromData(s.read()) if fid > -1: fam = QFontDatabase.applicationFontFamilies(fid) - fam = set(map(unicode, fam)) + fam = set(map(unicode_type, fam)) if u'calibre Symbols' in fam: _rating_font = u'calibre Symbols' @@ -821,7 +822,7 @@ class Application(QApplication): args = sys.argv[:1] args.extend(['-platformpluginpath', sys.extensions_location, '-platform', 'headless']) self.headless = headless - qargs = [i.encode('utf-8') if isinstance(i, unicode) else i for i in args] + qargs = [i.encode('utf-8') if isinstance(i, unicode_type) else i for i in args] self.pi = plugins['progress_indicator'][0] if not isosx and not headless: # On OS X high dpi scaling is turned on automatically by the OS, so we dont need to set it explicitly @@ -871,7 +872,7 @@ class Application(QApplication): self.line_height = max(12, QFontMetrics(self.font()).lineSpacing()) dl = QLocale(get_lang()) - if unicode(dl.bcp47Name()) != u'C': + if unicode_type(dl.bcp47Name()) != u'C': QLocale.setDefault(dl) global gui_thread, qt_app gui_thread = QThread.currentThread() @@ -1009,7 +1010,7 @@ class Application(QApplication): def event(self, e): if callable(self.file_event_hook) and e.type() == QEvent.FileOpen: - path = unicode(e.file()) + path = unicode_type(e.file()) if os.access(path, os.R_OK): with self._file_open_lock: self._file_open_paths.append(path) @@ -1241,7 +1242,7 @@ def elided_text(text, font=None, width=300, pos='middle'): chomp = {'middle':remove_middle, 'left':lambda x:(ellipsis + x[delta:]), 'right':lambda x:(x[:-delta] + ellipsis)}[pos] while len(text) > delta and fm.width(text) > width: text = chomp(text) - return unicode(text) + return unicode_type(text) def find_forms(srcdir): @@ -1366,7 +1367,7 @@ def set_app_uid(val): AppUserModelID.argtypes = [wintypes.LPCWSTR] AppUserModelID.restype = wintypes.HRESULT try: - AppUserModelID(unicode(val)) + AppUserModelID(unicode_type(val)) except Exception as err: prints(u'Failed to set app uid with error:', as_unicode(err)) return False @@ -1375,7 +1376,7 @@ def set_app_uid(val): def add_to_recent_docs(path): from win32com.shell import shell, shellcon - path = unicode(path) + path = unicode_type(path) app_id = get_app_uid() if app_id is None: shell.SHAddToRecentDocs(shellcon.SHARD_PATHW, path) diff --git a/src/calibre/gui2/actions/__init__.py b/src/calibre/gui2/actions/__init__.py index 1f1068ef1e..d60a26e42d 100644 --- a/src/calibre/gui2/actions/__init__.py +++ b/src/calibre/gui2/actions/__init__.py @@ -15,6 +15,7 @@ from calibre import prints from calibre.constants import isosx from calibre.gui2 import Dispatcher from calibre.gui2.keyboard import NameConflict +from polyglot.builtins import unicode_type def menu_action_unique_name(plugin, unique_name): @@ -162,7 +163,7 @@ class InterfaceAction(QObject): action = QAction(text, self.gui) if attr == 'qaction': mt = (action.text() if self.action_menu_clone_qaction is True else - unicode(self.action_menu_clone_qaction)) + unicode_type(self.action_menu_clone_qaction)) self.menuless_qaction = ma = QAction(action.icon(), mt, self.gui) ma.triggered.connect(action.trigger) for a in ((action, ma) if attr == 'qaction' else (action,)): @@ -179,7 +180,7 @@ class InterfaceAction(QObject): keys = ((shortcut,) if isinstance(shortcut, basestring) else tuple(shortcut)) if shortcut_name is None and spec[0]: - shortcut_name = unicode(spec[0]) + shortcut_name = unicode_type(spec[0]) if shortcut_name and self.action_spec[0] and not ( attr == 'qaction' and self.popup_type == QToolButton.InstantPopup): @@ -190,7 +191,7 @@ class InterfaceAction(QObject): group=self.action_spec[0]) except NameConflict as e: try: - prints(unicode(e)) + prints(unicode_type(e)) except: pass shortcut_action.setShortcuts([QKeySequence(key, @@ -240,7 +241,7 @@ class InterfaceAction(QObject): ''' if shortcut_name is None: - shortcut_name = unicode(text) + shortcut_name = unicode_type(text) ac = menu.addAction(text) if icon is not None: if not isinstance(icon, QIcon): diff --git a/src/calibre/gui2/actions/choose_library.py b/src/calibre/gui2/actions/choose_library.py index 3a85bb44dc..67581a1077 100644 --- a/src/calibre/gui2/actions/choose_library.py +++ b/src/calibre/gui2/actions/choose_library.py @@ -20,6 +20,7 @@ from calibre.utils.icu import sort_key from calibre.gui2 import (gprefs, warning_dialog, Dispatcher, error_dialog, question_dialog, info_dialog, open_local_file, choose_dir) from calibre.gui2.actions import InterfaceAction +from polyglot.builtins import unicode_type def db_class(): @@ -144,7 +145,7 @@ class MovedDialog(QDialog): # {{{ self.stats.remove(self.location) def accept(self): - newloc = unicode(self.loc.text()) + newloc = unicode_type(self.loc.text()) if not db_class().exists_at(newloc): error_dialog(self, _('No library found'), _('No existing calibre library found at %s')%newloc, @@ -416,7 +417,7 @@ class ChooseLibraryAction(InterfaceAction): 'Choose a new name for the library %s. ')%name + '

'+_( 'Note that the actual library folder will be renamed.'), text=old_name) - newname = sanitize_file_name_unicode(unicode(newname)) + newname = sanitize_file_name_unicode(unicode_type(newname)) if not ok or not newname or newname == old_name: return newloc = os.path.join(base, newname) diff --git a/src/calibre/gui2/actions/copy_to_library.py b/src/calibre/gui2/actions/copy_to_library.py index 32da577640..d9cb155ca1 100644 --- a/src/calibre/gui2/actions/copy_to_library.py +++ b/src/calibre/gui2/actions/copy_to_library.py @@ -26,6 +26,7 @@ from calibre.gui2.widgets2 import Dialog from calibre.utils.config import prefs from calibre.utils.icu import sort_key, numeric_sort_key from calibre.db.copy_to_library import copy_one_book +from polyglot.builtins import unicode_type def ask_about_cc_mismatch(gui, db, newdb, missing_cols, incompatible_cols): # {{{ @@ -132,7 +133,7 @@ class Worker(Thread): # {{{ except Exception as err: import traceback try: - err = unicode(err) + err = unicode_type(err) except: err = repr(err) self.error = (err, traceback.format_exc()) @@ -260,7 +261,7 @@ class ChooseLibrary(Dialog): # {{{ @property def args(self): - return (unicode(self.le.text()), self.delete_after_copy) + return (unicode_type(self.le.text()), self.delete_after_copy) # }}} @@ -298,7 +299,7 @@ class DuplicatesQuestion(QDialog): # {{{ self.resize(600, 400) def copy_to_clipboard(self): - items = [('✓' if item.checkState() == Qt.Checked else '✗') + ' ' + unicode(item.text()) + items = [('✓' if item.checkState() == Qt.Checked else '✗') + ' ' + unicode_type(item.text()) for item in self.items] QApplication.clipboard().setText('\n'.join(items)) diff --git a/src/calibre/gui2/actions/device.py b/src/calibre/gui2/actions/device.py index 61b967d22b..ee8c4fb402 100644 --- a/src/calibre/gui2/actions/device.py +++ b/src/calibre/gui2/actions/device.py @@ -12,6 +12,7 @@ from calibre.gui2.actions import InterfaceAction from calibre.gui2.dialogs.smartdevice import SmartdeviceDialog from calibre.utils.icu import primary_sort_key from calibre.utils.smtp import config as email_config +from polyglot.builtins import unicode_type class ShareConnMenu(QMenu): # {{{ @@ -54,7 +55,7 @@ class ShareConnMenu(QMenu): # {{{ gr = ConnectShareAction.action_spec[0] for attr in ('folder', ): ac = getattr(self, 'connect_to_%s_action'%attr) - r(prefix + attr, unicode(ac.text()), action=ac, + r(prefix + attr, unicode_type(ac.text()), action=ac, group=gr) r(prefix+' content server', _('Start/stop Content server'), action=self.toggle_server_action, group=gr) diff --git a/src/calibre/gui2/actions/edit_metadata.py b/src/calibre/gui2/actions/edit_metadata.py index de9282c550..2d8ef8e9a1 100644 --- a/src/calibre/gui2/actions/edit_metadata.py +++ b/src/calibre/gui2/actions/edit_metadata.py @@ -26,6 +26,7 @@ from calibre.db.errors import NoSuchFormat from calibre.library.comments import merge_comments from calibre.ebooks.metadata.sources.prefs import msprefs from calibre.gui2.actions.show_quickview import get_quickview_action_plugin +from polyglot.builtins import unicode_type class EditMetadataAction(InterfaceAction): @@ -118,7 +119,7 @@ class EditMetadataAction(InterfaceAction): book_id = db.id(rows[0].row()) mi = db.new_api.get_metadata(book_id) md = QMimeData() - md.setText(unicode(mi)) + md.setText(unicode_type(mi)) md.setData('application/calibre-book-metadata', bytearray(metadata_to_opf(mi, default_lang='und'))) img = db.new_api.cover(book_id, as_image=True) if img: @@ -647,7 +648,7 @@ class EditMetadataAction(InterfaceAction): if not dest_mi.comments: dest_mi.comments = src_mi.comments else: - dest_mi.comments = unicode(dest_mi.comments) + u'\n\n' + unicode(src_mi.comments) + dest_mi.comments = unicode_type(dest_mi.comments) + u'\n\n' + unicode_type(src_mi.comments) if src_mi.title and (not dest_mi.title or dest_mi.title == _('Unknown')): dest_mi.title = src_mi.title if (src_mi.authors and src_mi.authors[0] != _('Unknown')) and (not dest_mi.authors or dest_mi.authors[0] == _('Unknown')): @@ -700,7 +701,7 @@ class EditMetadataAction(InterfaceAction): if not dest_value: db.set_custom(dest_id, src_value, num=colnum) else: - dest_value = unicode(dest_value) + u'\n\n' + unicode(src_value) + dest_value = unicode_type(dest_value) + u'\n\n' + unicode_type(src_value) db.set_custom(dest_id, dest_value, num=colnum) if (dt in {'bool', 'int', 'float', 'rating', 'datetime'} and dest_value is None): db.set_custom(dest_id, src_value, num=colnum) @@ -726,7 +727,7 @@ class EditMetadataAction(InterfaceAction): to_rename = d.to_rename # dict of new text to old ids to_delete = d.to_delete # list of ids for old_id, new_name in to_rename.iteritems(): - model.rename_collection(old_id, new_name=unicode(new_name)) + model.rename_collection(old_id, new_name=unicode_type(new_name)) for item in to_delete: model.delete_collection_using_id(item) self.gui.upload_collections(model.db, view=view, oncard=oncard) diff --git a/src/calibre/gui2/actions/mark_books.py b/src/calibre/gui2/actions/mark_books.py index 40f1fed756..eda6020b5f 100644 --- a/src/calibre/gui2/actions/mark_books.py +++ b/src/calibre/gui2/actions/mark_books.py @@ -12,6 +12,7 @@ from PyQt5.Qt import QTimer, QApplication, Qt from calibre.gui2 import error_dialog from calibre.gui2.actions import InterfaceAction +from polyglot.builtins import unicode_type class MarkBooksAction(InterfaceAction): @@ -120,7 +121,7 @@ class MarkBooksAction(InterfaceAction): def clear_all_marked(self): self.gui.current_db.data.set_marked_ids(()) - if unicode(self.gui.search.text()).startswith('marked:'): + if unicode_type(self.gui.search.text()).startswith('marked:'): self.gui.search.set_search_string('') def mark_field(self, field, add): diff --git a/src/calibre/gui2/actions/polish.py b/src/calibre/gui2/actions/polish.py index fc089bae4d..292dcf33d1 100644 --- a/src/calibre/gui2/actions/polish.py +++ b/src/calibre/gui2/actions/polish.py @@ -10,7 +10,7 @@ __docformat__ = 'restructuredtext en' import os, weakref, shutil, textwrap from collections import OrderedDict from functools import partial -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from PyQt5.Qt import (QDialog, QGridLayout, QIcon, QCheckBox, QLabel, QFrame, QApplication, QDialogButtonBox, Qt, QSize, QSpacerItem, @@ -156,7 +156,7 @@ class Polish(QDialog): # {{{ name, ok = QInputDialog.getText(self, _('Choose name'), _('Choose a name for these settings')) if ok: - name = unicode(name).strip() + name = unicode_type(name).strip() if name: settings = {ac:getattr(self, 'opt_'+ac).isChecked() for ac in self.all_actions} @@ -195,7 +195,7 @@ class Polish(QDialog): # {{{ self.help_label.setText(self.help_text[name]) def help_link_activated(self, link): - link = unicode(link)[1:] + link = unicode_type(link)[1:] self.help_label.setText(self.help_text[link]) @property @@ -269,7 +269,7 @@ class Polish(QDialog): # {{{ QTimer.singleShot(0, self.do_one) def do_book(self, num, book_id, formats): - base = os.path.join(self.tdir, unicode(book_id)) + base = os.path.join(self.tdir, unicode_type(book_id)) os.mkdir(base) db = self.db() opf = os.path.join(base, 'metadata.opf') diff --git a/src/calibre/gui2/actions/toc_edit.py b/src/calibre/gui2/actions/toc_edit.py index 4134068d0c..518e98007a 100644 --- a/src/calibre/gui2/actions/toc_edit.py +++ b/src/calibre/gui2/actions/toc_edit.py @@ -14,6 +14,7 @@ from PyQt5.Qt import (QTimer, QDialog, QGridLayout, QCheckBox, QLabel, from calibre.gui2 import error_dialog, gprefs from calibre.gui2.actions import InterfaceAction +from polyglot.builtins import unicode_type SUPPORTED = {'EPUB', 'AZW3'} @@ -55,7 +56,7 @@ class ChooseFormat(QDialog): # {{{ def fget(self): for b in self.buttons: if b.isChecked(): - yield unicode(b.text())[1:] + yield unicode_type(b.text())[1:] def fset(self, formats): formats = {x.upper() for x in formats} diff --git a/src/calibre/gui2/actions/unpack_book.py b/src/calibre/gui2/actions/unpack_book.py index 5f4476636e..e92627ea57 100644 --- a/src/calibre/gui2/actions/unpack_book.py +++ b/src/calibre/gui2/actions/unpack_book.py @@ -17,6 +17,7 @@ from calibre.gui2.actions import InterfaceAction from calibre.ptempfile import (PersistentTemporaryDirectory, PersistentTemporaryFile) from calibre.utils.config import prefs, tweaks +from polyglot.builtins import unicode_type class UnpackBook(QDialog): @@ -34,7 +35,7 @@ class UnpackBook(QDialog): index_is_id=True)) button = self.fmt_choice_buttons[0] - button_map = {unicode(x.text()):x for x in self.fmt_choice_buttons} + button_map = {unicode_type(x.text()):x for x in self.fmt_choice_buttons} of = prefs['output_format'].upper() df = tweaks.get('default_tweak_format', None) lf = gprefs.get('last_tweak_format', None) @@ -281,7 +282,7 @@ class UnpackBook(QDialog): def current_format(self): for b in self.fmt_choice_buttons: if b.isChecked(): - return unicode(b.text()) + return unicode_type(b.text()) class UnpackBookAction(InterfaceAction): diff --git a/src/calibre/gui2/add.py b/src/calibre/gui2/add.py index aa11c9bd0f..c9bb3fbc41 100644 --- a/src/calibre/gui2/add.py +++ b/src/calibre/gui2/add.py @@ -11,7 +11,7 @@ from threading import Thread from collections import OrderedDict from Queue import Empty from io import BytesIO -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from PyQt5.Qt import QObject, Qt, pyqtSignal @@ -271,7 +271,7 @@ class Adder(QObject): except Failure as err: error_dialog(self.pd, _('Cannot add books'), _( 'Failed to add some books, click "Show details" for more information.'), - det_msg=unicode(err.failure_message) + '\n' + unicode(err.details), show=True) + det_msg=unicode_type(err.failure_message) + '\n' + unicode_type(err.details), show=True) self.pd.canceled = True else: # All tasks completed diff --git a/src/calibre/gui2/add_filters.py b/src/calibre/gui2/add_filters.py index 1ef66523ef..b6995b63b8 100644 --- a/src/calibre/gui2/add_filters.py +++ b/src/calibre/gui2/add_filters.py @@ -6,7 +6,7 @@ from __future__ import (unicode_literals, division, absolute_import, print_function) from collections import OrderedDict -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from calibre.db.adding import compile_glob, filter_filename, compile_rule from calibre.gui2 import elided_text, Application, error_dialog @@ -66,12 +66,12 @@ class RuleEdit(RuleEditBase): def rule(self, rule): def sc(name): c = getattr(self, name) - idx = c.findData(unicode(rule.get(name, ''))) + idx = c.findData(unicode_type(rule.get(name, ''))) if idx < 0: idx = 0 c.setCurrentIndex(idx) sc('action'), sc('match_type') - self.query.setText(unicode(rule.get('query', '')).strip()) + self.query.setText(unicode_type(rule.get('query', '')).strip()) def validate(self): ans = super(RuleEdit, self).validate() diff --git a/src/calibre/gui2/author_mapper.py b/src/calibre/gui2/author_mapper.py index c38ae4bb80..a5f52678d1 100644 --- a/src/calibre/gui2/author_mapper.py +++ b/src/calibre/gui2/author_mapper.py @@ -15,6 +15,7 @@ from calibre.gui2.tag_mapper import ( Tester as TesterBase ) from calibre.utils.config import JSONConfig +from polyglot.builtins import unicode_type author_maps = JSONConfig('author-mapping-rules') @@ -66,13 +67,13 @@ class RuleEdit(RuleEditBase): def rule(self, rule): def sc(name): c = getattr(self, name) - idx = c.findData(unicode(rule.get(name, ''))) + idx = c.findData(unicode_type(rule.get(name, ''))) if idx < 0: idx = 0 c.setCurrentIndex(idx) sc('match_type'), sc('action') - self.query.setText(unicode(rule.get('query', '')).strip()) - self.replace.setText(unicode(rule.get('replace', '')).strip()) + self.query.setText(unicode_type(rule.get('query', '')).strip()) + self.replace.setText(unicode_type(rule.get('replace', '')).strip()) class RuleEditDialog(RuleEditDialogBase): diff --git a/src/calibre/gui2/bars.py b/src/calibre/gui2/bars.py index cb1b039278..f861c71525 100644 --- a/src/calibre/gui2/bars.py +++ b/src/calibre/gui2/bars.py @@ -19,6 +19,7 @@ except ImportError: from calibre.constants import isosx from calibre.gui2 import gprefs, native_menubar_defaults, config from calibre.gui2.throbber import ThrobbingButton +from polyglot.builtins import unicode_type class RevealBar(QWidget): # {{{ @@ -303,7 +304,7 @@ class ToolBar(QToolBar): # {{{ mime = 'application/calibre+from_device' if data.hasFormat(mime): - paths = [unicode(u.toLocalFile()) for u in data.urls()] + paths = [unicode_type(u.toLocalFile()) for u in data.urls()] if paths: self.gui.iactions['Add Books'].add_books_from_device( self.gui.current_view(), paths=paths) diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py index e3943e933c..af32669c1a 100644 --- a/src/calibre/gui2/book_details.py +++ b/src/calibre/gui2/book_details.py @@ -34,6 +34,7 @@ from calibre.gui2.dnd import ( from calibre.utils.config import tweaks from calibre.utils.img import blend_image, image_from_x from calibre.utils.localization import is_rtl +from polyglot.builtins import unicode_type _css = None InternetSearch = namedtuple('InternetSearch', 'author where') @@ -57,7 +58,7 @@ def css(): val = P('templates/book_details.css', data=True).decode('utf-8') col = QApplication.instance().palette().color(QPalette.Link).name() val = val.replace('LINK_COLOR', col) - _css = re.sub(unicode(r'/\*.*?\*/'), u'', val, flags=re.DOTALL) + _css = re.sub(unicode_type(r'/\*.*?\*/'), u'', val, flags=re.DOTALL) return _css @@ -114,12 +115,12 @@ def render_html(mi, css, vertical, widget, all_fields=False, render_data_func=No if col.isValid(): col = col.toRgb() if col.isValid(): - ans = unicode(col.name()) + ans = unicode_type(col.name()) return ans fi = QFontInfo(QApplication.font(widget)) f = fi.pixelSize() + 1 + int(tweaks['change_book_details_font_size_by']) - fam = unicode(fi.family()).strip().replace('"', '') + fam = unicode_type(fi.family()).strip().replace('"', '') if not fam: fam = 'sans-serif' @@ -195,7 +196,7 @@ def details_context_menu_event(view, ev, book_info): # {{{ p = view.page() mf = p.mainFrame() r = mf.hitTestContent(ev.pos()) - url = unicode(r.linkUrl().toString(NO_URL_FORMATTING)).strip() + url = unicode_type(r.linkUrl().toString(NO_URL_FORMATTING)).strip() menu = p.createStandardContextMenu() ca = view.pageAction(p.Copy) for action in list(menu.actions()): @@ -264,7 +265,7 @@ def details_context_menu_event(view, ev, book_info): # {{{ else: el = r.linkElement() data = el.attribute('data-item') - author = el.toPlainText() if unicode(el.attribute('calibre-data')) == u'authors' else None + author = el.toPlainText() if unicode_type(el.attribute('calibre-data')) == u'authors' else None if url and not url.startswith('search:'): for a, t in [('copy', _('&Copy link')), ]: @@ -623,9 +624,9 @@ class BookInfo(QWebView): def link_activated(self, link): self._link_clicked = True - if unicode(link.scheme()) in ('http', 'https'): + if unicode_type(link.scheme()) in ('http', 'https'): return open_url(link) - link = unicode(link.toString(NO_URL_FORMATTING)) + link = unicode_type(link.toString(NO_URL_FORMATTING)) self.link_clicked.emit(link) def turnoff_scrollbar(self, *args): diff --git a/src/calibre/gui2/catalog/catalog_bibtex.py b/src/calibre/gui2/catalog/catalog_bibtex.py index 1464bc8124..e98f9a3a09 100644 --- a/src/calibre/gui2/catalog/catalog_bibtex.py +++ b/src/calibre/gui2/catalog/catalog_bibtex.py @@ -9,6 +9,7 @@ __docformat__ = 'restructuredtext en' from calibre.gui2 import gprefs from calibre.gui2.catalog.catalog_bibtex_ui import Ui_Form +from polyglot.builtins import unicode_type from PyQt5.Qt import QWidget, QListWidgetItem @@ -49,7 +50,7 @@ class PluginWidget(QWidget, Ui_Form): # Restore the activated db_fields from last use for x in xrange(self.db_fields.count()): item = self.db_fields.item(x) - item.setSelected(unicode(item.text()) in fields) + item.setSelected(unicode_type(item.text()) in fields) self.bibfile_enc.clear() self.bibfile_enc.addItems(['utf-8', 'cp1252', 'ascii/LaTeX']) self.bibfile_enctag.clear() @@ -74,12 +75,12 @@ class PluginWidget(QWidget, Ui_Form): for x in xrange(self.db_fields.count()): item = self.db_fields.item(x) if item.isSelected(): - fields.append(unicode(item.text())) + fields.append(unicode_type(item.text())) gprefs.set(self.name+'_db_fields', fields) # Dictionary currently activated fields if len(self.db_fields.selectedItems()): - opts_dict = {'fields':[unicode(i.text()) for i in self.db_fields.selectedItems()]} + opts_dict = {'fields':[unicode_type(i.text()) for i in self.db_fields.selectedItems()]} else: opts_dict = {'fields':['all']} @@ -92,7 +93,7 @@ class PluginWidget(QWidget, Ui_Form): elif opt[0] in ['impcit', 'addfiles'] : opt_value = getattr(self, opt[0]).isChecked() else : - opt_value = unicode(getattr(self, opt[0]).text()) + opt_value = unicode_type(getattr(self, opt[0]).text()) gprefs.set(self.name + '_' + opt[0], opt_value) opts_dict[opt[0]] = opt_value diff --git a/src/calibre/gui2/catalog/catalog_csv_xml.py b/src/calibre/gui2/catalog/catalog_csv_xml.py index ec3480a215..6280b606b7 100644 --- a/src/calibre/gui2/catalog/catalog_csv_xml.py +++ b/src/calibre/gui2/catalog/catalog_csv_xml.py @@ -8,6 +8,7 @@ __docformat__ = 'restructuredtext en' from calibre.gui2 import gprefs from calibre.gui2.ui import get_gui +from polyglot.builtins import unicode_type from PyQt5.Qt import QWidget, QListWidgetItem, Qt, QVBoxLayout, QLabel, QListWidget @@ -84,16 +85,16 @@ class PluginWidget(QWidget): # Restore the activated fields from last use for x in range(self.db_fields.count()): item = self.db_fields.item(x) - item.setCheckState(Qt.Checked if unicode(item.data(Qt.UserRole)) in fields else Qt.Unchecked) + item.setCheckState(Qt.Checked if unicode_type(item.data(Qt.UserRole)) in fields else Qt.Unchecked) def options(self): # Save the currently activated fields fields, all_fields = [], [] for x in xrange(self.db_fields.count()): item = self.db_fields.item(x) - all_fields.append(unicode(item.data(Qt.UserRole))) + all_fields.append(unicode_type(item.data(Qt.UserRole))) if item.checkState() == Qt.Checked: - fields.append(unicode(item.data(Qt.UserRole))) + fields.append(unicode_type(item.data(Qt.UserRole))) set_saved_field_data(self.name, fields, {x:i for i, x in enumerate(all_fields)}) # Return a dictionary with current options for this widget diff --git a/src/calibre/gui2/catalog/catalog_epub_mobi.py b/src/calibre/gui2/catalog/catalog_epub_mobi.py index d2b80a416f..3ea94eb7f6 100644 --- a/src/calibre/gui2/catalog/catalog_epub_mobi.py +++ b/src/calibre/gui2/catalog/catalog_epub_mobi.py @@ -16,6 +16,7 @@ from calibre.gui2 import gprefs, open_url, question_dialog, error_dialog from calibre.utils.config import JSONConfig from calibre.utils.icu import sort_key from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type from catalog_epub_mobi_ui import Ui_Form from PyQt5.Qt import (Qt, QAbstractItemView, QCheckBox, QComboBox, @@ -202,7 +203,7 @@ class PluginWidget(QWidget,Ui_Form): results = _('No genres will be excluded') - regex = unicode(getattr(self, 'exclude_genre').text()).strip() + regex = unicode_type(getattr(self, 'exclude_genre').text()).strip() if not regex: self.exclude_genre_results.clear() self.exclude_genre_results.setText(results) @@ -277,7 +278,7 @@ class PluginWidget(QWidget,Ui_Form): new_source = self.genre_source_field.currentText() self.genre_source_field_name = new_source if new_source != _('Tags'): - genre_source_spec = self.genre_source_fields[unicode(new_source)] + genre_source_spec = self.genre_source_fields[unicode_type(new_source)] self.genre_source_field_name = genre_source_spec['field'] self.exclude_genre_changed() @@ -297,7 +298,7 @@ class PluginWidget(QWidget,Ui_Form): new_source = self.header_note_source_field.currentText() self.header_note_source_field_name = new_source if new_source > '': - header_note_source_spec = self.header_note_source_fields[unicode(new_source)] + header_note_source_spec = self.header_note_source_fields[unicode_type(new_source)] self.header_note_source_field_name = header_note_source_spec['field'] def initialize(self, name, db): @@ -338,7 +339,7 @@ class PluginWidget(QWidget,Ui_Form): c_name, c_def, c_type = opt opt_value = gprefs.get(self.name + '_' + c_name, c_def) if c_type in ['check_box']: - getattr(self, c_name).setChecked(eval(unicode(opt_value))) + getattr(self, c_name).setChecked(eval(unicode_type(opt_value))) getattr(self, c_name).clicked.connect(partial(self.settings_changed, c_name)) elif c_type in ['combo_box']: if opt_value is None: @@ -385,21 +386,21 @@ class PluginWidget(QWidget,Ui_Form): # Init self.merge_source_field_name self.merge_source_field_name = '' - cs = unicode(self.merge_source_field.currentText()) + cs = unicode_type(self.merge_source_field.currentText()) if cs > '': merge_source_spec = self.merge_source_fields[cs] self.merge_source_field_name = merge_source_spec['field'] # Init self.header_note_source_field_name self.header_note_source_field_name = '' - cs = unicode(self.header_note_source_field.currentText()) + cs = unicode_type(self.header_note_source_field.currentText()) if cs > '': header_note_source_spec = self.header_note_source_fields[cs] self.header_note_source_field_name = header_note_source_spec['field'] # Init self.genre_source_field_name self.genre_source_field_name = _('Tags') - cs = unicode(self.genre_source_field.currentText()) + cs = unicode_type(self.genre_source_field.currentText()) if cs != _('Tags'): genre_source_spec = self.genre_source_fields[cs] self.genre_source_field_name = genre_source_spec['field'] @@ -433,7 +434,7 @@ class PluginWidget(QWidget,Ui_Form): new_source = self.merge_source_field.currentText() self.merge_source_field_name = new_source if new_source > '': - merge_source_spec = self.merge_source_fields[unicode(new_source)] + merge_source_spec = self.merge_source_fields[unicode_type(new_source)] self.merge_source_field_name = merge_source_spec['field'] if not self.merge_before.isChecked() and not self.merge_after.isChecked(): self.merge_after.setChecked(True) @@ -468,11 +469,11 @@ class PluginWidget(QWidget,Ui_Form): if c_type in ['check_box', 'radio_button']: opt_value = getattr(self, c_name).isChecked() elif c_type in ['combo_box']: - opt_value = unicode(getattr(self,c_name).currentText()).strip() + opt_value = unicode_type(getattr(self,c_name).currentText()).strip() elif c_type in ['line_edit']: - opt_value = unicode(getattr(self, c_name).text()).strip() + opt_value = unicode_type(getattr(self, c_name).text()).strip() elif c_type in ['spin_box']: - opt_value = unicode(getattr(self, c_name).value()) + opt_value = unicode_type(getattr(self, c_name).value()) elif c_type in ['table_widget']: if c_name == 'prefix_rules_tw': opt_value = self.prefix_rules_table.get_data() @@ -619,9 +620,9 @@ class PluginWidget(QWidget,Ui_Form): else: continue if c_type in ['check_box']: - getattr(self, c_name).setChecked(eval(unicode(opt_value))) + getattr(self, c_name).setChecked(eval(unicode_type(opt_value))) if c_name == 'generate_genres': - self.genre_source_field.setEnabled(eval(unicode(opt_value))) + self.genre_source_field.setEnabled(eval(unicode_type(opt_value))) elif c_type in ['combo_box']: if opt_value is None: index = 0 @@ -682,7 +683,7 @@ class PluginWidget(QWidget,Ui_Form): return item_id = self.preset_field.currentIndex() - item_name = unicode(self.preset_field.currentText()) + item_name = unicode_type(self.preset_field.currentText()) self.preset_field.blockSignals(True) self.preset_field.removeItem(item_id) @@ -710,7 +711,7 @@ class PluginWidget(QWidget,Ui_Form): error_dialog(self, _("Save catalog preset"), _("You must provide a name."), show=True) new = True - name = unicode(name) + name = unicode_type(name) if name in self.presets.keys(): if not question_dialog(self, _("Save catalog preset"), _("That saved preset already exists and will be overwritten. " @@ -734,11 +735,11 @@ class PluginWidget(QWidget,Ui_Form): elif c_type in ['combo_box']: if c_name == 'preset_field': continue - opt_value = unicode(getattr(self,c_name).currentText()).strip() + opt_value = unicode_type(getattr(self,c_name).currentText()).strip() elif c_type in ['line_edit']: - opt_value = unicode(getattr(self, c_name).text()).strip() + opt_value = unicode_type(getattr(self, c_name).text()).strip() elif c_type in ['spin_box']: - opt_value = unicode(getattr(self, c_name).value()) + opt_value = unicode_type(getattr(self, c_name).value()) elif c_type in ['table_widget']: if c_name == 'prefix_rules_tw': opt_value = self.prefix_rules_table.get_data() @@ -767,8 +768,8 @@ class PluginWidget(QWidget,Ui_Form): preset['merge_comments_rule'] = "%s:%s:%s" % \ (self.merge_source_field_name, checked, include_hr) - preset['header_note_source_field'] = unicode(self.header_note_source_field.currentText()) - preset['genre_source_field'] = unicode(self.genre_source_field.currentText()) + preset['header_note_source_field'] = unicode_type(self.header_note_source_field.currentText()) + preset['genre_source_field'] = unicode_type(self.genre_source_field.currentText()) # Append the current output profile try: @@ -979,7 +980,7 @@ class GenericRulesTable(QTableWidget): first = rows[0].row() + 1 last = rows[-1].row() + 1 - first_rule_name = unicode(self.cellWidget(first-1,self.COLUMNS['NAME']['ordinal']).text()).strip() + first_rule_name = unicode_type(self.cellWidget(first-1,self.COLUMNS['NAME']['ordinal']).text()).strip() message = _("Are you sure you want to delete '%s'?") % (first_rule_name) if len(rows) > 1: message = _('Are you sure you want to delete rules #%(first)d-%(last)d?') % dict(first=first, last=last) @@ -1134,15 +1135,15 @@ class GenericRulesTable(QTableWidget): elif source_field == _('Tags'): values = sorted(self.db.all_tags(), key=sort_key) else: - if self.eligible_custom_fields[unicode(source_field)]['datatype'] in ['enumeration', 'text']: + if self.eligible_custom_fields[unicode_type(source_field)]['datatype'] in ['enumeration', 'text']: values = self.db.all_custom(self.db.field_metadata.key_to_label( - self.eligible_custom_fields[unicode(source_field)]['field'])) + self.eligible_custom_fields[unicode_type(source_field)]['field'])) values = sorted(values, key=sort_key) - elif self.eligible_custom_fields[unicode(source_field)]['datatype'] in ['bool']: + elif self.eligible_custom_fields[unicode_type(source_field)]['datatype'] in ['bool']: values = [_('True'),_('False'),_('unspecified')] - elif self.eligible_custom_fields[unicode(source_field)]['datatype'] in ['composite']: + elif self.eligible_custom_fields[unicode_type(source_field)]['datatype'] in ['composite']: values = [_('any value'),_('unspecified')] - elif self.eligible_custom_fields[unicode(source_field)]['datatype'] in ['datetime']: + elif self.eligible_custom_fields[unicode_type(source_field)]['datatype'] in ['datetime']: values = [_('any date'),_('unspecified')] values_combo = ComboBox(self, values, pattern) @@ -1196,9 +1197,9 @@ class ExclusionRules(GenericRulesTable): data = self.create_blank_row_data() data['ordinal'] = row data['enabled'] = self.item(row,self.COLUMNS['ENABLED']['ordinal']).checkState() == Qt.Checked - data['name'] = unicode(self.cellWidget(row,self.COLUMNS['NAME']['ordinal']).text()).strip() - data['field'] = unicode(self.cellWidget(row,self.COLUMNS['FIELD']['ordinal']).currentText()).strip() - data['pattern'] = unicode(self.cellWidget(row,self.COLUMNS['PATTERN']['ordinal']).currentText()).strip() + data['name'] = unicode_type(self.cellWidget(row,self.COLUMNS['NAME']['ordinal']).text()).strip() + data['field'] = unicode_type(self.cellWidget(row,self.COLUMNS['FIELD']['ordinal']).currentText()).strip() + data['pattern'] = unicode_type(self.cellWidget(row,self.COLUMNS['PATTERN']['ordinal']).currentText()).strip() return data def create_blank_row_data(self): @@ -1290,10 +1291,10 @@ class PrefixRules(GenericRulesTable): data = self.create_blank_row_data() data['ordinal'] = row data['enabled'] = self.item(row,self.COLUMNS['ENABLED']['ordinal']).checkState() == Qt.Checked - data['name'] = unicode(self.cellWidget(row,self.COLUMNS['NAME']['ordinal']).text()).strip() - data['prefix'] = unicode(self.cellWidget(row,self.COLUMNS['PREFIX']['ordinal']).currentText()).strip() - data['field'] = unicode(self.cellWidget(row,self.COLUMNS['FIELD']['ordinal']).currentText()).strip() - data['pattern'] = unicode(self.cellWidget(row,self.COLUMNS['PATTERN']['ordinal']).currentText()).strip() + data['name'] = unicode_type(self.cellWidget(row,self.COLUMNS['NAME']['ordinal']).text()).strip() + data['prefix'] = unicode_type(self.cellWidget(row,self.COLUMNS['PREFIX']['ordinal']).currentText()).strip() + data['field'] = unicode_type(self.cellWidget(row,self.COLUMNS['FIELD']['ordinal']).currentText()).strip() + data['pattern'] = unicode_type(self.cellWidget(row,self.COLUMNS['PATTERN']['ordinal']).currentText()).strip() return data def create_blank_row_data(self): diff --git a/src/calibre/gui2/comments_editor.py b/src/calibre/gui2/comments_editor.py index 576d2591d1..300f024669 100644 --- a/src/calibre/gui2/comments_editor.py +++ b/src/calibre/gui2/comments_editor.py @@ -27,6 +27,7 @@ from calibre.gui2.widgets import LineEditECM from calibre.utils.soupparser import fromstring from calibre.utils.config import tweaks from calibre.utils.imghdr import what +from polyglot.builtins import unicode_type class PageAction(QAction): # {{{ @@ -214,13 +215,13 @@ class EditorWidget(QWebView, LineEditECM): # {{{ col = QColorDialog.getColor(Qt.black, self, _('Choose foreground color'), QColorDialog.ShowAlphaChannel) if col.isValid(): - self.exec_command('foreColor', unicode(col.name())) + self.exec_command('foreColor', unicode_type(col.name())) def background_color(self): col = QColorDialog.getColor(Qt.white, self, _('Choose background color'), QColorDialog.ShowAlphaChannel) if col.isValid(): - self.exec_command('hiliteColor', unicode(col.name())) + self.exec_command('hiliteColor', unicode_type(col.name())) def insert_hr(self, *args): self.exec_command('insertHTML', '


') @@ -231,7 +232,7 @@ class EditorWidget(QWebView, LineEditECM): # {{{ return url = self.parse_link(link) if url.isValid(): - url = unicode(url.toString(NO_URL_FORMATTING)) + url = unicode_type(url.toString(NO_URL_FORMATTING)) self.setFocus(Qt.OtherFocusReason) if is_image: self.exec_command('insertHTML', @@ -293,7 +294,7 @@ class EditorWidget(QWebView, LineEditECM): # {{{ d.resize(d.sizeHint()) link, name, is_image = None, None, False if d.exec_() == d.Accepted: - link, name = unicode(d.url.text()).strip(), unicode(d.name.text()).strip() + link, name = unicode_type(d.url.text()).strip(), unicode_type(d.name.text()).strip() is_image = d.treat_as_image.isChecked() return link, name, is_image @@ -327,7 +328,7 @@ class EditorWidget(QWebView, LineEditECM): # {{{ frame = self.page().mainFrame() if arg is not None: js = 'document.execCommand("%s", false, %s);' % (cmd, - json.dumps(unicode(arg))) + json.dumps(unicode_type(arg))) else: js = 'document.execCommand("%s", false, null);' % cmd frame.evaluateJavaScript(js) @@ -343,10 +344,10 @@ class EditorWidget(QWebView, LineEditECM): # {{{ try: if not self.page().mainFrame().documentElement().findFirst('meta[name="calibre-dont-sanitize"]').isNull(): # Bypass cleanup if special meta tag exists - return unicode(self.page().mainFrame().toHtml()) - check = unicode(self.page().mainFrame().toPlainText()).strip() - raw = unicode(self.page().mainFrame().toHtml()) - raw = xml_to_unicode(raw, strip_encoding_pats=True, + return unicode_type(self.page().mainFrame().toHtml()) + check = unicode_type(self.page().mainFrame().toPlainText()).strip() + raw = unicode_type(self.page().mainFrame().toHtml()) + raw = xml_to_unicode_type(raw, strip_encoding_pats=True, resolve_entities=True)[0] raw = self.comments_pat.sub('', raw) if not check and ' 1: @@ -395,13 +396,13 @@ class EditorWidget(QWebView, LineEditECM): # {{{ return mf = self.page().mainFrame() mf.evaluateJavaScript('document.execCommand("selectAll", false, null)') - mf.evaluateJavaScript('document.execCommand("insertHTML", false, %s)' % json.dumps(unicode(val))) + mf.evaluateJavaScript('document.execCommand("insertHTML", false, %s)' % json.dumps(unicode_type(val))) self.set_font_style() def set_font_style(self): fi = QFontInfo(QApplication.font(self)) f = fi.pixelSize() + 1 + int(tweaks['change_book_details_font_size_by']) - fam = unicode(fi.family()).strip().replace('"', '') + fam = unicode_type(fi.family()).strip().replace('"', '') if not fam: fam = 'sans-serif' style = 'font-size: %fpx; font-family:"%s",sans-serif;' % (f, fam) @@ -781,7 +782,7 @@ class Editor(QWidget): # {{{ self.wyswyg_dirty = False elif index == 0: # changing to wyswyg if self.source_dirty: - self.editor.html = unicode(self.code_edit.toPlainText()) + self.editor.html = unicode_type(self.code_edit.toPlainText()) self.source_dirty = False @dynamic_property diff --git a/src/calibre/gui2/complete2.py b/src/calibre/gui2/complete2.py index 18d5a79883..d1f801cf84 100644 --- a/src/calibre/gui2/complete2.py +++ b/src/calibre/gui2/complete2.py @@ -22,6 +22,7 @@ from calibre.constants import isosx, get_osx_version from calibre.utils.icu import sort_key, primary_startswith, primary_contains from calibre.gui2.widgets import EnComboBox, LineEditECM from calibre.utils.config import tweaks +from polyglot.builtins import unicode_type def containsq(x, prefix): @@ -37,7 +38,7 @@ class CompleteModel(QAbstractListModel): # {{{ self.current_prefix = '' def set_items(self, items): - items = [unicode(x.strip()) for x in items] + items = [unicode_type(x.strip()) for x in items] items = [x for x in items if x] items = tuple(sorted(items, key=self.sort_func)) self.beginResetModel() @@ -111,7 +112,7 @@ class Completer(QListView): # {{{ return self.hide() text = self.model().data(index, Qt.DisplayRole) - self.item_selected.emit(unicode(text)) + self.item_selected.emit(unicode_type(text)) def set_items(self, items): self.model().set_items(items) @@ -389,7 +390,7 @@ class LineEdit(QLineEdit, LineEditECM): def update_completions(self): ' Update the list of completions ' self.original_cursor_pos = cpos = self.cursorPosition() - text = unicode(self.text()) + text = unicode_type(self.text()) prefix = text[:cpos] complete_prefix = prefix.lstrip() if self.sep: @@ -406,7 +407,7 @@ class LineEdit(QLineEdit, LineEditECM): cursor_pos = self.cursorPosition() self.original_cursor_pos = None # Split text - curtext = unicode(self.text()) + curtext = unicode_type(self.text()) before_text = curtext[:cursor_pos] after_text = curtext[cursor_pos:].rstrip() # Remove the completion prefix from the before text @@ -426,7 +427,7 @@ class LineEdit(QLineEdit, LineEditECM): return before_text + completed_text, after_text def completion_selected(self, text): - before_text, after_text = self.get_completed_text(unicode(text)) + before_text, after_text = self.get_completed_text(unicode_type(text)) self.setText(before_text + after_text) self.setCursorPosition(len(before_text)) self.item_selected.emit(text) @@ -466,7 +467,7 @@ class EditWithComplete(EnComboBox): self.lineEdit().set_add_separator(what) def show_initial_value(self, what): - what = unicode(what) if what else u'' + what = unicode_type(what) if what else u'' self.setText(what) self.lineEdit().selectAll() @@ -490,7 +491,7 @@ class EditWithComplete(EnComboBox): # }}} def text(self): - return unicode(self.lineEdit().text()) + return unicode_type(self.lineEdit().text()) def selectAll(self): self.lineEdit().selectAll() diff --git a/src/calibre/gui2/convert/__init__.py b/src/calibre/gui2/convert/__init__.py index e7f5aec12e..b347e648bd 100644 --- a/src/calibre/gui2/convert/__init__.py +++ b/src/calibre/gui2/convert/__init__.py @@ -19,6 +19,7 @@ from calibre.ebooks.conversion.config import ( from calibre import prepare_string_for_xml from calibre.customize.ui import plugin_for_input_format from calibre.gui2.font_family_chooser import FontFamilyChooser +from polyglot.builtins import unicode_type def config_widget_for_input_plugin(plugin): @@ -100,7 +101,7 @@ class Widget(QWidget): buddy = g.buddy() if buddy is not None and hasattr(buddy, '_help'): g._help = buddy._help - htext = unicode(buddy.toolTip()).strip() + htext = unicode_type(buddy.toolTip()).strip() g.setToolTip(htext) g.setWhatsThis(htext) g.__class__.enterEvent = lambda obj, event: self.set_help(getattr(obj, '_help', obj.toolTip())) @@ -149,18 +150,18 @@ class Widget(QWidget): return g.value() elif isinstance(g, (QLineEdit, QTextEdit, QPlainTextEdit)): func = getattr(g, 'toPlainText', getattr(g, 'text', None))() - ans = unicode(func) + ans = unicode_type(func) if self.STRIP_TEXT_FIELDS: ans = ans.strip() if not ans: ans = None return ans elif isinstance(g, QFontComboBox): - return unicode(QFontInfo(g.currentFont()).family()) + return unicode_type(QFontInfo(g.currentFont()).family()) elif isinstance(g, FontFamilyChooser): return g.font_family elif isinstance(g, EncodingComboBox): - ans = unicode(g.currentText()).strip() + ans = unicode_type(g.currentText()).strip() try: codecs.lookup(ans) except: @@ -169,7 +170,7 @@ class Widget(QWidget): ans = None return ans elif isinstance(g, QComboBox): - return unicode(g.currentText()) + return unicode_type(g.currentText()) elif isinstance(g, QCheckBox): return bool(g.isChecked()) elif isinstance(g, XPathEdit): @@ -245,7 +246,7 @@ class Widget(QWidget): g.edit.setText(val if val else '') else: raise Exception('Can\'t set value %s in %s'%(repr(val), - unicode(g.objectName()))) + unicode_type(g.objectName()))) self.post_set_value(g, val) def set_help(self, msg): diff --git a/src/calibre/gui2/convert/bulk.py b/src/calibre/gui2/convert/bulk.py index 5ec8e2f8d4..57fe421a17 100644 --- a/src/calibre/gui2/convert/bulk.py +++ b/src/calibre/gui2/convert/bulk.py @@ -20,6 +20,7 @@ from calibre.ebooks.conversion.plumber import Plumber from calibre.ebooks.conversion.config import sort_formats_by_preference, get_output_formats from calibre.utils.config import prefs from calibre.utils.logging import Log +from polyglot.builtins import unicode_type class BulkConfig(Config): @@ -124,7 +125,7 @@ class BulkConfig(Config): preferred_output_format and preferred_output_format \ in output_formats else sort_formats_by_preference(output_formats, [prefs['output_format']])[0] - self.output_formats.addItems(list(map(unicode, [x.upper() for x in + self.output_formats.addItems(list(map(unicode_type, [x.upper() for x in output_formats]))) self.output_formats.setCurrentIndex(output_formats.index(preferred_output_format)) diff --git a/src/calibre/gui2/convert/debug.py b/src/calibre/gui2/convert/debug.py index ab1eae308c..16d4db42c9 100644 --- a/src/calibre/gui2/convert/debug.py +++ b/src/calibre/gui2/convert/debug.py @@ -12,6 +12,7 @@ from calibre.gui2.convert.debug_ui import Ui_Form from calibre.gui2.convert import Widget from calibre.gui2 import error_dialog, choose_dir from calibre.ebooks.conversion.config import OPTIONS +from polyglot.builtins import unicode_type class DebugWidget(Widget, Ui_Form): @@ -38,7 +39,7 @@ class DebugWidget(Widget, Ui_Form): def pre_commit_check(self): try: - x = unicode(self.opt_debug_pipeline.text()).strip() + x = unicode_type(self.opt_debug_pipeline.text()).strip() if not x: return True x = os.path.abspath(x) @@ -52,7 +53,7 @@ class DebugWidget(Widget, Ui_Form): import traceback det_msg = traceback.format_exc() error_dialog(self, _('Invalid debug directory'), - _('Failed to create debug directory')+': '+ unicode(self.opt_debug_pipeline.text()), + _('Failed to create debug directory')+': '+ unicode_type(self.opt_debug_pipeline.text()), det_msg=det_msg, show=True) return False return True diff --git a/src/calibre/gui2/convert/font_key.py b/src/calibre/gui2/convert/font_key.py index c061310dfb..e7a237d4df 100644 --- a/src/calibre/gui2/convert/font_key.py +++ b/src/calibre/gui2/convert/font_key.py @@ -10,6 +10,7 @@ from PyQt5.Qt import QDialog from calibre.gui2.convert.font_key_ui import Ui_Dialog from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type class FontKeyChooser(QDialog, Ui_Dialog): @@ -66,7 +67,7 @@ class FontKeyChooser(QDialog, Ui_Dialog): @property def fsizes(self): - key = unicode(self.font_size_key.text()).strip() + key = unicode_type(self.font_size_key.text()).strip() return [float(x.strip()) for x in key.split(',' if ',' in key else ' ') if x.strip()] @property diff --git a/src/calibre/gui2/convert/heuristics.py b/src/calibre/gui2/convert/heuristics.py index 9cab0fb452..0ff2da151d 100644 --- a/src/calibre/gui2/convert/heuristics.py +++ b/src/calibre/gui2/convert/heuristics.py @@ -11,6 +11,7 @@ from calibre.gui2.convert.heuristics_ui import Ui_Form from calibre.gui2.convert import Widget from calibre.utils.localization import localize_user_manual_link from calibre.ebooks.conversion.config import OPTIONS +from polyglot.builtins import unicode_type class HeuristicsWidget(Widget, Ui_Form): @@ -73,7 +74,7 @@ class HeuristicsWidget(Widget, Ui_Form): return True def load_histories(self): - val = unicode(self.opt_replace_scene_breaks.currentText()) + val = unicode_type(self.opt_replace_scene_breaks.currentText()) self.opt_replace_scene_breaks.clear() self.opt_replace_scene_breaks.lineEdit().setText('') @@ -90,7 +91,7 @@ class HeuristicsWidget(Widget, Ui_Form): def save_histories(self): rssb_history = [] - history_pats = [unicode(self.opt_replace_scene_breaks.lineEdit().text())] + [unicode(self.opt_replace_scene_breaks.itemText(i)) + history_pats = [unicode_type(self.opt_replace_scene_breaks.lineEdit().text())] + [unicode_type(self.opt_replace_scene_breaks.itemText(i)) for i in xrange(self.opt_replace_scene_breaks.count())] for p in history_pats[:10]: # Ensure we don't have duplicate items. diff --git a/src/calibre/gui2/convert/look_and_feel.py b/src/calibre/gui2/convert/look_and_feel.py index 6aed2d8c5a..3ab986b828 100644 --- a/src/calibre/gui2/convert/look_and_feel.py +++ b/src/calibre/gui2/convert/look_and_feel.py @@ -13,6 +13,7 @@ from PyQt5.Qt import Qt from calibre.gui2.convert.look_and_feel_ui import Ui_Form from calibre.gui2.convert import Widget from calibre.ebooks.conversion.config import OPTIONS +from polyglot.builtins import unicode_type class LookAndFeelWidget(Widget, Ui_Form): @@ -54,7 +55,7 @@ class LookAndFeelWidget(Widget, Ui_Form): def get_value_handler(self, g): if g is self.opt_change_justification: - ans = unicode(g.itemData(g.currentIndex()) or '') + ans = unicode_type(g.itemData(g.currentIndex()) or '') return ans if g is self.opt_filter_css: ans = set() @@ -63,10 +64,10 @@ class LookAndFeelWidget(Widget, Ui_Form): if w.isChecked(): ans = ans.union(item) ans = ans.union({x.strip().lower() for x in - unicode(self.filter_css_others.text()).split(',')}) + unicode_type(self.filter_css_others.text()).split(',')}) return ','.join(ans) if ans else None if g is self.opt_font_size_mapping: - val = unicode(g.text()).strip() + val = unicode_type(g.text()).strip() val = [x.strip() for x in val.split(',' if ',' in val else ' ') if x.strip()] return ', '.join(val) or None if g is self.opt_transform_css_rules: @@ -76,7 +77,7 @@ class LookAndFeelWidget(Widget, Ui_Form): def set_value_handler(self, g, val): if g is self.opt_change_justification: for i in range(g.count()): - c = unicode(g.itemData(i) or '') + c = unicode_type(g.itemData(i) or '') if val == c: g.setCurrentIndex(i) break @@ -113,7 +114,7 @@ class LookAndFeelWidget(Widget, Ui_Form): def font_key_wizard(self): from calibre.gui2.convert.font_key import FontKeyChooser d = FontKeyChooser(self, self.opt_base_font_size.value(), - unicode(self.opt_font_size_mapping.text()).strip()) + unicode_type(self.opt_font_size_mapping.text()).strip()) if d.exec_() == d.Accepted: self.opt_font_size_mapping.setText(', '.join(['%.1f'%x for x in d.fsizes])) diff --git a/src/calibre/gui2/convert/metadata.py b/src/calibre/gui2/convert/metadata.py index 106ee86aff..2ca3d72a01 100644 --- a/src/calibre/gui2/convert/metadata.py +++ b/src/calibre/gui2/convert/metadata.py @@ -21,6 +21,7 @@ from calibre.utils.icu import sort_key from calibre.library.comments import comments_to_html from calibre.utils.config import tweaks from calibre.ebooks.conversion.config import OPTIONS +from polyglot.builtins import unicode_type def create_opf_file(db, book_id, opf_file=None): @@ -73,7 +74,7 @@ class MetadataWidget(Widget, Ui_Form): self.cover_data = data def deduce_author_sort(self, *args): - au = unicode(self.author.currentText()) + au = unicode_type(self.author.currentText()) au = re.sub(r'\s+et al\.$', '', au) authors = string_to_authors(au) self.author_sort.setText(self.db.author_sort_from_authors(authors)) @@ -155,30 +156,30 @@ class MetadataWidget(Widget, Ui_Form): self.publisher.update_items_cache([x[1] for x in all_publishers]) def get_title_and_authors(self): - title = unicode(self.title.text()).strip() + title = unicode_type(self.title.text()).strip() if not title: title = _('Unknown') - authors = unicode(self.author.text()).strip() + authors = unicode_type(self.author.text()).strip() authors = string_to_authors(authors) if authors else [_('Unknown')] return title, authors def get_metadata(self): title, authors = self.get_title_and_authors() mi = MetaInformation(title, authors) - publisher = unicode(self.publisher.text()).strip() + publisher = unicode_type(self.publisher.text()).strip() if publisher: mi.publisher = publisher - author_sort = unicode(self.author_sort.text()).strip() + author_sort = unicode_type(self.author_sort.text()).strip() if author_sort: mi.author_sort = author_sort comments = self.comment.html if comments: mi.comments = comments mi.series_index = float(self.series_index.value()) - series = unicode(self.series.currentText()).strip() + series = unicode_type(self.series.currentText()).strip() if series: mi.series = series - tags = [t.strip() for t in unicode(self.tags.text()).strip().split(',')] + tags = [t.strip() for t in unicode_type(self.tags.text()).strip().split(',')] if tags: mi.tags = tags @@ -186,7 +187,7 @@ class MetadataWidget(Widget, Ui_Form): def select_cover(self): files = choose_images(self, 'change cover dialog', - _('Choose cover for ') + unicode(self.title.text())) + _('Choose cover for ') + unicode_type(self.title.text())) if not files: return _file = files[0] diff --git a/src/calibre/gui2/convert/page_setup.py b/src/calibre/gui2/convert/page_setup.py index 4a1dd1df08..093cda0496 100644 --- a/src/calibre/gui2/convert/page_setup.py +++ b/src/calibre/gui2/convert/page_setup.py @@ -12,6 +12,7 @@ from calibre.gui2.convert.page_setup_ui import Ui_Form from calibre.gui2.convert import Widget from calibre.customize.ui import input_profiles, output_profiles from calibre.ebooks.conversion.config import OPTIONS +from polyglot.builtins import unicode_type class ProfileModel(QAbstractListModel): @@ -60,13 +61,13 @@ class PageSetupWidget(Widget, Ui_Form): x.setMouseTracking(True) x.entered[(QModelIndex)].connect(self.show_desc) self.initialize_options(get_option, get_help, db, book_id) - it = unicode(self.opt_input_profile.toolTip()) + it = unicode_type(self.opt_input_profile.toolTip()) self.opt_input_profile.setToolTip('

'+it.replace('t.','t.\n
')) - it = unicode(self.opt_output_profile.toolTip()) + it = unicode_type(self.opt_output_profile.toolTip()) self.opt_output_profile.setToolTip('

'+it.replace('t.','ce.\n
')) def show_desc(self, index): - desc = unicode(index.model().data(index, Qt.StatusTipRole) or '') + desc = unicode_type(index.model().data(index, Qt.StatusTipRole) or '') self.profile_description.setText(desc) def connect_gui_obj_handler(self, g, slot): diff --git a/src/calibre/gui2/convert/regex_builder.py b/src/calibre/gui2/convert/regex_builder.py index 0ef3a2fa2a..ca60871df1 100644 --- a/src/calibre/gui2/convert/regex_builder.py +++ b/src/calibre/gui2/convert/regex_builder.py @@ -17,6 +17,7 @@ from calibre.constants import iswindows from calibre.utils.ipc.simple_worker import fork_job, WorkerError from calibre.ebooks.conversion.search_replace import compile_regular_expression from calibre.ptempfile import TemporaryFile +from polyglot.builtins import unicode_type class RegexBuilder(QDialog, Ui_RegexBuilder): @@ -58,7 +59,7 @@ class RegexBuilder(QDialog, Ui_RegexBuilder): gprefs['regex_builder_geometry'] = geom def regex_valid(self): - regex = unicode(self.regex.text()) + regex = unicode_type(self.regex.text()) if regex: try: compile_regular_expression(regex) @@ -81,8 +82,8 @@ class RegexBuilder(QDialog, Ui_RegexBuilder): selections = [] self.match_locs = [] if self.regex_valid(): - text = unicode(self.preview.toPlainText()) - regex = unicode(self.regex.text()) + text = unicode_type(self.preview.toPlainText()) + regex = unicode_type(self.regex.text()) cursor = QTextCursor(self.preview.document()) extsel = QTextEdit.ExtraSelection() extsel.cursor = cursor @@ -196,12 +197,12 @@ class RegexBuilder(QDialog, Ui_RegexBuilder): self.open_book(files[0]) def doc(self): - return unicode(self.preview.toPlainText()) + return unicode_type(self.preview.toPlainText()) class RegexEdit(QWidget, Ui_Edit): - doc_update = pyqtSignal(unicode) + doc_update = pyqtSignal(unicode_type) def __init__(self, parent=None): QWidget.__init__(self, parent) @@ -233,7 +234,7 @@ class RegexEdit(QWidget, Ui_Edit): def setObjectName(self, *args): QWidget.setObjectName(self, *args) if hasattr(self, 'edit'): - self.edit.initialize('regex_edit_'+unicode(self.objectName())) + self.edit.initialize('regex_edit_'+unicode_type(self.objectName())) def set_msg(self, msg): self.msg.setText(msg) @@ -255,7 +256,7 @@ class RegexEdit(QWidget, Ui_Edit): @property def text(self): - return unicode(self.edit.text()) + return unicode_type(self.edit.text()) @property def regex(self): diff --git a/src/calibre/gui2/convert/search_and_replace.py b/src/calibre/gui2/convert/search_and_replace.py index 5ef34d1224..71e9379317 100644 --- a/src/calibre/gui2/convert/search_and_replace.py +++ b/src/calibre/gui2/convert/search_and_replace.py @@ -16,6 +16,7 @@ from calibre import as_unicode from calibre.utils.localization import localize_user_manual_link from calibre.ebooks.conversion.search_replace import compile_regular_expression from calibre.ebooks.conversion.config import OPTIONS +from polyglot.builtins import unicode_type class SearchAndReplaceWidget(Widget, Ui_Form): @@ -189,7 +190,7 @@ class SearchAndReplaceWidget(Widget, Ui_Form): edit_search = self.sr_search.regex if edit_search: - edit_replace = unicode(self.sr_replace.text()) + edit_replace = unicode_type(self.sr_replace.text()) found = False for search, replace in definitions: if search == edit_search and replace == edit_replace: @@ -230,7 +231,7 @@ class SearchAndReplaceWidget(Widget, Ui_Form): for row in xrange(0, self.search_replace.rowCount()): colItems = [] for col in xrange(0, self.search_replace.columnCount()): - colItems.append(unicode(self.search_replace.item(row, col).text())) + colItems.append(unicode_type(self.search_replace.item(row, col).text())) ans.append(colItems) return ans diff --git a/src/calibre/gui2/convert/single.py b/src/calibre/gui2/convert/single.py index e00a18df34..e8f1ca11b3 100644 --- a/src/calibre/gui2/convert/single.py +++ b/src/calibre/gui2/convert/single.py @@ -28,6 +28,7 @@ from calibre.ebooks.conversion.plumber import create_dummy_plumber from calibre.ebooks.conversion.config import delete_specifics from calibre.customize.conversion import OptionRecommendation from calibre.utils.config import prefs +from polyglot.builtins import unicode_type class GroupModel(QAbstractListModel): @@ -107,11 +108,11 @@ class Config(QDialog, Ui_Dialog): @property def input_format(self): - return unicode(self.input_formats.currentText()).lower() + return unicode_type(self.input_formats.currentText()).lower() @property def output_format(self): - return unicode(self.output_formats.currentText()).lower() + return unicode_type(self.output_formats.currentText()).lower() @property def manually_fine_tune_toc(self): @@ -131,7 +132,7 @@ class Config(QDialog, Ui_Dialog): self.plumber.get_option_help, self.db, self.book_id) self.mw = widget_factory(MetadataWidget) - self.setWindowTitle(_('Convert')+ ' ' + unicode(self.mw.title.text())) + self.setWindowTitle(_('Convert')+ ' ' + unicode_type(self.mw.title.text())) lf = widget_factory(LookAndFeelWidget) hw = widget_factory(HeuristicsWidget) sr = widget_factory(SearchAndReplaceWidget) @@ -186,9 +187,9 @@ class Config(QDialog, Ui_Dialog): preferred_output_format in output_formats else \ sort_formats_by_preference(output_formats, [prefs['output_format']])[0] - self.input_formats.addItems(list(map(unicode, [x.upper() for x in + self.input_formats.addItems(list(map(unicode_type, [x.upper() for x in input_formats]))) - self.output_formats.addItems(list(map(unicode, [x.upper() for x in + self.output_formats.addItems(list(map(unicode_type, [x.upper() for x in output_formats]))) self.input_formats.setCurrentIndex(input_formats.index(input_format)) self.output_formats.setCurrentIndex(output_formats.index(preferred_output_format)) diff --git a/src/calibre/gui2/convert/txt_input.py b/src/calibre/gui2/convert/txt_input.py index c7b79b8191..fff09f18fe 100644 --- a/src/calibre/gui2/convert/txt_input.py +++ b/src/calibre/gui2/convert/txt_input.py @@ -10,6 +10,7 @@ from calibre.gui2.convert.txt_input_ui import Ui_Form from calibre.gui2.convert import Widget from calibre.ebooks.conversion.plugins.txt_input import MD_EXTENSIONS from calibre.ebooks.conversion.config import OPTIONS +from polyglot.builtins import unicode_type class PluginWidget(Widget, Ui_Form): @@ -48,7 +49,7 @@ class PluginWidget(Widget, Ui_Form): def get_value_handler(self, g): if g is not self.opt_markdown_extensions: return Widget.get_value_handler(self, g) - return ', '.join(unicode(i.data(Qt.UserRole) or '') for i in self.md_map.itervalues() if i.checkState()) + return ', '.join(unicode_type(i.data(Qt.UserRole) or '') for i in self.md_map.itervalues() if i.checkState()) def connect_gui_obj_handler(self, g, f): if g is not self.opt_markdown_extensions: diff --git a/src/calibre/gui2/convert/xpath_wizard.py b/src/calibre/gui2/convert/xpath_wizard.py index 6014f80cf8..97f80e1c81 100644 --- a/src/calibre/gui2/convert/xpath_wizard.py +++ b/src/calibre/gui2/convert/xpath_wizard.py @@ -12,6 +12,7 @@ from PyQt5.Qt import QDialog, QWidget, Qt, QDialogButtonBox, QVBoxLayout from calibre.gui2.convert.xpath_wizard_ui import Ui_Form from calibre.gui2.convert.xexp_edit_ui import Ui_Form as Ui_Edit from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type class WizardWidget(QWidget, Ui_Form): @@ -27,10 +28,10 @@ class WizardWidget(QWidget, Ui_Form): @property def xpath(self): - tag = unicode(self.tag.currentText()).strip() + tag = unicode_type(self.tag.currentText()).strip() if tag != '*': tag = 'h:'+tag - attr, val = map(unicode, (self.attribute.text(), self.value.text())) + attr, val = map(unicode_type, (self.attribute.text(), self.value.text())) attr, val = attr.strip(), val.strip() q = '' if attr: @@ -81,14 +82,14 @@ class XPathEdit(QWidget, Ui_Edit): def setObjectName(self, *args): QWidget.setObjectName(self, *args) if hasattr(self, 'edit'): - self.edit.initialize('xpath_edit_'+unicode(self.objectName())) + self.edit.initialize('xpath_edit_'+unicode_type(self.objectName())) def set_msg(self, msg): self.msg.setText(msg) @property def text(self): - return unicode(self.edit.text()) + return unicode_type(self.edit.text()) @property def xpath(self): diff --git a/src/calibre/gui2/css_transform_rules.py b/src/calibre/gui2/css_transform_rules.py index e352bce09a..361552e1e5 100644 --- a/src/calibre/gui2/css_transform_rules.py +++ b/src/calibre/gui2/css_transform_rules.py @@ -19,6 +19,7 @@ from calibre.gui2.tag_mapper import ( from calibre.gui2.widgets2 import Dialog from calibre.utils.config import JSONConfig from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type class RuleEdit(QWidget): # {{{ @@ -133,14 +134,14 @@ class RuleEdit(QWidget): # {{{ def rule(self, rule): def sc(name): c = getattr(self, name) - idx = c.findData(unicode(rule.get(name, ''))) + idx = c.findData(unicode_type(rule.get(name, ''))) if idx < 0: idx = 0 c.setCurrentIndex(idx) sc('action'), sc('match_type') - self.property.setText(unicode(rule.get('property', '')).strip()) - self.query.setText(unicode(rule.get('query', '')).strip()) - self.action_data.setText(unicode(rule.get('action_data', '')).strip()) + self.property.setText(unicode_type(rule.get('property', '')).strip()) + self.query.setText(unicode_type(rule.get('query', '')).strip()) + self.action_data.setText(unicode_type(rule.get('action_data', '')).strip()) self.update_state() def validate(self): diff --git a/src/calibre/gui2/custom_column_widgets.py b/src/calibre/gui2/custom_column_widgets.py index e6bbdbb666..1c73867eae 100644 --- a/src/calibre/gui2/custom_column_widgets.py +++ b/src/calibre/gui2/custom_column_widgets.py @@ -23,6 +23,7 @@ from calibre.utils.icu import sort_key from calibre.library.comments import comments_to_html from calibre.gui2.library.delegates import ClearingDoubleSpinBox, ClearingSpinBox from calibre.gui2.widgets2 import RatingEditor +from polyglot.builtins import unicode_type def safe_disconnect(signal): @@ -371,7 +372,7 @@ class Comments(Base): self._tb.wyswyg_dirtied() def getter(self): - val = unicode(self._tb.html).strip() + val = unicode_type(self._tb.html).strip() if not val: val = None return val @@ -497,12 +498,12 @@ class Text(Base): def getter(self): if self.col_metadata['is_multiple']: - val = unicode(self.widgets[1].text()).strip() + val = unicode_type(self.widgets[1].text()).strip() ans = [x.strip() for x in val.split(self.sep['ui_to_list']) if x.strip()] if not ans: ans = None return ans - val = unicode(self.widgets[1].currentText()).strip() + val = unicode_type(self.widgets[1].currentText()).strip() if not val: val = None return val @@ -571,7 +572,7 @@ class Series(Base): self.initial_val, self.initial_index = self.current_val def getter(self): - n = unicode(self.name_widget.currentText()).strip() + n = unicode_type(self.name_widget.currentText()).strip() i = self.idx_widget.value() return n, i @@ -643,7 +644,7 @@ class Enumeration(Base): self.widgets[1].setCurrentIndex(self.widgets[1].findText(val)) def getter(self): - return unicode(self.widgets[1].currentText()) + return unicode_type(self.widgets[1].currentText()) def normalize_db_val(self, val): if val is None: @@ -1164,7 +1165,7 @@ class BulkSeries(BulkBase): self.a_c_checkbox.setChecked(False) def getter(self): - n = unicode(self.main_widget.currentText()).strip() + n = unicode_type(self.main_widget.currentText()).strip() autonumber = self.idx_widget.checkState() force = self.force_number.checkState() start = self.series_start_number.value() @@ -1234,7 +1235,7 @@ class BulkEnumeration(BulkBase, Enumeration): self.main_widget.blockSignals(False) def getter(self): - return unicode(self.main_widget.currentText()) + return unicode_type(self.main_widget.currentText()) def setter(self, val): if val is None: @@ -1355,10 +1356,10 @@ class BulkText(BulkBase): if self.col_metadata['is_multiple']: if not self.col_metadata['display'].get('is_names', False): return self.removing_widget.checkbox.isChecked(), \ - unicode(self.adding_widget.text()), \ - unicode(self.removing_widget.tags_box.text()) - return unicode(self.adding_widget.text()) - val = unicode(self.main_widget.currentText()).strip() + unicode_type(self.adding_widget.text()), \ + unicode_type(self.removing_widget.tags_box.text()) + return unicode_type(self.adding_widget.text()) + val = unicode_type(self.main_widget.currentText()).strip() if not val: val = None return val diff --git a/src/calibre/gui2/dbus_export/gtk.py b/src/calibre/gui2/dbus_export/gtk.py index c1bf4bb758..2bb1af75b6 100644 --- a/src/calibre/gui2/dbus_export/gtk.py +++ b/src/calibre/gui2/dbus_export/gtk.py @@ -15,6 +15,8 @@ from pprint import pformat from gi.repository import Gtk, Gdk, GdkX11 # noqa +from polyglot.builtins import unicode_type + UI_INFO = """ @@ -200,7 +202,7 @@ class MenuExampleWindow(Gtk.ApplicationWindow): def convert(v): if isinstance(v, basestring): - return unicode(v) + return unicode_type(v) if isinstance(v, dbus.Struct): return tuple(convert(val) for val in v) if isinstance(v, list): @@ -275,7 +277,7 @@ class MyApplication(Gtk.Application): print ('Subscription group:', item[0]) print ('Menu number:', item[1]) for menu_item in item[2]: - menu_item = {unicode(k):convert(v) for k, v in menu_item.iteritems()} + menu_item = {unicode_type(k):convert(v) for k, v in menu_item.iteritems()} if ':submenu' in menu_item: groups.add(menu_item[':submenu'][0]) if ':section' in menu_item: diff --git a/src/calibre/gui2/dbus_export/menu2.py b/src/calibre/gui2/dbus_export/menu2.py index a3df7ab9dc..08ee421557 100644 --- a/src/calibre/gui2/dbus_export/menu2.py +++ b/src/calibre/gui2/dbus_export/menu2.py @@ -18,11 +18,12 @@ from PyQt5.Qt import QObject, pyqtSignal, QTimer, Qt from calibre.utils.dbus_service import Object, method as dbus_method, signal as dbus_signal from calibre.gui2.dbus_export.utils import set_X_window_properties +from polyglot.builtins import unicode_type def add_window_properties_for_menu(widget, object_path, bus): - op = unicode(object_path) - set_X_window_properties(widget.effectiveWinId(), _UNITY_OBJECT_PATH=op, _GTK_UNIQUE_BUS_NAME=unicode(bus.get_unique_name()), _GTK_MENUBAR_OBJECT_PATH=op) + op = unicode_type(object_path) + set_X_window_properties(widget.effectiveWinId(), _UNITY_OBJECT_PATH=op, _GTK_UNIQUE_BUS_NAME=unicode_type(bus.get_unique_name()), _GTK_MENUBAR_OBJECT_PATH=op) class DBusMenu(QObject): @@ -61,5 +62,3 @@ class DBusMenuAPI(Object): self.revision = 0 dbus_method, dbus_signal - - diff --git a/src/calibre/gui2/dbus_export/utils.py b/src/calibre/gui2/dbus_export/utils.py index 625b870eeb..3a47eda50f 100644 --- a/src/calibre/gui2/dbus_export/utils.py +++ b/src/calibre/gui2/dbus_export/utils.py @@ -12,6 +12,8 @@ import dbus from PyQt5.Qt import QSize, QImage, Qt, QKeySequence, QBuffer, QByteArray +from polyglot.builtins import unicode_type + def log(*args, **kw): kw['file'] = sys.stderr @@ -145,7 +147,7 @@ def set_X_window_properties(win_id, **properties): for name, val in properties.iteritems(): atom = atoms[name].reply().atom type_atom = xcb.xproto.Atom.STRING - if isinstance(val, unicode): + if isinstance(val, unicode_type): if utf8_string_atom is None: utf8_string_atom = conn.core.InternAtom(True, len(b'UTF8_STRING'), b'UTF8_STRING').reply().atom type_atom = utf8_string_atom diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index e3417bb778..f4b54a08ba 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -34,6 +34,7 @@ from calibre.utils.config import tweaks, device_prefs from calibre.utils.img import scale_image from calibre.library.save_to_disk import find_plugboard from calibre.ptempfile import PersistentTemporaryFile, force_unicode as filename_to_unicode +from polyglot.builtins import unicode_type # }}} @@ -105,7 +106,7 @@ class DeviceJob(BaseJob): # {{{ call_job_done = True self._aborted = True self.failed = True - self._details = unicode(err) + self._details = unicode_type(err) self.exception = err if call_job_done: self.job_done() @@ -561,7 +562,7 @@ class DeviceManager(Thread): # {{{ self.connected_device.set_plugboards(plugboards, find_plugboard) if metadata and files and len(metadata) == len(files): for f, mi in zip(files, metadata): - if isinstance(f, unicode): + if isinstance(f, unicode_type): ext = f.rpartition('.')[-1].lower() cpb = find_plugboard( device_name_for_plugboards(self.connected_device), @@ -928,7 +929,7 @@ class DeviceMixin(object): # {{{ d.show() def auto_convert_question(self, msg, autos): - autos = u'\n'.join(map(unicode, map(force_unicode, autos))) + autos = u'\n'.join(map(unicode_type, map(force_unicode, autos))) return self.ask_a_yes_no_question( _('No suitable formats'), msg, ans_when_user_unavailable=True, @@ -1026,7 +1027,7 @@ class DeviceMixin(object): # {{{ try: if 'Could not read 32 bytes on the control bus.' in \ - unicode(job.details): + unicode_type(job.details): error_dialog(self, _('Error talking to device'), _('There was a temporary error talking to the ' 'device. Please unplug and reconnect the device ' @@ -1347,7 +1348,7 @@ class DeviceMixin(object): # {{{ names = [] for mi in metadata: prefix = ascii_filename(mi.title) - if not isinstance(prefix, unicode): + if not isinstance(prefix, unicode_type): prefix = prefix.decode(preferred_encoding, 'replace') prefix = ascii_filename(prefix) names.append('%s_%d%s'%(prefix, id, @@ -1428,7 +1429,7 @@ class DeviceMixin(object): # {{{ names = [] for mi in metadata: prefix = ascii_filename(mi.title) - if not isinstance(prefix, unicode): + if not isinstance(prefix, unicode_type): prefix = prefix.decode(preferred_encoding, 'replace') prefix = ascii_filename(prefix) names.append('%s_%d%s'%(prefix, id, @@ -1507,7 +1508,7 @@ class DeviceMixin(object): # {{{ if not a: a = _('Unknown') prefix = ascii_filename(t+' - '+a) - if not isinstance(prefix, unicode): + if not isinstance(prefix, unicode_type): prefix = prefix.decode(preferred_encoding, 'replace') prefix = ascii_filename(prefix) names.append('%s_%d%s'%(prefix, id, os.path.splitext(f)[1])) @@ -1639,7 +1640,7 @@ class DeviceMixin(object): # {{{ d.exec_() elif isinstance(job.exception, WrongDestinationError): error_dialog(self, _('Incorrect destination'), - unicode(job.exception), show=True) + unicode_type(job.exception), show=True) else: self.device_job_exception(job) return diff --git a/src/calibre/gui2/device_drivers/configwidget.py b/src/calibre/gui2/device_drivers/configwidget.py index 6db50ccfb3..38c2b55e1e 100644 --- a/src/calibre/gui2/device_drivers/configwidget.py +++ b/src/calibre/gui2/device_drivers/configwidget.py @@ -13,6 +13,7 @@ from calibre.gui2 import error_dialog, question_dialog from calibre.gui2.device_drivers.configwidget_ui import Ui_ConfigWidget from calibre.utils.formatter import validation_formatter from calibre.ebooks import BOOK_EXTENSIONS +from polyglot.builtins import unicode_type class ConfigWidget(QWidget, Ui_ConfigWidget): @@ -135,7 +136,7 @@ class ConfigWidget(QWidget, Ui_ConfigWidget): self.columns.setCurrentRow(idx+1) def format_map(self): - formats = [unicode(self.columns.item(i).data(Qt.UserRole) or '') for i in range(self.columns.count()) if self.columns.item(i).checkState()==Qt.Checked] + formats = [unicode_type(self.columns.item(i).data(Qt.UserRole) or '') for i in range(self.columns.count()) if self.columns.item(i).checkState()==Qt.Checked] return formats def use_subdirs(self): @@ -160,15 +161,13 @@ class ConfigWidget(QWidget, Ui_ConfigWidget): (', '.join(fmts)), self.device_name)): return False - tmpl = unicode(self.opt_save_template.text()) + tmpl = unicode_type(self.opt_save_template.text()) try: validation_formatter.validate(tmpl) return True except Exception as err: error_dialog(self, _('Invalid template'), '

'+_('The template %s is invalid:')%tmpl + - '
'+unicode(err), show=True) + '
'+unicode_type(err), show=True) return False - - diff --git a/src/calibre/gui2/device_drivers/mtp_config.py b/src/calibre/gui2/device_drivers/mtp_config.py index ef0522b252..6aa1bf38e2 100644 --- a/src/calibre/gui2/device_drivers/mtp_config.py +++ b/src/calibre/gui2/device_drivers/mtp_config.py @@ -20,6 +20,7 @@ from calibre.gui2 import error_dialog from calibre.gui2.dialogs.template_dialog import TemplateDialog from calibre.utils.date import parse_date from calibre.gui2.device_drivers.mtp_folder_browser import Browser, IgnoredFolders +from polyglot.builtins import unicode_type class FormatsConfig(QWidget): # {{{ @@ -50,7 +51,7 @@ class FormatsConfig(QWidget): # {{{ @property def format_map(self): - return [unicode(self.f.item(i).data(Qt.UserRole) or '') for i in + return [unicode_type(self.f.item(i).data(Qt.UserRole) or '') for i in xrange(self.f.count()) if self.f.item(i).checkState()==Qt.Checked] def validate(self): @@ -97,7 +98,7 @@ class TemplateConfig(QWidget): # {{{ @property def template(self): - return unicode(self.t.text()).strip() + return unicode_type(self.t.text()).strip() def edit_template(self): t = TemplateDialog(self, self.template) @@ -114,7 +115,7 @@ class TemplateConfig(QWidget): # {{{ except Exception as err: error_dialog(self, _('Invalid template'), '

'+_('The template %s is invalid:')%tmpl + - '
'+unicode(err), show=True) + '
'+unicode_type(err), show=True) return False # }}} @@ -155,7 +156,7 @@ class SendToConfig(QWidget): # {{{ @property def value(self): - ans = [x.strip() for x in unicode(self.t.text()).strip().split(',')] + ans = [x.strip() for x in unicode_type(self.t.text()).strip().split(',')] return [x for x in ans if x] # }}} @@ -187,13 +188,13 @@ class IgnoredDevices(QWidget): # {{{ @property def blacklist(self): - return [unicode(self.f.item(i).data(Qt.UserRole) or '') for i in + return [unicode_type(self.f.item(i).data(Qt.UserRole) or '') for i in xrange(self.f.count()) if self.f.item(i).checkState()==Qt.Checked] def ignore_device(self, snum): for i in xrange(self.f.count()): i = self.f.item(i) - c = unicode(i.data(Qt.UserRole) or '') + c = unicode_type(i.data(Qt.UserRole) or '') if c == snum: i.setCheckState(Qt.Checked) break @@ -264,10 +265,10 @@ class Rule(QWidget): @property def rule(self): - folder = unicode(self.folder.text()).strip() + folder = unicode_type(self.folder.text()).strip() if folder: return ( - unicode(self.fmt.itemData(self.fmt.currentIndex()) or ''), + unicode_type(self.fmt.itemData(self.fmt.currentIndex()) or ''), folder ) return None diff --git a/src/calibre/gui2/device_drivers/mtp_folder_browser.py b/src/calibre/gui2/device_drivers/mtp_folder_browser.py index b054977e82..eeb42e5111 100644 --- a/src/calibre/gui2/device_drivers/mtp_folder_browser.py +++ b/src/calibre/gui2/device_drivers/mtp_folder_browser.py @@ -13,6 +13,7 @@ from PyQt5.Qt import (QTabWidget, QTreeWidget, QTreeWidgetItem, Qt, QDialog, QDialogButtonBox, QVBoxLayout, QSize, pyqtSignal, QIcon, QLabel) from calibre.gui2 import file_icon_provider +from polyglot.builtins import unicode_type def browser_item(f, parent): @@ -200,11 +201,11 @@ class IgnoredFolders(QDialog): for node in self.iterchildren(w.invisibleRootItem()): if node.checkState(0) == Qt.Checked: continue - path = unicode(node.data(0, Qt.UserRole) or '') + path = unicode_type(node.data(0, Qt.UserRole) or '') parent = path.rpartition('/')[0] if '/' not in path or icu_lower(parent) not in folders: folders.add(icu_lower(path)) - ans[unicode(w.storage.storage_id)] = list(folders) + ans[unicode_type(w.storage.storage_id)] = list(folders) return ans diff --git a/src/calibre/gui2/device_drivers/tabbed_device_config.py b/src/calibre/gui2/device_drivers/tabbed_device_config.py index ac6fc65ceb..be741441f2 100644 --- a/src/calibre/gui2/device_drivers/tabbed_device_config.py +++ b/src/calibre/gui2/device_drivers/tabbed_device_config.py @@ -17,6 +17,7 @@ from PyQt5.Qt import ( from calibre.ebooks import BOOK_EXTENSIONS from calibre.gui2.device_drivers.mtp_config import (FormatsConfig, TemplateConfig) from calibre.devices.usbms.driver import debug_print +from polyglot.builtins import unicode_type def wrap_msg(msg): @@ -340,11 +341,11 @@ class ExtraCustomization(DeviceConfigTab): # {{{ if hasattr(self.opt_extra_customization[i], 'isChecked'): ec.append(self.opt_extra_customization[i].isChecked()) elif hasattr(self.opt_extra_customization[i], 'currentText'): - ec.append(unicode(self.opt_extra_customization[i].currentText()).strip()) + ec.append(unicode_type(self.opt_extra_customization[i].currentText()).strip()) else: - ec.append(unicode(self.opt_extra_customization[i].text()).strip()) + ec.append(unicode_type(self.opt_extra_customization[i].text()).strip()) else: - ec = unicode(self.opt_extra_customization.text()).strip() + ec = unicode_type(self.opt_extra_customization.text()).strip() if not ec: ec = None diff --git a/src/calibre/gui2/dialogs/add_empty_book.py b/src/calibre/gui2/dialogs/add_empty_book.py index dbf66191e1..66fa354f0f 100644 --- a/src/calibre/gui2/dialogs/add_empty_book.py +++ b/src/calibre/gui2/dialogs/add_empty_book.py @@ -11,6 +11,7 @@ from calibre.ebooks.metadata import string_to_authors from calibre.gui2.complete2 import EditWithComplete from calibre.utils.config import tweaks from calibre.gui2 import gprefs +from polyglot.builtins import unicode_type class AddEmptyBookDialog(QDialog): @@ -161,11 +162,11 @@ class AddEmptyBookDialog(QDialog): @property def selected_authors(self): - return string_to_authors(unicode(self.authors_combo.text())) + return string_to_authors(unicode_type(self.authors_combo.text())) @property def selected_series(self): - return unicode(self.series_combo.text()) + return unicode_type(self.series_combo.text()) @property def selected_title(self): diff --git a/src/calibre/gui2/dialogs/add_from_isbn.py b/src/calibre/gui2/dialogs/add_from_isbn.py index d65ca7754c..f8712dc49c 100644 --- a/src/calibre/gui2/dialogs/add_from_isbn.py +++ b/src/calibre/gui2/dialogs/add_from_isbn.py @@ -15,6 +15,7 @@ from PyQt5.Qt import ( from calibre.ebooks.metadata import check_isbn from calibre.constants import iswindows from calibre.gui2 import gprefs, question_dialog, error_dialog +from polyglot.builtins import unicode_type class AddFromISBN(QDialog): @@ -25,7 +26,7 @@ class AddFromISBN(QDialog): path = r'C:\Users\kovid\e-books\some_book.epub' if iswindows else \ '/Users/kovid/e-books/some_book.epub' - self.label.setText(unicode(self.label.text())%path) + self.label.setText(unicode_type(self.label.text())%path) self.isbns = [] self.books = [] @@ -70,19 +71,19 @@ class AddFromISBN(QDialog): def paste(self, *args): app = QApplication.instance() c = app.clipboard() - txt = unicode(c.text()).strip() + txt = unicode_type(c.text()).strip() if txt: - old = unicode(self.isbn_box.toPlainText()).strip() + old = unicode_type(self.isbn_box.toPlainText()).strip() new = old + '\n' + txt self.isbn_box.setPlainText(new) def accept(self, *args): - tags = unicode(self.add_tags.text()).strip().split(',') + tags = unicode_type(self.add_tags.text()).strip().split(',') tags = list(filter(None, [x.strip() for x in tags])) gprefs['add from ISBN tags'] = tags self.set_tags = tags bad = set() - for line in unicode(self.isbn_box.toPlainText()).strip().splitlines(): + for line in unicode_type(self.isbn_box.toPlainText()).strip().splitlines(): line = line.strip() if not line: continue @@ -117,4 +118,3 @@ class AddFromISBN(QDialog): _('All the ISBNs you entered were invalid. No books' ' can be added.'), show=True) QDialog.accept(self, *args) - diff --git a/src/calibre/gui2/dialogs/authors_edit.py b/src/calibre/gui2/dialogs/authors_edit.py index 34ce34722c..e020d071af 100644 --- a/src/calibre/gui2/dialogs/authors_edit.py +++ b/src/calibre/gui2/dialogs/authors_edit.py @@ -16,6 +16,7 @@ from calibre.utils.config_base import tweaks from calibre.gui2 import gprefs from calibre.gui2.complete2 import EditWithComplete from calibre.ebooks.metadata import string_to_authors +from polyglot.builtins import unicode_type class ItemDelegate(QStyledItemDelegate): @@ -30,12 +31,12 @@ class ItemDelegate(QStyledItemDelegate): return QStyledItemDelegate.sizeHint(self, *args) + QSize(0, 15) def setEditorData(self, editor, index): - name = unicode(index.data(Qt.DisplayRole) or '') + name = unicode_type(index.data(Qt.DisplayRole) or '') editor.setText(name) editor.lineEdit().selectAll() def setModelData(self, editor, model, index): - authors = string_to_authors(unicode(editor.text())) + authors = string_to_authors(unicode_type(editor.text())) model.setData(index, authors[0]) self.edited.emit(index.row()) @@ -89,10 +90,10 @@ class List(QListWidget): def edited(self, i): item = self.item(i) - q = unicode(item.text()) + q = unicode_type(item.text()) remove = [] for j in xrange(self.count()): - if i != j and unicode(self.item(j).text()) == q: + if i != j and unicode_type(self.item(j).text()) == q: remove.append(j) for x in sorted(remove, reverse=True): self.takeItem(x) @@ -177,7 +178,7 @@ class AuthorsEdit(QDialog): def authors(self): ans = [] for i in xrange(self.al.count()): - ans.append(unicode(self.al.item(i).text())) + ans.append(unicode_type(self.al.item(i).text())) return ans or [_('Unknown')] def add_author(self): diff --git a/src/calibre/gui2/dialogs/book_info.py b/src/calibre/gui2/dialogs/book_info.py index 2871c85615..aec75c3133 100644 --- a/src/calibre/gui2/dialogs/book_info.py +++ b/src/calibre/gui2/dialogs/book_info.py @@ -16,6 +16,7 @@ from calibre.gui2.book_details import css, details_context_menu_event, render_ht from calibre.gui2.ui import get_gui from calibre.gui2.widgets import CoverView from calibre.gui2.widgets2 import Dialog +from polyglot.builtins import unicode_type class Configure(Dialog): @@ -154,9 +155,9 @@ class BookInfo(QDialog): self.ps = QShortcut(QKeySequence('Alt+Left'), self) self.ps.activated.connect(self.previous) self.next_button.setToolTip(_('Next [%s]')% - unicode(self.ns.key().toString(QKeySequence.NativeText))) + unicode_type(self.ns.key().toString(QKeySequence.NativeText))) self.previous_button.setToolTip(_('Previous [%s]')% - unicode(self.ps.key().toString(QKeySequence.NativeText))) + unicode_type(self.ps.key().toString(QKeySequence.NativeText))) geom = QCoreApplication.instance().desktop().availableGeometry(self) screen_height = geom.height() - 100 @@ -179,7 +180,7 @@ class BookInfo(QDialog): self.refresh(self.current_row, mi=mi) def link_clicked(self, qurl): - link = unicode(qurl.toString(NO_URL_FORMATTING)) + link = unicode_type(qurl.toString(NO_URL_FORMATTING)) self.link_delegate(link) def done(self, r): diff --git a/src/calibre/gui2/dialogs/catalog.py b/src/calibre/gui2/dialogs/catalog.py index 05b3fce85a..0537b35473 100644 --- a/src/calibre/gui2/dialogs/catalog.py +++ b/src/calibre/gui2/dialogs/catalog.py @@ -14,6 +14,7 @@ from calibre.customize.ui import config from calibre.gui2.dialogs.catalog_ui import Ui_Dialog from calibre.gui2 import dynamic, info_dialog from calibre.customize.ui import catalog_plugins +from polyglot.builtins import unicode_type class Catalog(QDialog, Ui_Dialog): @@ -30,7 +31,7 @@ class Catalog(QDialog, Ui_Dialog): self.dbspec, self.ids = dbspec, ids # Display the number of books we've been passed - self.count.setText(unicode(self.count.text()).format(len(ids))) + self.count.setText(unicode_type(self.count.text()).format(len(ids))) # Display the last-used title self.title.setText(dynamic.get('catalog_last_used_title', @@ -150,7 +151,7 @@ class Catalog(QDialog, Ui_Dialog): return ans def show_plugin_tab(self, idx): - cf = unicode(self.format.currentText()).lower() + cf = unicode_type(self.format.currentText()).lower() while self.tabs.count() > 1: self.tabs.removeTab(1) for pw in self.widgets: @@ -168,7 +169,7 @@ class Catalog(QDialog, Ui_Dialog): self.buttonBox.button(self.buttonBox.Help).setVisible(False) def format_changed(self, idx): - cf = unicode(self.format.currentText()) + cf = unicode_type(self.format.currentText()) if cf in self.sync_enabled_formats: self.sync.setEnabled(True) else: @@ -179,7 +180,7 @@ class Catalog(QDialog, Ui_Dialog): ''' When title/format change, invalidate Preset in E-book options tab ''' - cf = unicode(self.format.currentText()).lower() + cf = unicode_type(self.format.currentText()).lower() if cf in ['azw3', 'epub', 'mobi'] and hasattr(self.options_widget, 'settings_changed'): self.options_widget.settings_changed("title/format") @@ -192,9 +193,9 @@ class Catalog(QDialog, Ui_Dialog): return ans def save_catalog_settings(self): - self.catalog_format = unicode(self.format.currentText()) + self.catalog_format = unicode_type(self.format.currentText()) dynamic.set('catalog_preferred_format', self.catalog_format) - self.catalog_title = unicode(self.title.text()) + self.catalog_title = unicode_type(self.title.text()) dynamic.set('catalog_last_used_title', self.catalog_title) self.catalog_sync = bool(self.sync.isChecked()) dynamic.set('catalog_sync_to_device', self.catalog_sync) diff --git a/src/calibre/gui2/dialogs/check_library.py b/src/calibre/gui2/dialogs/check_library.py index 9f032bed33..52108e16c4 100644 --- a/src/calibre/gui2/dialogs/check_library.py +++ b/src/calibre/gui2/dialogs/check_library.py @@ -15,6 +15,7 @@ from calibre.gui2.dialogs.confirm_delete import confirm from calibre.library.check_library import CheckLibrary, CHECKS from calibre.utils.recycle_bin import delete_file, delete_tree from calibre import prints, as_unicode +from polyglot.builtins import unicode_type class DBCheck(QDialog): # {{{ @@ -232,8 +233,8 @@ class CheckLibraryDialog(QDialog): return True def accept(self): - self.db.new_api.set_pref('check_library_ignore_extensions', unicode(self.ext_ignores.text())) - self.db.new_api.set_pref('check_library_ignore_names', unicode(self.name_ignores.text())) + self.db.new_api.set_pref('check_library_ignore_extensions', unicode_type(self.ext_ignores.text())) + self.db.new_api.set_pref('check_library_ignore_names', unicode_type(self.name_ignores.text())) QDialog.accept(self) def box_to_list(self, txt): @@ -241,8 +242,8 @@ class CheckLibraryDialog(QDialog): def run_the_check(self): checker = CheckLibrary(self.db.library_path, self.db) - checker.scan_library(self.box_to_list(unicode(self.name_ignores.text())), - self.box_to_list(unicode(self.ext_ignores.text()))) + checker.scan_library(self.box_to_list(unicode_type(self.name_ignores.text())), + self.box_to_list(unicode_type(self.ext_ignores.text()))) plaintext = [] @@ -335,7 +336,7 @@ class CheckLibraryDialog(QDialog): for it in items: if it.checkState(1): try: - p = os.path.join(self.db.library_path ,unicode(it.text(1))) + p = os.path.join(self.db.library_path, unicode_type(it.text(1))) if os.path.isdir(p): delete_tree(p) else: @@ -343,7 +344,7 @@ class CheckLibraryDialog(QDialog): except: prints('failed to delete', os.path.join(self.db.library_path, - unicode(it.text(1)))) + unicode_type(it.text(1)))) self.run_the_check() def fix_missing_formats(self): diff --git a/src/calibre/gui2/dialogs/choose_format_device.py b/src/calibre/gui2/dialogs/choose_format_device.py index 775af1dad5..63af23d726 100644 --- a/src/calibre/gui2/dialogs/choose_format_device.py +++ b/src/calibre/gui2/dialogs/choose_format_device.py @@ -5,6 +5,7 @@ from PyQt5.Qt import QDialog, QTreeWidgetItem, QIcon, QModelIndex from calibre.gui2 import file_icon_provider from calibre.gui2.dialogs.choose_format_device_ui import Ui_ChooseFormatDeviceDialog +from polyglot.builtins import unicode_type class ChooseFormatDeviceDialog(QDialog, Ui_ChooseFormatDeviceDialog): @@ -48,6 +49,5 @@ class ChooseFormatDeviceDialog(QDialog, Ui_ChooseFormatDeviceDialog): return self._format def accept(self): - self._format = unicode(self.formats.currentItem().text(0)) + self._format = unicode_type(self.formats.currentItem().text(0)) return QDialog.accept(self) - diff --git a/src/calibre/gui2/dialogs/choose_library.py b/src/calibre/gui2/dialogs/choose_library.py index 535c729419..419ed96da7 100644 --- a/src/calibre/gui2/dialogs/choose_library.py +++ b/src/calibre/gui2/dialogs/choose_library.py @@ -17,6 +17,7 @@ from calibre.gui2 import error_dialog, choose_dir from calibre.constants import (filesystem_encoding, iswindows, get_portable_base) from calibre import isbytestring, patheq, force_unicode +from polyglot.builtins import unicode_type class ProgressDialog(PD): @@ -54,7 +55,7 @@ class ChooseLibrary(QDialog, Ui_Dialog): lp = db.library_path if isbytestring(lp): lp = lp.decode(filesystem_encoding) - loc = unicode(self.old_location.text()).format(lp) + loc = unicode_type(self.old_location.text()).format(lp) self.old_location.setText(loc) self.browse_button.clicked.connect(self.choose_loc) self.empty_library.toggled.connect(self.empty_library_toggled) @@ -168,7 +169,7 @@ class ChooseLibrary(QDialog, Ui_Dialog): action = 'existing' elif self.empty_library.isChecked(): action = 'new' - text = unicode(self.location.text()).strip() + text = unicode_type(self.location.text()).strip() if not text: return error_dialog(self, _('No location'), _('No location selected'), show=True) diff --git a/src/calibre/gui2/dialogs/comicconf.py b/src/calibre/gui2/dialogs/comicconf.py index 07931322aa..2bffd4a4c7 100644 --- a/src/calibre/gui2/dialogs/comicconf.py +++ b/src/calibre/gui2/dialogs/comicconf.py @@ -7,6 +7,7 @@ __docformat__ = 'restructuredtext en' from PyQt5.Qt import QDialog from calibre.gui2.dialogs.comicconf_ui import Ui_Dialog from calibre.ebooks.lrf.comic.convert_from import config, PROFILES +from polyglot.builtins import unicode_type def set_conversion_defaults(window): @@ -81,9 +82,9 @@ class ComicConf(QDialog, Ui_Dialog): elif hasattr(g, 'value'): val = g.value() elif hasattr(g, 'itemText'): - val = unicode(g.itemText(g.currentIndex())) + val = unicode_type(g.itemText(g.currentIndex())) elif hasattr(g, 'text'): - val = unicode(g.text()) + val = unicode_type(g.text()) else: raise Exception('Bad coding') self.config.set(opt.name, val) diff --git a/src/calibre/gui2/dialogs/custom_recipes.py b/src/calibre/gui2/dialogs/custom_recipes.py index 3ba3baef7d..4562361c5e 100644 --- a/src/calibre/gui2/dialogs/custom_recipes.py +++ b/src/calibre/gui2/dialogs/custom_recipes.py @@ -21,6 +21,7 @@ from calibre.gui2.tweak_book.editor.text import TextEdit from calibre.utils.icu import sort_key from calibre.web.feeds.recipes.collection import get_builtin_recipe_collection, get_builtin_recipe_by_id from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type def is_basic_recipe(src): @@ -118,14 +119,14 @@ def py3_repr(x): ans = repr(x) if isinstance(x, bytes) and not ans.startswith('b'): ans = 'b' + ans - if isinstance(x, unicode) and ans.startswith('u'): + if isinstance(x, unicode_type) and ans.startswith('u'): ans = ans[1:] return ans def options_to_recipe_source(title, oldest_article, max_articles_per_feed, feeds): classname = 'BasicUserRecipe%d' % int(time.time()) - title = unicode(title).strip() or classname + title = unicode_type(title).strip() or classname indent = ' ' * 8 if feeds: if len(feeds[0]) == 1: @@ -593,8 +594,8 @@ class CustomRecipes(Dialog): if not items: return item = items[-1] - id_ = unicode(item.data(Qt.UserRole) or '') - title = unicode(item.data(Qt.DisplayRole) or '').rpartition(' [')[0] + id_ = unicode_type(item.data(Qt.UserRole) or '') + title = unicode_type(item.data(Qt.DisplayRole) or '').rpartition(' [')[0] src = get_builtin_recipe_by_id(id_, download_recipe=True) if src is None: raise Exception('Something weird happened') diff --git a/src/calibre/gui2/dialogs/delete_matching_from_device.py b/src/calibre/gui2/dialogs/delete_matching_from_device.py index 09f7707449..646233dbae 100644 --- a/src/calibre/gui2/dialogs/delete_matching_from_device.py +++ b/src/calibre/gui2/dialogs/delete_matching_from_device.py @@ -11,6 +11,7 @@ from calibre.ebooks.metadata import authors_to_string, authors_to_sort_string, \ from calibre.gui2.dialogs.delete_matching_from_device_ui import \ Ui_DeleteMatchingFromDeviceDialog from calibre.utils.date import UNDEFINED_DATE +from polyglot.builtins import unicode_type class tableItem(QTableWidgetItem): @@ -116,7 +117,6 @@ class DeleteMatchingFromDeviceDialog(QDialog, Ui_DeleteMatchingFromDeviceDialog) if self.table.item(row, 0).checkState() == Qt.Unchecked: continue (model, id, path) = self.table.item(row, 0).data(Qt.UserRole) - path = unicode(path) + path = unicode_type(path) self.result.append((model, id, path)) return - diff --git a/src/calibre/gui2/dialogs/device_category_editor.py b/src/calibre/gui2/dialogs/device_category_editor.py index 3923c3dd93..9cb9cd1230 100644 --- a/src/calibre/gui2/dialogs/device_category_editor.py +++ b/src/calibre/gui2/dialogs/device_category_editor.py @@ -5,6 +5,7 @@ from PyQt5.Qt import Qt, QDialog, QListWidgetItem from calibre.gui2.dialogs.device_category_editor_ui import Ui_DeviceCategoryEditor from calibre.gui2 import question_dialog, error_dialog +from polyglot.builtins import unicode_type class ListWidgetItem(QListWidgetItem): @@ -90,7 +91,7 @@ class DeviceCategoryEditor(QDialog, Ui_DeviceCategoryEditor): return if item.text() != item.initial_text(): id_ = int(item.data(Qt.UserRole)) - self.to_rename[id_] = unicode(item.text()) + self.to_rename[id_] = unicode_type(item.text()) def rename_tag(self): item = self.available_tags.currentItem() @@ -109,7 +110,7 @@ class DeviceCategoryEditor(QDialog, Ui_DeviceCategoryEditor): error_dialog(self, _('No items selected'), _('You must select at least one item from the list.')).exec_() return - ct = ', '.join([unicode(item.text()) for item in deletes]) + ct = ', '.join([unicode_type(item.text()) for item in deletes]) if not question_dialog(self, _('Are you sure?'), '

'+_('Are you sure you want to delete the following items?')+'
'+ct): return diff --git a/src/calibre/gui2/dialogs/drm_error.py b/src/calibre/gui2/dialogs/drm_error.py index 1a70ad0458..44a6252358 100644 --- a/src/calibre/gui2/dialogs/drm_error.py +++ b/src/calibre/gui2/dialogs/drm_error.py @@ -8,6 +8,7 @@ __docformat__ = 'restructuredtext en' from PyQt5.Qt import QDialog from calibre.gui2.dialogs.drm_error_ui import Ui_Dialog +from polyglot.builtins import unicode_type class DRMErrorMessage(QDialog, Ui_Dialog): @@ -16,7 +17,6 @@ class DRMErrorMessage(QDialog, Ui_Dialog): QDialog.__init__(self, parent) self.setupUi(self) if title is not None: - t = unicode(self.msg.text()) + t = unicode_type(self.msg.text()) self.msg.setText('

%s

%s'%(title, t)) self.resize(self.sizeHint()) - diff --git a/src/calibre/gui2/dialogs/duplicates.py b/src/calibre/gui2/dialogs/duplicates.py index 5154058095..0c0b3d32c7 100644 --- a/src/calibre/gui2/dialogs/duplicates.py +++ b/src/calibre/gui2/dialogs/duplicates.py @@ -15,6 +15,7 @@ from PyQt5.Qt import ( from calibre.gui2 import gprefs from calibre.ebooks.metadata import authors_to_string +from polyglot.builtins import unicode_type class DuplicatesQuestion(QDialog): @@ -144,10 +145,10 @@ class DuplicatesQuestion(QDialog): for i in xrange(self.dup_list.topLevelItemCount()): x = self.dup_list.topLevelItem(i) check = '✓' if x.checkState(0) == Qt.Checked else '✗' - title = '%s %s' % (check, unicode(x.text(0))) + title = '%s %s' % (check, unicode_type(x.text(0))) dups = [] for child in (x.child(j) for j in xrange(x.childCount())): - dups.append('\t' + unicode(child.text(0))) + dups.append('\t' + unicode_type(child.text(0))) entries.append(title + '\n' + '\n'.join(dups)) return '\n\n'.join(entries) diff --git a/src/calibre/gui2/dialogs/edit_authors_dialog.py b/src/calibre/gui2/dialogs/edit_authors_dialog.py index 8072b221c5..dc218bebd9 100644 --- a/src/calibre/gui2/dialogs/edit_authors_dialog.py +++ b/src/calibre/gui2/dialogs/edit_authors_dialog.py @@ -11,15 +11,16 @@ from calibre.ebooks.metadata import author_to_author_sort, string_to_authors from calibre.gui2 import error_dialog, gprefs from calibre.gui2.dialogs.edit_authors_dialog_ui import Ui_EditAuthorsDialog from calibre.utils.icu import sort_key +from polyglot.builtins import unicode_type class tableItem(QTableWidgetItem): def __ge__(self, other): - return sort_key(unicode(self.text())) >= sort_key(unicode(other.text())) + return sort_key(unicode_type(self.text())) >= sort_key(unicode_type(other.text())) def __lt__(self, other): - return sort_key(unicode(self.text())) < sort_key(unicode(other.text())) + return sort_key(unicode_type(self.text())) < sort_key(unicode_type(other.text())) class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog): @@ -195,28 +196,28 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog): def copy_to_clipboard(self): cb = QApplication.clipboard() - cb.setText(unicode(self.context_item.text())) + cb.setText(unicode_type(self.context_item.text())) def paste_from_clipboard(self): cb = QApplication.clipboard() self.context_item.setText(cb.text()) def upper_case(self): - self.context_item.setText(icu_upper(unicode(self.context_item.text()))) + self.context_item.setText(icu_upper(unicode_type(self.context_item.text()))) def lower_case(self): - self.context_item.setText(icu_lower(unicode(self.context_item.text()))) + self.context_item.setText(icu_lower(unicode_type(self.context_item.text()))) def swap_case(self): - self.context_item.setText(unicode(self.context_item.text()).swapcase()) + self.context_item.setText(unicode_type(self.context_item.text()).swapcase()) def title_case(self): from calibre.utils.titlecase import titlecase - self.context_item.setText(titlecase(unicode(self.context_item.text()))) + self.context_item.setText(titlecase(unicode_type(self.context_item.text()))) def capitalize(self): from calibre.utils.icu import capitalize - self.context_item.setText(capitalize(unicode(self.context_item.text()))) + self.context_item.setText(capitalize(unicode_type(self.context_item.text()))) def copy_aus_to_au(self): row = self.context_item.row() @@ -242,14 +243,14 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog): self.buttonBox.button(QDialogButtonBox.Ok).setAutoDefault(False) self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(False) self.buttonBox.button(QDialogButtonBox.Cancel).setAutoDefault(False) - st = icu_lower(unicode(self.find_box.currentText())) + st = icu_lower(unicode_type(self.find_box.currentText())) for i in range(0, self.table.rowCount()*2): self.start_find_pos = (self.start_find_pos + 1) % (self.table.rowCount()*2) r = (self.start_find_pos/2)%self.table.rowCount() c = self.start_find_pos % 2 item = self.table.item(r, c) - text = icu_lower(unicode(item.text())) + text = icu_lower(unicode_type(item.text())) if st in text: self.table.setCurrentItem(item) self.table.setFocus(True) @@ -281,9 +282,9 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog): self.result = [] for row in range(0,self.table.rowCount()): id = int(self.table.item(row, 0).data(Qt.UserRole)) - aut = unicode(self.table.item(row, 0).text()).strip() - sort = unicode(self.table.item(row, 1).text()).strip() - link = unicode(self.table.item(row, 2).text()).strip() + aut = unicode_type(self.table.item(row, 0).text()).strip() + sort = unicode_type(self.table.item(row, 1).text()).strip() + link = unicode_type(self.table.item(row, 2).text()).strip() orig_aut,orig_sort,orig_link = self.authors[id] if orig_aut != aut or orig_sort != sort or orig_link != link: self.result.append((id, orig_aut, aut, sort, link)) @@ -292,7 +293,7 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog): self.table.cellChanged.disconnect() for row in range(0,self.table.rowCount()): item = self.table.item(row, 0) - aut = unicode(item.text()).strip() + aut = unicode_type(item.text()).strip() c = self.table.item(row, 1) # Sometimes trailing commas are left by changing between copy algs c.setText(author_to_author_sort(aut).rstrip(',')) @@ -303,7 +304,7 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog): self.table.cellChanged.disconnect() for row in range(0,self.table.rowCount()): item = self.table.item(row, 1) - aus = unicode(item.text()).strip() + aus = unicode_type(item.text()).strip() c = self.table.item(row, 0) # Sometimes trailing commas are left by changing between copy algs c.setText(aus) @@ -313,7 +314,7 @@ class EditAuthorsDialog(QDialog, Ui_EditAuthorsDialog): def cell_changed(self, row, col): if col == 0: item = self.table.item(row, 0) - aut = unicode(item.text()).strip() + aut = unicode_type(item.text()).strip() aut_list = string_to_authors(aut) if len(aut_list) != 1: error_dialog(self.parent(), _('Invalid author name'), diff --git a/src/calibre/gui2/dialogs/match_books.py b/src/calibre/gui2/dialogs/match_books.py index 35a440be25..f258f78d88 100644 --- a/src/calibre/gui2/dialogs/match_books.py +++ b/src/calibre/gui2/dialogs/match_books.py @@ -14,6 +14,7 @@ from PyQt5.Qt import (Qt, QDialog, QAbstractItemView, QTableWidgetItem, from calibre.gui2 import gprefs, error_dialog from calibre.gui2.dialogs.match_books_ui import Ui_MatchBooks from calibre.utils.icu import sort_key +from polyglot.builtins import unicode_type class TableItem(QTableWidgetItem): @@ -125,7 +126,7 @@ class MatchBooks(QDialog, Ui_MatchBooks): QDialog.keyPressEvent(self, e) def do_search(self): - query = unicode(self.search_text.text()) + query = unicode_type(self.search_text.text()) if not query: d = error_dialog(self.gui, _('Match books'), _('You must enter a search expression into the search box')) @@ -217,4 +218,3 @@ class MatchBooks(QDialog, Ui_MatchBooks): def reject(self): self.close() QDialog.reject(self) - diff --git a/src/calibre/gui2/dialogs/message_box.py b/src/calibre/gui2/dialogs/message_box.py index d02a063e5f..b7e2618ba3 100644 --- a/src/calibre/gui2/dialogs/message_box.py +++ b/src/calibre/gui2/dialogs/message_box.py @@ -16,6 +16,7 @@ from PyQt5.Qt import ( from calibre.constants import __version__, isfrozen from calibre.gui2 import gprefs +from polyglot.builtins import unicode_type class Icon(QWidget): @@ -162,9 +163,9 @@ class MessageBox(QDialog): # {{{ def copy_to_clipboard(self, *args): QApplication.clipboard().setText( 'calibre, version %s\n%s: %s\n\n%s' % - (__version__, unicode(self.windowTitle()), - unicode(self.msg.text()), - unicode(self.det_msg.toPlainText()))) + (__version__, unicode_type(self.windowTitle()), + unicode_type(self.msg.text()), + unicode_type(self.det_msg.toPlainText()))) if hasattr(self, 'ctc_button'): self.ctc_button.setText(_('Copied')) @@ -418,13 +419,13 @@ class JobError(QDialog): # {{{ QApplication.clipboard().setText( u'calibre, version %s (%s, embedded-python: %s)\n%s: %s\n\n%s' % (__version__, sys.platform, isfrozen, - unicode(self.windowTitle()), unicode(d.toPlainText()), - unicode(self.det_msg.toPlainText()))) + unicode_type(self.windowTitle()), unicode_type(d.toPlainText()), + unicode_type(self.det_msg.toPlainText()))) if hasattr(self, 'ctc_button'): self.ctc_button.setText(_('Copied')) def toggle_det_msg(self, *args): - vis = unicode(self.det_msg_toggle.text()) == self.hide_det_msg + vis = unicode_type(self.det_msg_toggle.text()) == self.hide_det_msg self.det_msg_toggle.setText(self.show_det_msg if vis else self.hide_det_msg) self.det_msg.setVisible(not vis) diff --git a/src/calibre/gui2/dialogs/metadata_bulk.py b/src/calibre/gui2/dialogs/metadata_bulk.py index 76f0d3cf68..0c87c31b11 100644 --- a/src/calibre/gui2/dialogs/metadata_bulk.py +++ b/src/calibre/gui2/dialogs/metadata_bulk.py @@ -32,6 +32,7 @@ from calibre.utils.date import qt_to_dt, internal_iso_format_string from calibre.utils.icu import capitalize, sort_key from calibre.utils.titlecase import titlecase from calibre.gui2.widgets import LineEditECM +from polyglot.builtins import unicode_type Settings = namedtuple('Settings', 'remove_all remove add au aus do_aus rating pub do_series do_autonumber ' @@ -170,7 +171,7 @@ class MyBlockingBusy(QDialog): # {{{ except Exception as err: import traceback try: - err = unicode(err) + err = unicode_type(err) except: err = repr(err) self.error = (err, traceback.format_exc()) @@ -478,7 +479,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): self.refresh_book_list.toggled.connect(self.save_refresh_booklist) self.ids = [self.db.id(r) for r in rows] self.first_title = self.db.title(self.ids[0], index_is_id=True) - self.cover_clone.setToolTip(unicode(self.cover_clone.toolTip()) + ' (%s)' % self.first_title) + self.cover_clone.setToolTip(unicode_type(self.cover_clone.toolTip()) + ' (%s)' % self.first_title) self.box_title.setText('

' + _('Editing meta information for %d books') % len(rows)) @@ -581,8 +582,8 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): self.comments = d.textbox.html b = self.comments_button b.setStyleSheet('QPushButton { font-weight: bold }') - if unicode(b.text())[-1] != '*': - b.setText(unicode(b.text()) + ' *') + if unicode_type(b.text())[-1] != '*': + b.setText(unicode_type(b.text()) + ' *') def save_refresh_booklist(self, *args): gprefs['refresh_book_list_on_bulk_edit'] = bool(self.refresh_book_list.isChecked()) @@ -752,18 +753,18 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): def s_r_sf_itemdata(self, idx): if idx is None: idx = self.search_field.currentIndex() - return unicode(self.search_field.itemData(idx) or '') + return unicode_type(self.search_field.itemData(idx) or '') def s_r_df_itemdata(self, idx): if idx is None: idx = self.destination_field.currentIndex() - return unicode(self.destination_field.itemData(idx) or '') + return unicode_type(self.destination_field.itemData(idx) or '') def s_r_get_field(self, mi, field): if field: if field == '{template}': v = SafeFormat().safe_format( - unicode(self.s_r_template.text()), mi, _('S/R TEMPLATE ERROR'), mi) + unicode_type(self.s_r_template.text()), mi, _('S/R TEMPLATE ERROR'), mi) return [v] fm = self.db.metadata_for_field(field) if field == 'sort': @@ -776,7 +777,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): val = str(val) elif fm['is_csp']: # convert the csp dict into a list - id_type = unicode(self.s_r_src_ident.currentText()) + id_type = unicode_type(self.s_r_src_ident.currentText()) if id_type: val = [val.get(id_type, '')] else: @@ -825,7 +826,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): if len(t) > 1: t = t[self.starting_from.value()-1: self.starting_from.value()-1 + self.results_count.value()] - w.setText(unicode(self.multiple_separator.text()).join(t)) + w.setText(unicode_type(self.multiple_separator.text()).join(t)) if self.search_mode.currentIndex() == 0: self.destination_field.setCurrentIndex(idx) @@ -893,8 +894,8 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): getattr(self, 'book_%d_result'%(i+1)).setText('') def s_r_func(self, match): - rfunc = self.s_r_functions[unicode(self.replace_func.currentText())] - rtext = unicode(self.replace_with.text()) + rfunc = self.s_r_functions[unicode_type(self.replace_func.currentText())] + rtext = unicode_type(self.replace_with.text()) rtext = match.expand(rtext) return rfunc(rtext) @@ -902,7 +903,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): src_field = self.s_r_sf_itemdata(None) src = self.s_r_get_field(mi, src_field) result = [] - rfunc = self.s_r_functions[unicode(self.replace_func.currentText())] + rfunc = self.s_r_functions[unicode_type(self.replace_func.currentText())] for s in src: t = self.s_r_obj.sub(self.s_r_func, s) if self.search_mode.currentIndex() == 0: @@ -936,7 +937,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): dest_mode = self.replace_mode.currentIndex() if self.destination_field_fm['is_csp']: - dest_ident = unicode(self.s_r_dst_ident.text()) + dest_ident = unicode_type(self.s_r_dst_ident.text()) if not dest_ident or (src == 'identifiers' and dest_ident == '*'): raise Exception(_('You must specify a destination identifier type')) @@ -953,7 +954,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): if dest_mode != 0: dest_val = mi.get(dest, '') if self.db.metadata_for_field(dest)['is_csp']: - dst_id_type = unicode(self.s_r_dst_ident.text()) + dst_id_type = unicode_type(self.s_r_dst_ident.text()) if dst_id_type: dest_val = [dest_val.get(dst_id_type, '')] else: @@ -989,7 +990,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): flags |= re.UNICODE try: - stext = unicode(self.search_for.text()) + stext = unicode_type(self.search_for.text()) if not stext: raise Exception(_('You must specify a search expression in the "Search for" field')) if self.search_mode.currentIndex() == 0: @@ -1004,7 +1005,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): try: self.test_result.setText(self.s_r_obj.sub(self.s_r_func, - unicode(self.test_text.text()))) + unicode_type(self.test_text.text()))) except Exception as e: self.s_r_error = e self.s_r_set_colors() @@ -1019,7 +1020,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): if len(t) > 1 and self.destination_field_fm['is_multiple']: t = t[self.starting_from.value()-1: self.starting_from.value()-1 + self.results_count.value()] - t = unicode(self.multiple_separator.text()).join(t) + t = unicode_type(self.multiple_separator.text()).join(t) else: t = self.s_r_replace_mode_separator().join(t) wr.setText(t) @@ -1043,7 +1044,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): if dfm['is_csp']: # convert the colon-separated pair strings back into a dict, # which is what set_identifiers wants - dst_id_type = unicode(self.s_r_dst_ident.text()) + dst_id_type = unicode_type(self.s_r_dst_ident.text()) if dst_id_type and dst_id_type != '*': v = ''.join(val) ids = mi.get(dest) @@ -1166,19 +1167,19 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): remove_all = self.remove_all_tags.isChecked() remove = [] if not remove_all: - remove = unicode(self.remove_tags.text()).strip().split(',') - add = unicode(self.tags.text()).strip().split(',') - au = unicode(self.authors.text()) - aus = unicode(self.author_sort.text()) + remove = unicode_type(self.remove_tags.text()).strip().split(',') + add = unicode_type(self.tags.text()).strip().split(',') + au = unicode_type(self.authors.text()) + aus = unicode_type(self.author_sort.text()) do_aus = self.author_sort.isEnabled() rating = self.rating.rating_value if not self.apply_rating.isChecked(): rating = -1 - pub = unicode(self.publisher.text()) + pub = unicode_type(self.publisher.text()) do_series = self.write_series clear_series = self.clear_series.isChecked() clear_pub = self.clear_pub.isChecked() - series = unicode(self.series.currentText()).strip() + series = unicode_type(self.series.currentText()).strip() do_autonumber = self.autonumber_series.isChecked() do_series_restart = self.series_numbering_restarts.isChecked() series_start_value = self.series_start_number.value() @@ -1248,7 +1249,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): return QDialog.accept(self) def series_changed(self, *args): - self.write_series = bool(unicode(self.series.currentText()).strip()) + self.write_series = bool(unicode_type(self.series.currentText()).strip()) self.autonumber_series.setEnabled(True) def s_r_remove_query(self, *args): @@ -1261,7 +1262,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): return item_id = self.query_field.currentIndex() - item_name = unicode(self.query_field.currentText()) + item_name = unicode_type(self.query_field.currentText()) self.query_field.blockSignals(True) self.query_field.removeItem(item_id) @@ -1289,7 +1290,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): error_dialog(self, _("Save search/replace"), _("You must provide a name."), show=True) new = True - name = unicode(name) + name = unicode_type(name) if name in self.queries.keys(): if not question_dialog(self, _("Save search/replace"), _("That saved search/replace already exists and will be overwritten. " @@ -1299,21 +1300,21 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): query = {} query['name'] = name - query['search_field'] = unicode(self.search_field.currentText()) - query['search_mode'] = unicode(self.search_mode.currentText()) - query['s_r_template'] = unicode(self.s_r_template.text()) - query['s_r_src_ident'] = unicode(self.s_r_src_ident.currentText()) - query['search_for'] = unicode(self.search_for.text()) + query['search_field'] = unicode_type(self.search_field.currentText()) + query['search_mode'] = unicode_type(self.search_mode.currentText()) + query['s_r_template'] = unicode_type(self.s_r_template.text()) + query['s_r_src_ident'] = unicode_type(self.s_r_src_ident.currentText()) + query['search_for'] = unicode_type(self.search_for.text()) query['case_sensitive'] = self.case_sensitive.isChecked() - query['replace_with'] = unicode(self.replace_with.text()) - query['replace_func'] = unicode(self.replace_func.currentText()) - query['destination_field'] = unicode(self.destination_field.currentText()) - query['s_r_dst_ident'] = unicode(self.s_r_dst_ident.text()) - query['replace_mode'] = unicode(self.replace_mode.currentText()) + query['replace_with'] = unicode_type(self.replace_with.text()) + query['replace_func'] = unicode_type(self.replace_func.currentText()) + query['destination_field'] = unicode_type(self.destination_field.currentText()) + query['s_r_dst_ident'] = unicode_type(self.s_r_dst_ident.text()) + query['replace_mode'] = unicode_type(self.replace_mode.currentText()) query['comma_separated'] = self.comma_separated.isChecked() query['results_count'] = self.results_count.value() query['starting_from'] = self.starting_from.value() - query['multiple_separator'] = unicode(self.multiple_separator.text()) + query['multiple_separator'] = unicode_type(self.multiple_separator.text()) self.queries[name] = query self.queries.commit() @@ -1332,7 +1333,7 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): self.s_r_reset_query_fields() self.saved_search_name = '' return - item = self.queries.get(unicode(item_name), None) + item = self.queries.get(unicode_type(item_name), None) if item is None: self.s_r_reset_query_fields() return diff --git a/src/calibre/gui2/dialogs/opml.py b/src/calibre/gui2/dialogs/opml.py index 9235eea48d..0f35b81b3d 100644 --- a/src/calibre/gui2/dialogs/opml.py +++ b/src/calibre/gui2/dialogs/opml.py @@ -17,6 +17,7 @@ from lxml import etree from calibre.gui2 import choose_files, error_dialog from calibre.utils.icu import sort_key +from polyglot.builtins import unicode_type Group = namedtuple('Group', 'title feeds') @@ -125,7 +126,7 @@ class ImportOPML(QDialog): self.path.setText(opml_files[0]) def accept(self): - path = unicode(self.path.text()) + path = unicode_type(self.path.text()) if not path: return error_dialog(self, _('Path not specified'), _( 'You must specify the path to the OPML file to import'), show=True) diff --git a/src/calibre/gui2/dialogs/password.py b/src/calibre/gui2/dialogs/password.py index 08a7ca6251..708cc9d1ba 100644 --- a/src/calibre/gui2/dialogs/password.py +++ b/src/calibre/gui2/dialogs/password.py @@ -5,6 +5,7 @@ from PyQt5.Qt import QDialog, QLineEdit, Qt from calibre.gui2.dialogs.password_ui import Ui_Dialog from calibre.gui2 import dynamic +from polyglot.builtins import unicode_type class PasswordDialog(QDialog, Ui_Dialog): @@ -34,13 +35,12 @@ class PasswordDialog(QDialog, Ui_Dialog): self.gui_password.setEchoMode(QLineEdit.Normal) def username(self): - return unicode(self.gui_username.text()) + return unicode_type(self.gui_username.text()) def password(self): - return unicode(self.gui_password.text()) + return unicode_type(self.gui_password.text()) def accept(self): - dynamic.set(self.cfg_key+'__un', unicode(self.gui_username.text())) - dynamic.set(self.cfg_key+'__pw', unicode(self.gui_password.text())) + dynamic.set(self.cfg_key+'__un', unicode_type(self.gui_username.text())) + dynamic.set(self.cfg_key+'__pw', unicode_type(self.gui_password.text())) QDialog.accept(self) - diff --git a/src/calibre/gui2/dialogs/plugin_updater.py b/src/calibre/gui2/dialogs/plugin_updater.py index 917b9d4cb4..18355b16b4 100644 --- a/src/calibre/gui2/dialogs/plugin_updater.py +++ b/src/calibre/gui2/dialogs/plugin_updater.py @@ -24,6 +24,7 @@ from calibre.gui2 import error_dialog, question_dialog, info_dialog, open_url, g from calibre.gui2.preferences.plugins import ConfigWidget from calibre.utils.date import UNDEFINED_DATE, format_date from calibre.utils.https import get_https_resource_securely +from polyglot.builtins import unicode_type SERVER = 'https://code.calibre-ebook.com/plugins/' INDEX_URL = '%splugins.json.bz2' % SERVER @@ -267,7 +268,7 @@ class DisplayPluginSortFilterModel(QSortFilterProxyModel): self.invalidateFilter() def set_filter_text(self, filter_text_value): - self.filter_text = icu_lower(unicode(filter_text_value)) + self.filter_text = icu_lower(unicode_type(filter_text_value)) self.invalidateFilter() @@ -276,7 +277,7 @@ class DisplayPluginModel(QAbstractTableModel): def __init__(self, display_plugins): QAbstractTableModel.__init__(self) self.display_plugins = display_plugins - self.headers = map(unicode, [_('Plugin name'), _('Donate'), _('Status'), _('Installed'), + self.headers = map(unicode_type, [_('Plugin name'), _('Donate'), _('Status'), _('Installed'), _('Available'), _('Released'), _('calibre'), _('Author')]) def rowCount(self, *args): @@ -726,7 +727,7 @@ class PluginUpdaterDialog(SizePersistedDialog): plugin = add_plugin(zip_path) except NameConflict as e: return error_dialog(self.gui, _('Already exists'), - unicode(e), show=True) + unicode_type(e), show=True) # Check for any toolbars to add to. widget = ConfigWidget(self.gui) widget.gui = self.gui @@ -841,7 +842,7 @@ class PluginUpdaterDialog(SizePersistedDialog): continue if heading_node.text_content().lower().find('version history') != -1: div_node = spoiler_node.xpath('div')[0] - text = html.tostring(div_node, method='html', encoding=unicode) + text = html.tostring(div_node, method='html', encoding=unicode_type) return re.sub('', '

', text) except: if DEBUG: diff --git a/src/calibre/gui2/dialogs/progress.py b/src/calibre/gui2/dialogs/progress.py index e36bcaf5bb..bc50921431 100644 --- a/src/calibre/gui2/dialogs/progress.py +++ b/src/calibre/gui2/dialogs/progress.py @@ -9,6 +9,7 @@ from PyQt5.Qt import ( from calibre.gui2 import elided_text from calibre.gui2.progress_indicator import ProgressIndicator +from polyglot.builtins import unicode_type class ProgressDialog(QDialog): @@ -102,7 +103,7 @@ class ProgressDialog(QDialog): return self.title_label.text() def fset(self, val): - self.title_label.setText(unicode(val or '')) + self.title_label.setText(unicode_type(val or '')) return property(fget=fget, fset=fset) @dynamic_property @@ -111,7 +112,7 @@ class ProgressDialog(QDialog): return self.message.text() def fset(self, val): - val = unicode(val or '') + val = unicode_type(val or '') self.message.setText(elided_text(val, self.font(), self.message.minimumWidth()-10)) return property(fget=fget, fset=fset) diff --git a/src/calibre/gui2/dialogs/quickview.py b/src/calibre/gui2/dialogs/quickview.py index 433abb00f3..8514408eeb 100644 --- a/src/calibre/gui2/dialogs/quickview.py +++ b/src/calibre/gui2/dialogs/quickview.py @@ -17,6 +17,7 @@ from calibre.gui2.dialogs.quickview_ui import Ui_Quickview from calibre.utils.date import timestampfromdt from calibre.utils.icu import sort_key from calibre.utils.iso8601 import UNDEFINED_DATE +from polyglot.builtins import unicode_type class TableItem(QTableWidgetItem): @@ -42,7 +43,7 @@ class TableItem(QTableWidgetItem): # self is not None and other is None therefore self >= other return True - if isinstance(self.sort, (str, unicode)): + if isinstance(self.sort, (str, unicode_type)): l = sort_key(self.sort) r = sort_key(other.sort) else: @@ -65,7 +66,7 @@ class TableItem(QTableWidgetItem): # self is not None therefore self > other return False - if isinstance(self.sort, (str, unicode)): + if isinstance(self.sort, (str, unicode_type)): l = sort_key(self.sort) r = sort_key(other.sort) else: @@ -406,7 +407,7 @@ class Quickview(QDialog, Ui_Quickview): def item_selected(self, txt): if self.no_valid_items: return - self.fill_in_books_box(unicode(txt)) + self.fill_in_books_box(unicode_type(txt)) self.set_search_text(self.current_key + ':"=' + txt.replace('"', '\\"') + '"') def refresh(self, idx): @@ -455,9 +456,9 @@ class Quickview(QDialog, Ui_Quickview): self.no_valid_items = False if self.fm[key]['datatype'] == 'rating': if self.fm[key]['display'].get('allow_half_stars', False): - vals = unicode(vals/2.0) + vals = unicode_type(vals/2.0) else: - vals = unicode(vals/2) + vals = unicode_type(vals/2) if not isinstance(vals, list): vals = [vals] vals.sort(key=sort_key) diff --git a/src/calibre/gui2/dialogs/scheduler.py b/src/calibre/gui2/dialogs/scheduler.py index e3f3eee073..9180f8057f 100644 --- a/src/calibre/gui2/dialogs/scheduler.py +++ b/src/calibre/gui2/dialogs/scheduler.py @@ -26,6 +26,7 @@ from calibre.utils.date import utcnow from calibre.utils.network import internet_connected from calibre import force_unicode from calibre.utils.localization import get_lang, canonicalize_lang +from polyglot.builtins import unicode_type def convert_day_time_schedule(val): @@ -151,7 +152,7 @@ class DaysOfMonth(Base): @property def schedule(self): - parts = [x.strip() for x in unicode(self.days.text()).split(',') if + parts = [x.strip() for x in unicode_type(self.days.text()).split(',') if x.strip()] try: days_of_month = tuple(map(int, parts)) @@ -455,7 +456,7 @@ class SchedulerDialog(QDialog): return True if self.account.isVisible(): - un, pw = map(unicode, (self.username.text(), self.password.text())) + un, pw = map(unicode_type, (self.username.text(), self.password.text())) un, pw = un.strip(), pw.strip() if not un and not pw and self.schedule.isChecked(): if not getattr(self, 'subscription_optional', False): @@ -478,8 +479,8 @@ class SchedulerDialog(QDialog): add_title_tag = self.add_title_tag.isChecked() keep_issues = u'0' if self.keep_issues.isEnabled(): - keep_issues = unicode(self.keep_issues.value()) - custom_tags = unicode(self.custom_tags.text()).strip() + keep_issues = unicode_type(self.keep_issues.value()) + custom_tags = unicode_type(self.custom_tags.text()).strip() custom_tags = [x.strip() for x in custom_tags.split(',')] self.recipe_model.customize_recipe(urn, add_title_tag, custom_tags, keep_issues) return True diff --git a/src/calibre/gui2/dialogs/search.py b/src/calibre/gui2/dialogs/search.py index d929ebf6b4..92f76f110e 100644 --- a/src/calibre/gui2/dialogs/search.py +++ b/src/calibre/gui2/dialogs/search.py @@ -19,6 +19,7 @@ from calibre.utils.icu import sort_key from calibre.utils.config import tweaks from calibre.utils.date import now from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type box_values = {} last_matchkind = CONTAINS_MATCH @@ -37,7 +38,7 @@ def init_dateop(cb): def current_dateop(cb): - return unicode(cb.itemData(cb.currentIndex()) or '') + return unicode_type(cb.itemData(cb.currentIndex()) or '') def create_msg_label(self): @@ -296,7 +297,7 @@ class SearchDialog(QDialog): return (self.adv_search_string, self.box_search_string, self.date_search_string)[i]() def date_search_string(self): - field = unicode(self.date_field.itemData(self.date_field.currentIndex()) or '') + field = unicode_type(self.date_field.itemData(self.date_field.currentIndex()) or '') op = current_dateop(self.dateop_date) prefix = '%s:%s' % (field, op) if self.sel_date.isChecked(): @@ -312,7 +313,7 @@ class SearchDialog(QDialog): val = self.date_daysago.value() val *= {0:1, 1:7, 2:30, 3:365}[self.date_ago_type.currentIndex()] return '%s%sdaysago' % (prefix, val) - return '%s%s' % (prefix, unicode(self.date_human.itemData(self.date_human.currentIndex()) or '')) + return '%s%s' % (prefix, unicode_type(self.date_human.itemData(self.date_human.currentIndex()) or '')) def adv_search_string(self): mk = self.matchkind.currentIndex() @@ -322,7 +323,7 @@ class SearchDialog(QDialog): self.mc = '=' else: self.mc = '~' - all, any, phrase, none = map(lambda x: unicode(x.text()), + all, any, phrase, none = map(lambda x: unicode_type(x.text()), (self.all, self.any, self.phrase, self.none)) all, any, none = map(self.tokens, (all, any, none)) phrase = phrase.strip() @@ -344,11 +345,11 @@ class SearchDialog(QDialog): return ans def token(self): - txt = unicode(self.text.text()).strip() + txt = unicode_type(self.text.text()).strip() if txt: if self.negate.isChecked(): txt = '!'+txt - tok = self.FIELDS[unicode(self.field.currentText())]+txt + tok = self.FIELDS[unicode_type(self.field.currentText())]+txt if re.search(r'\s', tok): tok = '"%s"'%tok return tok @@ -364,35 +365,35 @@ class SearchDialog(QDialog): ans = [] self.box_last_values = {} - title = unicode(self.title_box.text()).strip() + title = unicode_type(self.title_box.text()).strip() self.box_last_values['title_box'] = title if title: ans.append('title:"' + self.mc + title + '"') - author = unicode(self.authors_box.text()).strip() + author = unicode_type(self.authors_box.text()).strip() self.box_last_values['authors_box'] = author if author: ans.append('author:"' + self.mc + author + '"') - series = unicode(self.series_box.text()).strip() + series = unicode_type(self.series_box.text()).strip() self.box_last_values['series_box'] = series if series: ans.append('series:"' + self.mc + series + '"') - tags = unicode(self.tags_box.text()) + tags = unicode_type(self.tags_box.text()) self.box_last_values['tags_box'] = tags tags = [t.strip() for t in tags.split(',') if t.strip()] if tags: tags = ['tags:"' + self.mc + t + '"' for t in tags] ans.append('(' + ' or '.join(tags) + ')') - general = unicode(self.general_box.text()) + general = unicode_type(self.general_box.text()) self.box_last_values['general_box'] = general - general_index = unicode(self.general_combo.currentText()) + general_index = unicode_type(self.general_combo.currentText()) self.box_last_values['general_index'] = general_index global box_values global last_matchkind box_values = copy.deepcopy(self.box_last_values) last_matchkind = mk if general: - ans.append(unicode(self.general_combo.currentText()) + ':"' + + ans.append(unicode_type(self.general_combo.currentText()) + ':"' + self.mc + general + '"') if ans: return ' and '.join(ans) diff --git a/src/calibre/gui2/dialogs/smartdevice.py b/src/calibre/gui2/dialogs/smartdevice.py index 00323c5ef4..57b5ad55c3 100644 --- a/src/calibre/gui2/dialogs/smartdevice.py +++ b/src/calibre/gui2/dialogs/smartdevice.py @@ -10,6 +10,7 @@ from PyQt5.Qt import (QDialog, QLineEdit, Qt) from calibre.gui2 import error_dialog from calibre.gui2.dialogs.smartdevice_ui import Ui_Dialog from calibre.utils.mdns import get_all_ips +from polyglot.builtins import unicode_type def _cmp_ipaddr(l, r): @@ -115,7 +116,7 @@ class SmartdeviceDialog(QDialog, Ui_Dialog): Qt.Unchecked else QLineEdit.Normal) def accept(self): - port = unicode(self.fixed_port.text()) + port = unicode_type(self.fixed_port.text()) if not port: error_dialog(self, _('Invalid port number'), _('You must provide a port number.'), show=True) @@ -133,13 +134,13 @@ class SmartdeviceDialog(QDialog, Ui_Dialog): return self.device_manager.set_option('smartdevice', 'password', - unicode(self.password_box.text())) + unicode_type(self.password_box.text())) self.device_manager.set_option('smartdevice', 'autostart', self.autostart_box.isChecked()) self.device_manager.set_option('smartdevice', 'use_fixed_port', self.use_fixed_port.isChecked()) self.device_manager.set_option('smartdevice', 'port_number', - unicode(self.fixed_port.text())) + unicode_type(self.fixed_port.text())) message = self.device_manager.start_plugin('smartdevice') @@ -153,4 +154,3 @@ class SmartdeviceDialog(QDialog, Ui_Dialog): self.orig_port_number) else: QDialog.accept(self) - diff --git a/src/calibre/gui2/dialogs/tag_categories.py b/src/calibre/gui2/dialogs/tag_categories.py index d48ae9117f..783a513bec 100644 --- a/src/calibre/gui2/dialogs/tag_categories.py +++ b/src/calibre/gui2/dialogs/tag_categories.py @@ -10,6 +10,7 @@ from calibre.gui2.dialogs.confirm_delete import confirm from calibre.gui2 import error_dialog from calibre.constants import islinux from calibre.utils.icu import sort_key, strcmp +from polyglot.builtins import unicode_type class Item(object): @@ -197,7 +198,7 @@ class TagCategories(QDialog, Ui_TagCategories): def add_category(self): self.save_category() - cat_name = unicode(self.input_box.text()).strip() + cat_name = unicode_type(self.input_box.text()).strip() if cat_name == '': return False comps = [c.strip() for c in cat_name.split('.') if c.strip()] @@ -226,7 +227,7 @@ class TagCategories(QDialog, Ui_TagCategories): def rename_category(self): self.save_category() - cat_name = unicode(self.input_box.text()).strip() + cat_name = unicode_type(self.input_box.text()).strip() if cat_name == '': return False if not self.current_cat_name: @@ -267,7 +268,7 @@ class TagCategories(QDialog, Ui_TagCategories): self.save_category() s = self.category_box.itemText(idx) if s: - self.current_cat_name = unicode(s) + self.current_cat_name = unicode_type(s) else: self.current_cat_name = None self.fill_applied_items() diff --git a/src/calibre/gui2/dialogs/tag_editor.py b/src/calibre/gui2/dialogs/tag_editor.py index 822f898e24..38b6e921d7 100644 --- a/src/calibre/gui2/dialogs/tag_editor.py +++ b/src/calibre/gui2/dialogs/tag_editor.py @@ -8,6 +8,7 @@ from calibre.gui2.dialogs.tag_editor_ui import Ui_TagEditor from calibre.gui2 import question_dialog, error_dialog, gprefs from calibre.constants import islinux from calibre.utils.icu import sort_key, primary_contains +from polyglot.builtins import unicode_type class TagEditor(QDialog, Ui_TagEditor): @@ -103,15 +104,15 @@ class TagEditor(QDialog, Ui_TagEditor): return pos = self.available_tags.verticalScrollBar().value() for item in items: - used = self.db.is_tag_used(unicode(item.text())) \ + used = self.db.is_tag_used(unicode_type(item.text())) \ if self.key is None else \ - self.db.is_item_used_in_multiple(unicode(item.text()), label=self.key) + self.db.is_item_used_in_multiple(unicode_type(item.text()), label=self.key) if used: confirms.append(item) else: deletes.append(item) if confirms: - ct = ', '.join([unicode(item.text()) for item in confirms]) + ct = ', '.join([unicode_type(item.text()) for item in confirms]) if question_dialog(self, _('Are your sure?'), '

'+_('The following tags are used by one or more books. ' 'Are you certain you want to delete them?')+'
'+ct): @@ -119,9 +120,9 @@ class TagEditor(QDialog, Ui_TagEditor): for item in deletes: if self.key is None: - self.db.delete_tag(unicode(item.text())) + self.db.delete_tag(unicode_type(item.text())) else: - bks = self.db.delete_item_from_multiple(unicode(item.text()), + bks = self.db.delete_item_from_multiple(unicode_type(item.text()), label=self.key) self.db.refresh_ids(bks) self.available_tags.takeItem(self.available_tags.row(item)) @@ -135,7 +136,7 @@ class TagEditor(QDialog, Ui_TagEditor): row = max(rows) tags = self._get_applied_tags_box_contents() for item in items: - tag = unicode(item.text()) + tag = unicode_type(item.text()) tags.append(tag) self.available_tags.takeItem(self.available_tags.row(item)) @@ -158,14 +159,14 @@ class TagEditor(QDialog, Ui_TagEditor): def _get_applied_tags_box_contents(self): tags = [] for i in range(0, self.applied_tags.count()): - tags.append(unicode(self.applied_tags.item(i).text())) + tags.append(unicode_type(self.applied_tags.item(i).text())) return tags def unapply_tags(self, item=None): tags = self._get_applied_tags_box_contents() items = self.applied_tags.selectedItems() if item is None else [item] for item in items: - tag = unicode(item.text()) + tag = unicode_type(item.text()) tags.remove(tag) self.available_tags.addItem(tag) @@ -175,7 +176,7 @@ class TagEditor(QDialog, Ui_TagEditor): for tag in tags: self.applied_tags.addItem(tag) - items = [unicode(self.available_tags.item(x).text()) for x in + items = [unicode_type(self.available_tags.item(x).text()) for x in range(self.available_tags.count())] items.sort(key=sort_key) self.available_tags.clear() @@ -187,7 +188,7 @@ class TagEditor(QDialog, Ui_TagEditor): self.filter_tags(self.available_filter_input.text()) def add_tag(self): - tags = unicode(self.add_tag_input.text()).split(self.sep) + tags = unicode_type(self.add_tag_input.text()).split(self.sep) tags_in_box = self._get_applied_tags_box_contents() for tag in tags: tag = tag.strip() @@ -211,10 +212,10 @@ class TagEditor(QDialog, Ui_TagEditor): # filter tags def filter_tags(self, filter_value, which='available_tags'): collection = getattr(self, which) - q = icu_lower(unicode(filter_value)) + q = icu_lower(unicode_type(filter_value)) for i in xrange(collection.count()): # on every available tag item = collection.item(i) - item.setHidden(bool(q and not primary_contains(q, unicode(item.text())))) + item.setHidden(bool(q and not primary_contains(q, unicode_type(item.text())))) def accept(self): self.tags = self._get_applied_tags_box_contents() diff --git a/src/calibre/gui2/dialogs/tag_list_editor.py b/src/calibre/gui2/dialogs/tag_list_editor.py index 1a58316a27..b5fa904af4 100644 --- a/src/calibre/gui2/dialogs/tag_list_editor.py +++ b/src/calibre/gui2/dialogs/tag_list_editor.py @@ -8,6 +8,7 @@ from calibre.gui2.dialogs.tag_list_editor_ui import Ui_TagListEditor from calibre.gui2.dialogs.confirm_delete import confirm from calibre.gui2 import question_dialog, error_dialog, gprefs from calibre.utils.icu import sort_key +from polyglot.builtins import unicode_type class NameTableWidgetItem(QTableWidgetItem): @@ -55,10 +56,10 @@ class NameTableWidgetItem(QTableWidgetItem): QTableWidgetItem.setText(self, txt) def __ge__(self, other): - return sort_key(unicode(self.text())) >= sort_key(unicode(other.text())) + return sort_key(unicode_type(self.text())) >= sort_key(unicode_type(other.text())) def __lt__(self, other): - return sort_key(unicode(self.text())) < sort_key(unicode(other.text())) + return sort_key(unicode_type(self.text())) < sort_key(unicode_type(other.text())) class CountTableWidgetItem(QTableWidgetItem): @@ -230,12 +231,12 @@ class TagListEditor(QDialog, Ui_TagListEditor): tag = item.initial_text() self.all_tags[tag]['cur_name'] = item.text() self.all_tags[tag]['is_deleted'] = item.is_deleted - search_for = icu_lower(unicode(self.search_box.text())) + search_for = icu_lower(unicode_type(self.search_box.text())) if len(search_for) == 0: self.fill_in_table(None, None) result = [] for k in self.ordered_tags: - if search_for in icu_lower(unicode(self.all_tags[k]['cur_name'])): + if search_for in icu_lower(unicode_type(self.all_tags[k]['cur_name'])): result.append(k) self.fill_in_table(result, None) @@ -270,7 +271,7 @@ class TagListEditor(QDialog, Ui_TagListEditor): return if item.text() != item.initial_text(): id_ = int(item.data(Qt.UserRole)) - self.to_rename[id_] = unicode(item.text()) + self.to_rename[id_] = unicode_type(item.text()) orig = self.table.item(item.row(), 2) self.table.blockSignals(True) orig.setData(Qt.DisplayRole, item.initial_text()) @@ -336,13 +337,13 @@ class TagListEditor(QDialog, Ui_TagListEditor): else: to_del.append(item) if to_del: - ct = ', '.join([unicode(item.text()) for item in to_del]) + ct = ', '.join([unicode_type(item.text()) for item in to_del]) if not confirm( '

'+_('Are you sure you want to delete the following items?')+'
'+ct, 'tag_list_editor_delete'): return if to_undel: - ct = ', '.join([unicode(item.text()) for item in to_undel]) + ct = ', '.join([unicode_type(item.text()) for item in to_undel]) if not confirm( '

'+_('Are you sure you want to undelete the following items?')+'
'+ct, 'tag_list_editor_undelete'): diff --git a/src/calibre/gui2/dialogs/template_dialog.py b/src/calibre/gui2/dialogs/template_dialog.py index 8f1dc4a539..0383f047b8 100644 --- a/src/calibre/gui2/dialogs/template_dialog.py +++ b/src/calibre/gui2/dialogs/template_dialog.py @@ -20,6 +20,7 @@ from calibre.ebooks.metadata.book.formatter import SafeFormat from calibre.library.coloring import (displayable_columns, color_row_key) from calibre.gui2 import error_dialog, choose_files, pixmap_to_data from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type class ParenPosition: @@ -134,7 +135,7 @@ class TemplateHighlighter(QSyntaxHighlighter): i = regex.indexIn(text, i + length) if self.generate_paren_positions: - t = unicode(text) + t = unicode_type(text) i = 0 foundQuote = False while i < len(t): @@ -392,15 +393,15 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): def color_to_clipboard(self): app = QApplication.instance() c = app.clipboard() - c.setText(unicode(self.color_name.color)) + c.setText(unicode_type(self.color_name.color)) def icon_to_clipboard(self): app = QApplication.instance() c = app.clipboard() - c.setText(unicode(self.icon_files.currentText())) + c.setText(unicode_type(self.icon_files.currentText())) def textbox_changed(self): - cur_text = unicode(self.textbox.toPlainText()) + cur_text = unicode_type(self.textbox.toPlainText()) if self.last_text != cur_text: self.last_text = cur_text self.highlighter.regenerate_paren_positions() @@ -412,7 +413,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): def text_cursor_changed(self): cursor = self.textbox.textCursor() position = cursor.position() - t = unicode(self.textbox.toPlainText()) + t = unicode_type(self.textbox.toPlainText()) if position > 0 and position <= len(t): block_number = cursor.blockNumber() pos_in_block = cursor.positionInBlock() - 1 @@ -420,7 +421,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): pos_in_block) def function_changed(self, toWhat): - name = unicode(toWhat) + name = unicode_type(toWhat) self.source_code.clear() self.documentation.clear() if name in self.funcs: @@ -431,7 +432,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): self.source_code.setPlainText(self.funcs[name].program_text) def accept(self): - txt = unicode(self.textbox.toPlainText()).rstrip() + txt = unicode_type(self.textbox.toPlainText()).rstrip() if self.coloring: if self.colored_field.currentIndex() == -1: error_dialog(self, _('No column chosen'), @@ -442,12 +443,12 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): _('The template box cannot be empty'), show=True) return - self.rule = (unicode(self.colored_field.itemData( + self.rule = (unicode_type(self.colored_field.itemData( self.colored_field.currentIndex()) or ''), txt) elif self.iconing: - rt = unicode(self.icon_kind.itemData(self.icon_kind.currentIndex()) or '') + rt = unicode_type(self.icon_kind.itemData(self.icon_kind.currentIndex()) or '') self.rule = (rt, - unicode(self.icon_field.itemData( + unicode_type(self.icon_field.itemData( self.icon_field.currentIndex()) or ''), txt) elif self.embleming: diff --git a/src/calibre/gui2/dnd.py b/src/calibre/gui2/dnd.py index a46190351a..2ff0668146 100644 --- a/src/calibre/gui2/dnd.py +++ b/src/calibre/gui2/dnd.py @@ -20,6 +20,7 @@ from calibre.ptempfile import PersistentTemporaryFile from calibre import browser, as_unicode, prints from calibre.gui2 import error_dialog from calibre.utils.imghdr import what +from polyglot.builtins import unicode_type def image_extensions(): @@ -177,7 +178,7 @@ def dnd_has_extension(md, extensions, allow_all_extensions=False): if DEBUG: prints('\nDebugging DND event') for f in md.formats(): - f = unicode(f) + f = unicode_type(f) raw = data_as_string(f, md) prints(f, len(raw), repr(raw[:300]), '\n') print () @@ -207,7 +208,7 @@ def dnd_get_image(md, image_exts=None): ''' if md.hasImage(): for x in md.formats(): - x = unicode(x) + x = unicode_type(x) if x.startswith('image/'): cdata = bytes(md.data(x)) pmap = QPixmap() @@ -319,7 +320,7 @@ def _get_firefox_pair(md, exts, url, fname): def get_firefox_rurl(md, exts): - formats = frozenset([unicode(x) for x in md.formats()]) + formats = frozenset([unicode_type(x) for x in md.formats()]) url = fname = None if 'application/x-moz-file-promise-url' in formats and \ 'application/x-moz-file-promise-dest-filename' in formats: @@ -362,5 +363,3 @@ def get_firefox_rurl(md, exts): def has_firefox_ext(md, exts): return bool(get_firefox_rurl(md, exts)[0]) - - diff --git a/src/calibre/gui2/email.py b/src/calibre/gui2/email.py index 6e54bd8814..f24f131923 100644 --- a/src/calibre/gui2/email.py +++ b/src/calibre/gui2/email.py @@ -28,6 +28,7 @@ from calibre.library.save_to_disk import get_components from calibre.utils.config import tweaks, prefs from calibre.utils.icu import primary_sort_key from calibre.gui2.threaded_jobs import ThreadedJob +from polyglot.builtins import unicode_type class Worker(Thread): @@ -210,7 +211,7 @@ class SelectRecipients(QDialog): # {{{ for i, name in enumerate(('address', 'alias', 'formats', 'subject')): c = i % 2 row = l.rowCount() - c - self.labels[i].setText(unicode(self.labels[i].text()) + ':') + self.labels[i].setText(unicode_type(self.labels[i].text()) + ':') l.addWidget(self.labels[i], row, (2*c)) le = QLineEdit(self) le.setToolTip(tooltips[i]) @@ -232,11 +233,11 @@ class SelectRecipients(QDialog): # {{{ self.init_list() def add_recipient(self): - to = unicode(self.address.text()).strip() + to = unicode_type(self.address.text()).strip() if not to: return error_dialog( self, _('Need address'), _('You must specify an address'), show=True) - formats = ','.join([x.strip().upper() for x in unicode(self.formats.text()).strip().split(',') if x.strip()]) + formats = ','.join([x.strip().upper() for x in unicode_type(self.formats.text()).strip().split(',') if x.strip()]) if not formats: return error_dialog( self, _('Need formats'), _('You must specify at least one format to send'), show=True) @@ -248,11 +249,11 @@ class SelectRecipients(QDialog): # {{{ acc[to] = [formats, False, False] c = email_config() c.set('accounts', acc) - alias = unicode(self.alias.text()).strip() + alias = unicode_type(self.alias.text()).strip() if alias: opts.aliases[to] = alias c.set('aliases', opts.aliases) - subject = unicode(self.subject.text()).strip() + subject = unicode_type(self.subject.text()).strip() if subject: opts.subjects[to] = subject c.set('subjects', opts.subjects) @@ -287,7 +288,7 @@ class SelectRecipients(QDialog): # {{{ ans = [] for i in self.items: if i.checkState() == Qt.Checked: - to = unicode(i.data(Qt.UserRole) or '') + to = unicode_type(i.data(Qt.UserRole) or '') fmts = tuple(x.strip().upper() for x in (opts.accounts[to][0] or '').split(',')) subject = opts.subjects.get(to, '') ans.append((to, fmts, subject)) @@ -408,7 +409,7 @@ class EmailMixin(object): # {{{ from calibre.utils.html2text import html2text texts[-1] += '\n\n' + _('About this book:') + '\n\n' + textwrap.fill(html2text(mi.comments)) prefix = ascii_filename(t+' - '+a) - if not isinstance(prefix, unicode): + if not isinstance(prefix, unicode_type): prefix = prefix.decode(preferred_encoding, 'replace') attachment_names.append(prefix + os.path.splitext(f)[1]) remove = remove_ids if delete_from_library else [] diff --git a/src/calibre/gui2/font_family_chooser.py b/src/calibre/gui2/font_family_chooser.py index 7fb0197866..f30fddc384 100644 --- a/src/calibre/gui2/font_family_chooser.py +++ b/src/calibre/gui2/font_family_chooser.py @@ -17,6 +17,7 @@ from PyQt5.Qt import (QFontInfo, QFontMetrics, Qt, QFont, QFontDatabase, QPen, from calibre.constants import config_dir from calibre.gui2 import choose_files, error_dialog, info_dialog, empty_index +from polyglot.builtins import unicode_type def add_fonts(parent): @@ -112,7 +113,7 @@ class FontFamilyDelegate(QStyledItemDelegate): painter.restore() def do_paint(self, painter, option, index): - text = unicode(index.data(Qt.DisplayRole) or '') + text = unicode_type(index.data(Qt.DisplayRole) or '') font = QFont(option.font) font.setPointSize(QFontInfo(font).pointSize() * 1.5) font2 = QFont(font) @@ -264,7 +265,7 @@ class FontFamilyDialog(QDialog): i = self.view.currentIndex().row() if i < 0: i = 0 - q = icu_lower(unicode(self.search.text())).strip() + q = icu_lower(unicode_type(self.search.text())).strip() if not q: return r = (xrange(i-1, -1, -1) if backwards else xrange(i+1, diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py index 8cae6075de..03faa4c4f0 100644 --- a/src/calibre/gui2/init.py +++ b/src/calibre/gui2/init.py @@ -25,6 +25,7 @@ from calibre.gui2.notify import get_notifier from calibre.gui2.layout_menu import LayoutMenu from calibre.customize.ui import find_plugin from calibre.utils.localization import localize_website_link +from polyglot.builtins import unicode_type _keep_refs = [] @@ -322,7 +323,7 @@ class StatusBar(QStatusBar): # {{{ def show_message(self, msg, timeout=0, show_notification=True): self.showMessage(msg, timeout) if self.notifier is not None and not config['disable_tray_notification'] and show_notification: - if isosx and isinstance(msg, unicode): + if isosx and isinstance(msg, unicode_type): try: msg = msg.encode(preferred_encoding) except UnicodeEncodeError: @@ -343,7 +344,7 @@ class GridViewButton(LayoutButton): # {{{ self.set_state_to_show() self.action_toggle = QAction(self.icon(), _('Toggle') + ' ' + self.label, self) gui.addAction(self.action_toggle) - gui.keyboard.register_shortcut('grid view toggle' + self.label, unicode(self.action_toggle.text()), + gui.keyboard.register_shortcut('grid view toggle' + self.label, unicode_type(self.action_toggle.text()), default_keys=(sc,), action=self.action_toggle) self.action_toggle.triggered.connect(self.toggle) self.action_toggle.changed.connect(self.update_shortcut) @@ -373,7 +374,7 @@ class SearchBarButton(LayoutButton): # {{{ self.set_state_to_hide() self.action_toggle = QAction(self.icon(), _('Toggle') + ' ' + self.label, self) gui.addAction(self.action_toggle) - gui.keyboard.register_shortcut('search bar toggle' + self.label, unicode(self.action_toggle.text()), + gui.keyboard.register_shortcut('search bar toggle' + self.label, unicode_type(self.action_toggle.text()), default_keys=(sc,), action=self.action_toggle) self.action_toggle.triggered.connect(self.toggle) self.action_toggle.changed.connect(self.update_shortcut) @@ -457,14 +458,14 @@ class VLTabs(QTabBar): # {{{ def tab_changed(self, idx): if self.ignore_tab_changed: return - vl = unicode(self.tabData(idx) or '').strip() or None + vl = unicode_type(self.tabData(idx) or '').strip() or None self.gui.apply_virtual_library(vl, update_tabs=False) def tab_moved(self, from_, to): - self.current_db.new_api.set_pref('virt_libs_order', [unicode(self.tabData(i) or '') for i in range(self.count())]) + self.current_db.new_api.set_pref('virt_libs_order', [unicode_type(self.tabData(i) or '') for i in range(self.count())]) def tab_close(self, index): - vl = unicode(self.tabData(index) or '') + vl = unicode_type(self.tabData(index) or '') if vl: # Dont allow closing the All Books tab self.current_db.new_api.set_pref('virt_libs_hidden', list( self.current_db.prefs['virt_libs_hidden']) + [vl]) @@ -540,7 +541,7 @@ class VLTabs(QTabBar): # {{{ m.addAction(_('Unlock virtual library tabs'), self.unlock_tab) i = self.tabAt(ev.pos()) if i > -1: - vl = unicode(self.tabData(i) or '') + vl = unicode_type(self.tabData(i) or '') if vl: m.addSeparator() m.addAction(_('Edit "%s"') % vl, partial(self.gui.do_create_edit, name=vl)) @@ -604,7 +605,7 @@ class LayoutMixin(object): # {{{ self.qv = self.qv.actual_plugin_ self.status_bar = StatusBar(self) - stylename = unicode(self.style().objectName()) + stylename = unicode_type(self.style().objectName()) self.grid_view_button = GridViewButton(self) self.search_bar_button = SearchBarButton(self) self.grid_view_button.toggled.connect(self.toggle_grid_view) diff --git a/src/calibre/gui2/jobs.py b/src/calibre/gui2/jobs.py index 9b45d0be86..9e9d1f4c3f 100644 --- a/src/calibre/gui2/jobs.py +++ b/src/calibre/gui2/jobs.py @@ -30,6 +30,7 @@ from calibre.gui2.threaded_jobs import ThreadedJobServer, ThreadedJob from calibre.gui2.widgets2 import Dialog from calibre.utils.search_query_parser import SearchQueryParser, ParseException from calibre.utils.icu import lower +from polyglot.builtins import unicode_type class AdaptSQP(SearchQueryParser): @@ -557,7 +558,7 @@ class JobsButton(QWidget): # {{{ self.pi.stopAnimation() def jobs(self): - src = unicode(self._jobs.text()) + src = unicode_type(self._jobs.text()) return int(re.search(r'\d+', src).group()) def tray_tooltip(self, num=0): @@ -573,7 +574,7 @@ class JobsButton(QWidget): # {{{ def job_added(self, nnum): jobs = self._jobs - src = unicode(jobs.text()) + src = unicode_type(jobs.text()) num = self.jobs() text = src.replace(str(num), str(nnum)) jobs.setText(text) @@ -582,7 +583,7 @@ class JobsButton(QWidget): # {{{ def job_done(self, nnum): jobs = self._jobs - src = unicode(jobs.text()) + src = unicode_type(jobs.text()) num = self.jobs() text = src.replace(str(num), str(nnum)) jobs.setText(text) diff --git a/src/calibre/gui2/keyboard.py b/src/calibre/gui2/keyboard.py index 5079cdb8ee..ebf8404a87 100644 --- a/src/calibre/gui2/keyboard.py +++ b/src/calibre/gui2/keyboard.py @@ -26,6 +26,7 @@ from calibre.utils.icu import sort_key, lower from calibre.gui2 import error_dialog, info_dialog from calibre.utils.search_query_parser import SearchQueryParser, ParseException from calibre.gui2.search_box import SearchBox2 +from polyglot.builtins import unicode_type ROOT = QModelIndex() @@ -70,7 +71,7 @@ def finalize(shortcuts, custom_keys_map={}): # {{{ keys = [] for x in candidates: ks = QKeySequence(x, QKeySequence.PortableText) - x = unicode(ks.toString(QKeySequence.PortableText)) + x = unicode_type(ks.toString(QKeySequence.PortableText)) if x in seen: if DEBUG: prints('Key %r for shortcut %s is already used by' @@ -282,7 +283,7 @@ class ConfigModel(SearchQueryParser, QAbstractItemModel): sc = node.data if sc['set_to_default']: continue - keys = [unicode(k.toString(k.PortableText)) for k in sc['keys']] + keys = [unicode_type(k.toString(k.PortableText)) for k in sc['keys']] kmap[sc['unique_name']] = keys self.keyboard.config['map'] = kmap @@ -428,11 +429,11 @@ class Editor(QFrame): # {{{ self.default_keys = [QKeySequence(k, QKeySequence.PortableText) for k in shortcut['default_keys']] self.current_keys = list(shortcut['keys']) - default = ', '.join([unicode(k.toString(k.NativeText)) for k in + default = ', '.join([unicode_type(k.toString(k.NativeText)) for k in self.default_keys]) if not default: default = _('None') - current = ', '.join([unicode(k.toString(k.NativeText)) for k in + current = ', '.join([unicode_type(k.toString(k.NativeText)) for k in self.current_keys]) if not current: current = _('None') @@ -490,7 +491,7 @@ class Editor(QFrame): # {{{ dup_desc = self.dup_check(sequence) if dup_desc is not None: error_dialog(self, _('Already assigned'), - unicode(sequence.toString(QKeySequence.NativeText)) + ' ' + _( + unicode_type(sequence.toString(QKeySequence.NativeText)) + ' ' + _( 'already assigned to') + ' ' + dup_desc, show=True) self.clear_clicked(which=which) @@ -509,7 +510,7 @@ class Editor(QFrame): # {{{ ans = [] for which in (1, 2): button = getattr(self, 'button%d'%which) - t = unicode(button.text()) + t = unicode_type(button.text()) if t == _('None'): continue ks = QKeySequence(t, QKeySequence.NativeText) @@ -536,7 +537,7 @@ class Delegate(QStyledItemDelegate): # {{{ elif data.is_shortcut: shortcut = data.data # Shortcut - keys = [unicode(k.toString(k.NativeText)) for k in shortcut['keys']] + keys = [unicode_type(k.toString(k.NativeText)) for k in shortcut['keys']] if not keys: keys = _('None') else: @@ -707,7 +708,7 @@ class ShortcutConfig(QWidget): # {{{ if not idx.isValid(): idx = self._model.index(0, 0) idx = self._model.find_next(idx, - unicode(self.search.currentText())) + unicode_type(self.search.currentText())) self.highlight_index(idx) def find_previous(self, *args): @@ -715,7 +716,7 @@ class ShortcutConfig(QWidget): # {{{ if not idx.isValid(): idx = self._model.index(0, 0) idx = self._model.find_next(idx, - unicode(self.search.currentText()), backwards=True) + unicode_type(self.search.currentText()), backwards=True) self.highlight_index(idx) def highlight_group(self, group_name): diff --git a/src/calibre/gui2/languages.py b/src/calibre/gui2/languages.py index 377cdfd00d..1f7ce4f0fd 100644 --- a/src/calibre/gui2/languages.py +++ b/src/calibre/gui2/languages.py @@ -11,6 +11,7 @@ from calibre.gui2 import gui_prefs from calibre.gui2.complete2 import EditWithComplete from calibre.utils.localization import lang_map_for_ui from calibre.utils.icu import sort_key, lower +from polyglot.builtins import unicode_type class LanguagesEdit(EditWithComplete): @@ -53,7 +54,7 @@ class LanguagesEdit(EditWithComplete): @property def vals(self): - raw = unicode(self.lineEdit().text()) + raw = unicode_type(self.lineEdit().text()) for k, v in self.comma_map.iteritems(): raw = raw.replace(k, v) parts = [x.strip() for x in raw.split(',')] diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py index 095118904a..6c902fb9c8 100644 --- a/src/calibre/gui2/layout.py +++ b/src/calibre/gui2/layout.py @@ -18,6 +18,7 @@ from calibre.gui2.bars import BarsManager from calibre.gui2.widgets2 import RightClickButton from calibre.utils.config_base import tweaks from calibre import human_readable +from polyglot.builtins import unicode_type class LocationManager(QObject): # {{{ @@ -128,7 +129,7 @@ class LocationManager(QObject): # {{{ had_device = self.has_device if cp is None: cp = (None, None) - if isinstance(cp, (str, unicode)): + if isinstance(cp, (str, unicode_type)): cp = (cp, None) if len(fs) < 3: fs = list(fs) + [0] diff --git a/src/calibre/gui2/library/alternate_views.py b/src/calibre/gui2/library/alternate_views.py index 5b8c8bd1c8..fe7246068f 100644 --- a/src/calibre/gui2/library/alternate_views.py +++ b/src/calibre/gui2/library/alternate_views.py @@ -30,6 +30,7 @@ from calibre.gui2 import gprefs, config, rating_font, empty_index from calibre.gui2.gestures import GestureManager from calibre.gui2.library.caches import CoverCache, ThumbnailCache from calibre.utils.config import prefs, tweaks +from polyglot.builtins import unicode_type CM_TO_INCH = 0.393701 CACHE_FORMAT = 'PPM' @@ -242,7 +243,7 @@ def paths_from_event(self, event): md = event.mimeData() if md.hasFormat('text/uri-list') and not \ md.hasFormat('application/calibre+from_library'): - urls = [unicode(u.toLocalFile()) for u in md.urls()] + urls = [unicode_type(u.toLocalFile()) for u in md.urls()] return [u for u in urls if os.path.splitext(u)[1] and os.path.exists(u)] @@ -463,7 +464,7 @@ class CoverDelegate(QStyledItemDelegate): if fm and fm['datatype'] == 'rating': ans = rating_to_stars(val, fm['display'].get('allow_half_stars', False)) is_stars = True - return ('' if ans is None else unicode(ans)), is_stars + return ('' if ans is None else unicode_type(ans)), is_stars except Exception: if DEBUG: import traceback diff --git a/src/calibre/gui2/library/delegates.py b/src/calibre/gui2/library/delegates.py index 430793aab7..7c91eaec3b 100644 --- a/src/calibre/gui2/library/delegates.py +++ b/src/calibre/gui2/library/delegates.py @@ -26,6 +26,7 @@ from calibre.gui2.dialogs.comments_dialog import CommentsDialog, PlainTextDialog from calibre.gui2.dialogs.template_dialog import TemplateDialog from calibre.gui2.dialogs.tag_editor import TagEditor from calibre.gui2.languages import LanguagesEdit +from polyglot.builtins import unicode_type class UpdateEditorGeometry(object): @@ -193,7 +194,7 @@ def get_val_for_textlike_columns(index_): ct = '' else: ct = index_.data(Qt.DisplayRole) or '' - return unicode(ct) + return unicode_type(ct) # }}} @@ -611,7 +612,7 @@ class CcEnumDelegate(QStyledItemDelegate, UpdateEditorGeometry): # {{{ return editor def setModelData(self, editor, model, index): - val = unicode(editor.currentText()) + val = unicode_type(editor.currentText()) if not val: val = None model.setData(index, (val), Qt.EditRole) diff --git a/src/calibre/gui2/library/models.py b/src/calibre/gui2/library/models.py index 6154e6ca31..e5d3f028ec 100644 --- a/src/calibre/gui2/library/models.py +++ b/src/calibre/gui2/library/models.py @@ -30,6 +30,7 @@ from calibre.constants import filesystem_encoding, DEBUG, config_dir from calibre.gui2.library import DEFAULT_SORT from calibre.utils.localization import calibre_langcode_to_name from calibre.library.coloring import color_row_key +from polyglot.builtins import unicode_type Counts = namedtuple('Counts', 'library_total total current') @@ -942,7 +943,7 @@ class BooksModel(QAbstractTableModel): # {{{ cc = self.custom_columns[self.column_map[col]]['display'] colors = cc.get('enum_colors', []) values = cc.get('enum_values', []) - txt = unicode(index.data(Qt.DisplayRole) or '') + txt = unicode_type(index.data(Qt.DisplayRole) or '') if len(colors) > 0 and txt in values: try: color = QColor(colors[values.index(txt)]) @@ -1055,10 +1056,10 @@ class BooksModel(QAbstractTableModel): # {{{ label=self.db.field_metadata.key_to_label(colhead) s_index = None if typ in ('text', 'comments'): - val = unicode(value or '').strip() + val = unicode_type(value or '').strip() val = val if val else None elif typ == 'enumeration': - val = unicode(value or '').strip() + val = unicode_type(value or '').strip() if not val: val = None elif typ == 'bool': @@ -1069,7 +1070,7 @@ class BooksModel(QAbstractTableModel): # {{{ if value == 0: val = '0' else: - val = unicode(value or '').strip() + val = unicode_type(value or '').strip() if not val: val = None elif typ == 'datetime': @@ -1081,7 +1082,7 @@ class BooksModel(QAbstractTableModel): # {{{ return False val = qt_to_dt(val, as_utc=False) elif typ == 'series': - val = unicode(value or '').strip() + val = unicode_type(value or '').strip() if val: pat = re.compile(r'\[([.0-9]+)\]') match = pat.search(val) @@ -1095,7 +1096,7 @@ class BooksModel(QAbstractTableModel): # {{{ s_index = self.db.get_next_cc_series_num_for(val, label=label, num=None) elif typ == 'composite': - tmpl = unicode(value or '').strip() + tmpl = unicode_type(value or '').strip() disp = cc['display'] disp['composite_template'] = tmpl self.db.set_custom_column_metadata(cc['colnum'], display=disp, @@ -1151,7 +1152,7 @@ class BooksModel(QAbstractTableModel): # {{{ return False val = (int(value) if column == 'rating' else value if column in ('timestamp', 'pubdate') - else re.sub(u'\\s', u' ', unicode(value or '').strip())) + else re.sub(u'\\s', u' ', unicode_type(value or '').strip())) id = self.db.id(row) books_to_refresh = {id} if column == 'rating': @@ -1714,7 +1715,7 @@ class DeviceBooksModel(BooksModel): # {{{ cname = self.column_map[col] if cname in ('size', 'timestamp', 'inlibrary'): return False - val = unicode(value or '').strip() + val = unicode_type(value or '').strip() idx = self.map[row] if cname == 'collections': tags = [i.strip() for i in val.split(',')] diff --git a/src/calibre/gui2/library/views.py b/src/calibre/gui2/library/views.py index d247ef3617..dca3c9e050 100644 --- a/src/calibre/gui2/library/views.py +++ b/src/calibre/gui2/library/views.py @@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en' import itertools, operator from functools import partial -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from collections import OrderedDict from PyQt5.Qt import ( @@ -73,7 +73,7 @@ class HeaderView(QHeaderView): # {{{ opt.orientation = self.orientation() opt.fontMetrics = self.fm model = self.parent().model() - opt.text = unicode(model.headerData(logical_index, opt.orientation, Qt.DisplayRole) or '') + opt.text = unicode_type(model.headerData(logical_index, opt.orientation, Qt.DisplayRole) or '') if opt.orientation == Qt.Vertical: try: val = model.headerData(logical_index, opt.orientation, Qt.DecorationRole) @@ -100,7 +100,7 @@ class HeaderView(QHeaderView): # {{{ if self.isSortIndicatorShown() and self.sortIndicatorSection() == logical_index: opt.sortIndicator = QStyleOptionHeader.SortDown if self.sortIndicatorOrder() == Qt.AscendingOrder else QStyleOptionHeader.SortUp margin += style.pixelMetric(style.PM_HeaderMarkSize, None, self) - opt.text = unicode(model.headerData(logical_index, opt.orientation, Qt.DisplayRole) or '') + opt.text = unicode_type(model.headerData(logical_index, opt.orientation, Qt.DisplayRole) or '') if self.textElideMode() != Qt.ElideNone: opt.text = opt.fontMetrics.elidedText(opt.text, Qt.ElideRight, rect.width() - margin) if self.isEnabled(): @@ -465,7 +465,7 @@ class BooksView(QTableView): # {{{ ans.addSeparator() if hidden_cols: m = ans.addMenu(_('Show column')) - hcols = [(hcol, unicode(self.model().headerData(hidx, Qt.Horizontal, Qt.DisplayRole) or '')) for hcol, hidx in hidden_cols.iteritems()] + hcols = [(hcol, unicode_type(self.model().headerData(hidx, Qt.Horizontal, Qt.DisplayRole) or '')) for hcol, hidx in hidden_cols.iteritems()] hcols.sort(key=lambda x: primary_sort_key(x[1])) for hcol, hname in hcols: m.addAction(hname, partial(handler, action='show', column=hcol)) @@ -484,7 +484,7 @@ class BooksView(QTableView): # {{{ col = None if idx > -1 and idx < len(self.column_map): col = self.column_map[idx] - name = unicode(self.model().headerData(idx, Qt.Horizontal, Qt.DisplayRole) or '') + name = unicode_type(self.model().headerData(idx, Qt.Horizontal, Qt.DisplayRole) or '') view.column_header_context_menu = self.create_context_menu(col, name, view) has_context_menu = hasattr(view, 'column_header_context_menu') if self.is_library_view and has_context_menu: @@ -625,7 +625,7 @@ class BooksView(QTableView): # {{{ def write_state(self, state): db = getattr(self.model(), 'db', None) - name = unicode(self.objectName()) + name = unicode_type(self.objectName()) if name and db is not None: db.new_api.set_pref(name + ' books view state', state) @@ -740,7 +740,7 @@ class BooksView(QTableView): # {{{ def get_old_state(self): ans = None - name = unicode(self.objectName()) + name = unicode_type(self.objectName()) if name: name += ' books view state' db = getattr(self.model(), 'db', None) @@ -1308,14 +1308,14 @@ class DeviceBooksView(BooksView): # {{{ def get_old_state(self): ans = None - name = unicode(self.objectName()) + name = unicode_type(self.objectName()) if name: name += ' books view state' ans = gprefs.get(name, None) return ans def write_state(self, state): - name = unicode(self.objectName()) + name = unicode_type(self.objectName()) if name: gprefs.set(name + ' books view state', state) diff --git a/src/calibre/gui2/linux_file_dialogs.py b/src/calibre/gui2/linux_file_dialogs.py index b834e079fc..a012ae25c4 100644 --- a/src/calibre/gui2/linux_file_dialogs.py +++ b/src/calibre/gui2/linux_file_dialogs.py @@ -11,7 +11,7 @@ import sys import time from threading import Thread -from polyglot.builtins import reraise +from polyglot.builtins import reraise, unicode_type from PyQt5.Qt import QEventLoop from calibre import force_unicode @@ -84,7 +84,7 @@ def save_initial_dir(name, title, ans, no_save_dir, is_file=False): def encode_arg(title): - if isinstance(title, unicode): + if isinstance(title, unicode_type): try: title = title.encode(preferred_encoding) except UnicodeEncodeError: diff --git a/src/calibre/gui2/lrf_renderer/main.py b/src/calibre/gui2/lrf_renderer/main.py index f1c62bc417..985babf440 100644 --- a/src/calibre/gui2/lrf_renderer/main.py +++ b/src/calibre/gui2/lrf_renderer/main.py @@ -17,6 +17,7 @@ from calibre.gui2.lrf_renderer.config_ui import Ui_ViewerConfig from calibre.gui2.main_window import MainWindow from calibre.gui2.lrf_renderer.document import Document from calibre.gui2.search_box import SearchBox2 +from polyglot.builtins import unicode_type class RenderWorker(QThread): @@ -200,7 +201,7 @@ class Main(MainWindow, Ui_MainWindow): print('Error rendering document', file=sys.stderr) print(exception, file=sys.stderr) print(self.renderer.formatted_traceback, file=sys.stderr) - msg = u'

%s: '%(exception.__class__.__name__,) + unicode(str(exception), 'utf8', 'replace') + u'

' + msg = u'

%s: '%(exception.__class__.__name__,) + unicode_type(str(exception), 'utf8', 'replace') + u'

' msg += u'

Failed to render document

' msg += u'

Detailed traceback:

'
             msg += self.renderer.formatted_traceback + '
' diff --git a/src/calibre/gui2/lrf_renderer/text.py b/src/calibre/gui2/lrf_renderer/text.py index 3bcbe21b1e..8e30c0162c 100644 --- a/src/calibre/gui2/lrf_renderer/text.py +++ b/src/calibre/gui2/lrf_renderer/text.py @@ -10,6 +10,7 @@ from PyQt5.Qt import ( from calibre.ebooks.lrf.fonts import LIBERATION_FONT_MAP from calibre.ebooks.BeautifulSoup import Tag from calibre.ebooks.hyphenate import hyphenate_word +from polyglot.builtins import unicode_type WEIGHT_MAP = lambda wt : int((wt/10.)-1) NULL = lambda a, b: a @@ -533,12 +534,12 @@ class Line(QGraphicsItem): while True: word = words.next() word.highlight = False - if tokens[0] in unicode(word.string).lower(): + if tokens[0] in unicode_type(word.string).lower(): matches.append(word) for c in range(1, len(tokens)): word = words.next() print(tokens[c], word.string) - if tokens[c] not in unicode(word.string): + if tokens[c] not in unicode_type(word.string): return None matches.append(word) for w in matches: @@ -561,11 +562,11 @@ class Line(QGraphicsItem): if isinstance(tok, (int, float)): s += ' ' elif isinstance(tok, Word): - s += unicode(tok.string) + s += unicode_type(tok.string) return s def __str__(self): - return unicode(self).encode('utf-8') + return unicode_type(self).encode('utf-8') class Word(object): diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 9f15f8de68..99bcc5c4b4 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -28,6 +28,7 @@ from calibre.utils.config import dynamic, prefs from calibre.utils.ipc import RC, gui_socket_address from calibre.utils.lock import singleinstance from calibre.utils.monotonic import monotonic +from polyglot.builtins import unicode_type if iswindows: winutil = plugins['winutil'][0] @@ -129,7 +130,7 @@ def get_default_library_path(): fname = _('Calibre Library') if iswindows: fname = 'Calibre Library' - if isinstance(fname, unicode): + if isinstance(fname, unicode_type): try: fname = fname.encode(filesystem_encoding) except: @@ -149,7 +150,7 @@ def get_library_path(gui_runner): base = os.path.expanduser('~') if not base or not os.path.exists(base): from PyQt5.Qt import QDir - base = unicode(QDir.homePath()).replace('/', os.sep) + base = unicode_type(QDir.homePath()).replace('/', os.sep) candidate = gui_runner.choose_dir(base) if not candidate: candidate = os.path.join(base, 'Calibre Library') @@ -583,6 +584,6 @@ if __name__ == '__main__': log = open(logfile).read().decode('utf-8', 'ignore') d = QErrorMessage() d.showMessage(('Error:%s
Traceback:
' - '%sLog:
%s')%(unicode(err), - unicode(tb).replace('\n', '
'), + '%sLog:
%s')%(unicode_type(err), + unicode_type(tb).replace('\n', '
'), log.replace('\n', '
'))) diff --git a/src/calibre/gui2/main_window.py b/src/calibre/gui2/main_window.py index c0cc2c80b1..be4c90c7a8 100644 --- a/src/calibre/gui2/main_window.py +++ b/src/calibre/gui2/main_window.py @@ -12,6 +12,7 @@ from PyQt5.Qt import (QMainWindow, QTimer, QAction, QMenu, QMenuBar, QIcon, from calibre.utils.config import OptionParser from calibre.gui2 import error_dialog from calibre import prints +from polyglot.builtins import unicode_type def option_parser(usage='''\ @@ -144,7 +145,7 @@ class MainWindow(QMainWindow): prints(value.locking_debug_msg, file=sio) fe = sio.getvalue() prints(fe, file=sys.stderr) - msg = '%s:'%type.__name__ + unicode(str(value), 'utf8', 'replace') + msg = '%s:'%type.__name__ + unicode_type(str(value), 'utf8', 'replace') error_dialog(self, _('Unhandled exception'), msg, det_msg=fe, show=True) except BaseException: diff --git a/src/calibre/gui2/metadata/basic_widgets.py b/src/calibre/gui2/metadata/basic_widgets.py index 2b41ac384e..0cacf6f85a 100644 --- a/src/calibre/gui2/metadata/basic_widgets.py +++ b/src/calibre/gui2/metadata/basic_widgets.py @@ -41,6 +41,7 @@ from calibre.ptempfile import PersistentTemporaryFile, SpooledTemporaryFile from calibre.gui2.languages import LanguagesEdit as LE from calibre.db import SPOOL_SIZE from calibre.ebooks.oeb.polish.main import SUPPORTED as EDIT_SUPPORTED +from polyglot.builtins import unicode_type OK_COLOR = 'rgba(0, 255, 0, 12%)' ERR_COLOR = 'rgba(255, 0, 0, 12%)' @@ -228,7 +229,7 @@ class TitleEdit(EnLineEdit, ToMetadataMixin): def current_val(self): def fget(self): - title = clean_text(unicode(self.text())) + title = clean_text(unicode_type(self.text())) if not title: title = self.get_default() return title.strip() @@ -419,7 +420,7 @@ class AuthorsEdit(EditWithComplete, ToMetadataMixin): def current_val(self): def fget(self): - au = clean_text(unicode(self.text())) + au = clean_text(unicode_type(self.text())) if not au: au = self.get_default() return string_to_authors(au) @@ -488,7 +489,7 @@ class AuthorSortEdit(EnLineEdit, ToMetadataMixin): def current_val(self): def fget(self): - return clean_text(unicode(self.text())) + return clean_text(unicode_type(self.text())) def fset(self, val): if not val: @@ -510,7 +511,7 @@ class AuthorSortEdit(EnLineEdit, ToMetadataMixin): return self.db.new_api.author_sort_from_authors(authors, key_func=lambda x: x) def update_state(self, *args): - au = unicode(self.authors_edit.text()) + au = unicode_type(self.authors_edit.text()) au = re.sub(r'\s+et al\.$', '', au) au = self.author_sort_from_authors(string_to_authors(au)) @@ -537,13 +538,13 @@ class AuthorSortEdit(EnLineEdit, ToMetadataMixin): self.authors_edit.current_val = ans def auto_generate(self, *args): - au = unicode(self.authors_edit.text()) + au = unicode_type(self.authors_edit.text()) au = re.sub(r'\s+et al\.$', '', au).strip() authors = string_to_authors(au) self.current_val = self.author_sort_from_authors(authors) def author_to_sort(self, *args): - au = unicode(self.authors_edit.text()) + au = unicode_type(self.authors_edit.text()) au = re.sub(r'\s+et al\.$', '', au).strip() if au: self.current_val = au @@ -616,7 +617,7 @@ class SeriesEdit(EditWithComplete, ToMetadataMixin): def current_val(self): def fget(self): - return clean_text(unicode(self.currentText())) + return clean_text(unicode_type(self.currentText())) def fset(self, val): if not val: @@ -1392,7 +1393,7 @@ class TagsEdit(EditWithComplete, ToMetadataMixin): # {{{ @dynamic_property def current_val(self): def fget(self): - return [clean_text(x) for x in unicode(self.text()).split(',')] + return [clean_text(x) for x in unicode_type(self.text()).split(',')] def fset(self, val): if not val: @@ -1564,7 +1565,7 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin): @dynamic_property def current_val(self): def fget(self): - raw = unicode(self.text()).strip() + raw = unicode_type(self.text()).strip() parts = [clean_text(x) for x in raw.split(',')] ans = {} for x in parts: @@ -1638,14 +1639,14 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin): if prefix == 'isbn': self.paste_isbn() else: - text = unicode(QApplication.clipboard().text()).strip() + text = unicode_type(QApplication.clipboard().text()).strip() if text: vals = self.current_val vals[prefix] = text self.current_val = vals def paste_isbn(self): - text = unicode(QApplication.clipboard().text()).strip() + text = unicode_type(QApplication.clipboard().text()).strip() if not text or not check_isbn(text): d = ISBNDialog(self, text) if not d.exec_(): @@ -1665,7 +1666,7 @@ class IdentifiersEdit(QLineEdit, ToMetadataMixin): def parse_clipboard_for_identifier(self): from calibre.ebooks.metadata.sources.prefs import msprefs from calibre.utils.formatter import EvalFormatter - text = unicode(QApplication.clipboard().text()).strip() + text = unicode_type(QApplication.clipboard().text()).strip() if not text: return False @@ -1733,7 +1734,7 @@ class ISBNDialog(QDialog): # {{{ self.resize(sz) def accept(self): - isbn = unicode(self.line_edit.text()) + isbn = unicode_type(self.line_edit.text()) if not check_isbn(isbn): return error_dialog(self, _('Invalid ISBN'), _('The ISBN you entered is not valid. Try again.'), @@ -1741,7 +1742,7 @@ class ISBNDialog(QDialog): # {{{ QDialog.accept(self) def checkText(self, txt): - isbn = unicode(txt) + isbn = unicode_type(txt) if not isbn: col = 'none' extra = '' @@ -1755,7 +1756,7 @@ class ISBNDialog(QDialog): # {{{ self.line_edit.setStyleSheet(INDICATOR_SHEET % col) def text(self): - return check_isbn(unicode(self.line_edit.text())) + return check_isbn(unicode_type(self.line_edit.text())) # }}} @@ -1781,7 +1782,7 @@ class PublisherEdit(EditWithComplete, ToMetadataMixin): # {{{ def current_val(self): def fget(self): - return clean_text(unicode(self.currentText())) + return clean_text(unicode_type(self.currentText())) def fset(self, val): if not val: diff --git a/src/calibre/gui2/metadata/config.py b/src/calibre/gui2/metadata/config.py index c4a68e4d04..2667d4a966 100644 --- a/src/calibre/gui2/metadata/config.py +++ b/src/calibre/gui2/metadata/config.py @@ -14,6 +14,7 @@ from PyQt5.Qt import (QWidget, QGridLayout, QGroupBox, QListView, Qt, QSpinBox, from calibre.gui2.preferences.metadata_sources import FieldsModel as FM from calibre.utils.icu import sort_key +from polyglot.builtins import unicode_type class FieldsModel(FM): # {{{ @@ -126,10 +127,10 @@ class ConfigWidget(QWidget): if isinstance(w, (QSpinBox, QDoubleSpinBox)): val = w.value() elif isinstance(w, QLineEdit): - val = unicode(w.text()) + val = unicode_type(w.text()) elif isinstance(w, QCheckBox): val = w.isChecked() elif isinstance(w, QComboBox): idx = w.currentIndex() - val = unicode(w.itemData(idx) or '') + val = unicode_type(w.itemData(idx) or '') self.plugin.prefs[w.opt.name] = val diff --git a/src/calibre/gui2/metadata/diff.py b/src/calibre/gui2/metadata/diff.py index db442d1936..01606711ce 100644 --- a/src/calibre/gui2/metadata/diff.py +++ b/src/calibre/gui2/metadata/diff.py @@ -9,7 +9,7 @@ __copyright__ = '2013, Kovid Goyal ' import os, weakref from collections import OrderedDict, namedtuple from functools import partial -from polyglot.builtins import zip +from polyglot.builtins import zip, unicode_type from PyQt5.Qt import ( QDialog, QWidget, QGridLayout, QLabel, QToolButton, QIcon, @@ -52,7 +52,7 @@ class LineEdit(EditWithComplete): @dynamic_property def value(self): def fget(self): - val = unicode(self.text()).strip() + val = unicode_type(self.text()).strip() ism = self.metadata['is_multiple'] if ism: if not val: @@ -88,7 +88,7 @@ class LineEdit(EditWithComplete): @dynamic_property def current_val(self): def fget(self): - return unicode(self.text()) + return unicode_type(self.text()) def fset(self, val): self.setText(val) @@ -212,7 +212,7 @@ class SeriesEdit(LineEdit): self.setCursorPosition(0) def to_mi(self, mi): - val = unicode(self.text()).strip() + val = unicode_type(self.text()).strip() try: series_index = float(val.rpartition('[')[-1].rstrip(']').strip()) except: diff --git a/src/calibre/gui2/metadata/pdf_covers.py b/src/calibre/gui2/metadata/pdf_covers.py index 920628259c..5b9ce0129b 100644 --- a/src/calibre/gui2/metadata/pdf_covers.py +++ b/src/calibre/gui2/metadata/pdf_covers.py @@ -25,6 +25,7 @@ from calibre.ebooks.metadata.pdf import page_images from calibre.gui2 import error_dialog, file_icon_provider from calibre.ptempfile import PersistentTemporaryDirectory from calibre.gui2.progress_indicator import WaitLayout +from polyglot.builtins import unicode_type class CoverDelegate(QStyledItemDelegate): @@ -88,9 +89,9 @@ class PDFCovers(QDialog): @property def cover_path(self): for item in self.covers.selectedItems(): - return unicode(item.data(Qt.UserRole) or '') + return unicode_type(item.data(Qt.UserRole) or '') if self.covers.count() > 0: - return unicode(self.covers.item(0).data(Qt.UserRole) or '') + return unicode_type(self.covers.item(0).data(Qt.UserRole) or '') def cleanup(self): try: diff --git a/src/calibre/gui2/metadata/single_download.py b/src/calibre/gui2/metadata/single_download.py index 1b3a188517..ed3ed1cd04 100644 --- a/src/calibre/gui2/metadata/single_download.py +++ b/src/calibre/gui2/metadata/single_download.py @@ -40,6 +40,7 @@ from calibre import force_unicode from calibre.utils.config import tweaks from calibre.utils.ipc.simple_worker import fork_job, WorkerError from calibre.ptempfile import TemporaryDirectory +from polyglot.builtins import unicode_type # }}} @@ -153,7 +154,7 @@ class ResultsModel(QAbstractTableModel): # {{{ def data_as_text(self, book, col): if col == 0: - return unicode(book.gui_rank+1) + return unicode_type(book.gui_rank+1) if col == 1: t = book.title if book.title else _('Unknown') a = authors_to_string(book.authors) if book.authors else '' @@ -343,12 +344,12 @@ class Comments(QWebView): # {{{ if col.isValid(): col = col.toRgb() if col.isValid(): - ans = unicode(col.name()) + ans = unicode_type(col.name()) return ans fi = QFontInfo(QApplication.font(self.parent())) f = fi.pixelSize()+1+int(tweaks['change_book_details_font_size_by']) - fam = unicode(fi.family()).strip().replace('"', '') + fam = unicode_type(fi.family()).strip().replace('"', '') if not fam: fam = 'sans-serif' @@ -513,7 +514,7 @@ class IdentifyWidget(QWidget): # {{{ if 'isbn' in identifiers: simple_desc += 'ISBN: %s' % identifiers['isbn'] self.query.setText(simple_desc) - self.log(unicode(self.query.text())) + self.log(unicode_type(self.query.text())) self.worker = IdentifyWorker(self.log, self.abort, title, authors, identifiers, self.caches) @@ -842,7 +843,7 @@ class CoversView(QListView): # {{{ pmap = self.model().cc if pmap is not None: from calibre.gui2.viewer.image_popup import ImageView - d = ImageView(self, pmap, unicode(idx.data(Qt.DisplayRole) or ''), geom_name='metadata_download_cover_popup_geom') + d = ImageView(self, pmap, unicode_type(idx.data(Qt.DisplayRole) or ''), geom_name='metadata_download_cover_popup_geom') d(use_exec=True) def copy_cover(self): diff --git a/src/calibre/gui2/notify.py b/src/calibre/gui2/notify.py index ae06954641..779ada9a62 100644 --- a/src/calibre/gui2/notify.py +++ b/src/calibre/gui2/notify.py @@ -10,6 +10,7 @@ __docformat__ = 'restructuredtext en' import time from calibre import prints from calibre.constants import islinux, isosx, get_osx_version, DEBUG +from polyglot.builtins import unicode_type class Notifier(object): @@ -106,7 +107,7 @@ class QtNotifier(Notifier): try: hide = False try: - if not isinstance(body, unicode): + if not isinstance(body, unicode_type): body = body.decode('utf-8') if isosx and not self.systray.isVisible(): self.systray.show() @@ -144,7 +145,7 @@ class AppleNotifier(Notifier): def notify(self, body, summary): def encode(x): - if isinstance(x, unicode): + if isinstance(x, unicode_type): x = x.encode('utf-8') return x diff --git a/src/calibre/gui2/preferences/__init__.py b/src/calibre/gui2/preferences/__init__.py index 833d2dff80..4b87413192 100644 --- a/src/calibre/gui2/preferences/__init__.py +++ b/src/calibre/gui2/preferences/__init__.py @@ -14,6 +14,7 @@ from PyQt5.Qt import (QWidget, pyqtSignal, QCheckBox, QAbstractSpinBox, from calibre.customize.ui import preferences_plugins from calibre.utils.config import ConfigProxy from calibre.gui2.complete2 import EditWithComplete +from polyglot.builtins import unicode_type class AbortCommit(Exception): @@ -118,15 +119,15 @@ class Setting(object): raise ValueError('Unknown data type %s' % self.gui_obj.__class__) if isinstance(self.config_obj, ConfigProxy) and \ - not unicode(self.gui_obj.toolTip()): + not unicode_type(self.gui_obj.toolTip()): h = self.config_obj.help(self.name) if h: self.gui_obj.setToolTip(h) - tt = unicode(self.gui_obj.toolTip()) + tt = unicode_type(self.gui_obj.toolTip()) if tt: - if not unicode(self.gui_obj.whatsThis()): + if not unicode_type(self.gui_obj.whatsThis()): self.gui_obj.setWhatsThis(tt) - if not unicode(self.gui_obj.statusTip()): + if not unicode_type(self.gui_obj.statusTip()): self.gui_obj.setStatusTip(tt) tt = '\n'.join(textwrap.wrap(tt, 70)) self.gui_obj.setToolTip(tt) @@ -194,17 +195,17 @@ class Setting(object): elif self.datatype == 'number': val = self.gui_obj.value() elif self.datatype == 'string': - val = unicode(self.gui_obj.text()).strip() + val = unicode_type(self.gui_obj.text()).strip() if self.empty_string_is_None and not val: val = None elif self.datatype == 'choice': if isinstance(self.gui_obj, EditWithComplete): - val = unicode(self.gui_obj.text()) + val = unicode_type(self.gui_obj.text()) else: idx = self.gui_obj.currentIndex() if idx < 0: idx = 0 - val = unicode(self.gui_obj.itemData(idx) or '') + val = unicode_type(self.gui_obj.itemData(idx) or '') return val @@ -217,7 +218,7 @@ class CommaSeparatedList(Setting): self.gui_obj.setText(x) def get_gui_val(self): - val = unicode(self.gui_obj.text()).strip() + val = unicode_type(self.gui_obj.text()).strip() ans = [] if val: ans = [x.strip() for x in val.split(',')] diff --git a/src/calibre/gui2/preferences/adding.py b/src/calibre/gui2/preferences/adding.py index 2bdc2c1b5d..d2ae8f547f 100644 --- a/src/calibre/gui2/preferences/adding.py +++ b/src/calibre/gui2/preferences/adding.py @@ -16,6 +16,7 @@ from calibre.utils.config import prefs from calibre.gui2.widgets import FilenamePattern from calibre.gui2.auto_add import AUTO_ADDED from calibre.gui2 import gprefs, choose_dir, error_dialog, question_dialog +from polyglot.builtins import unicode_type class ConfigWidget(ConfigWidgetBase, Ui_Form): @@ -131,7 +132,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): viewer = self.opt_blocked_auto_formats for i in range(viewer.count()): if viewer.item(i).checkState() == Qt.Checked: - fmts.append(unicode(viewer.item(i).text())) + fmts.append(unicode_type(viewer.item(i).text())) return fmts # }}} @@ -144,7 +145,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.add_filter_rules = [] def commit(self): - path = unicode(self.opt_auto_add_path.text()).strip() + path = unicode_type(self.opt_auto_add_path.text()).strip() if path != gprefs['auto_add_path']: if path: path = os.path.abspath(path) diff --git a/src/calibre/gui2/preferences/behavior.py b/src/calibre/gui2/preferences/behavior.py index 6f7e56596a..b9a1fcfd47 100644 --- a/src/calibre/gui2/preferences/behavior.py +++ b/src/calibre/gui2/preferences/behavior.py @@ -18,6 +18,7 @@ from calibre.ebooks import BOOK_EXTENSIONS from calibre.ebooks.oeb.iterator import is_supported from calibre.constants import iswindows from calibre.utils.icu import sort_key +from polyglot.builtins import unicode_type class OutputFormatSetting(Setting): @@ -83,7 +84,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): def commit(self): input_map = prefs['input_format_order'] - input_cols = [unicode(self.opt_input_order.item(i).data(Qt.UserRole) or '') for + input_cols = [unicode_type(self.opt_input_order.item(i).data(Qt.UserRole) or '') for i in range(self.opt_input_order.count())] if input_map != input_cols: prefs['input_format_order'] = input_cols @@ -128,7 +129,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): viewer = self.opt_internally_viewed_formats for i in range(viewer.count()): if viewer.item(i).checkState() == Qt.Checked: - fmts.append(unicode(viewer.item(i).text())) + fmts.append(unicode_type(viewer.item(i).text())) return fmts # }}} diff --git a/src/calibre/gui2/preferences/coloring.py b/src/calibre/gui2/preferences/coloring.py index 5efb4a08d5..ee14634c1b 100644 --- a/src/calibre/gui2/preferences/coloring.py +++ b/src/calibre/gui2/preferences/coloring.py @@ -26,6 +26,7 @@ from calibre.library.coloring import (Rule, conditionable_columns, displayable_columns, rule_from_template, color_row_key) from calibre.utils.localization import lang_map from calibre.utils.icu import lower +from polyglot.builtins import unicode_type all_columns_string = _('All columns') @@ -141,11 +142,11 @@ class ConditionEditor(QWidget): # {{{ def current_col(self): def fget(self): idx = self.column_box.currentIndex() - return unicode(self.column_box.itemData(idx) or '') + return unicode_type(self.column_box.itemData(idx) or '') def fset(self, val): for idx in range(self.column_box.count()): - c = unicode(self.column_box.itemData(idx) or '') + c = unicode_type(self.column_box.itemData(idx) or '') if c == val: self.column_box.setCurrentIndex(idx) return @@ -156,11 +157,11 @@ class ConditionEditor(QWidget): # {{{ def current_action(self): def fget(self): idx = self.action_box.currentIndex() - return unicode(self.action_box.itemData(idx) or '') + return unicode_type(self.action_box.itemData(idx) or '') def fset(self, val): for idx in range(self.action_box.count()): - c = unicode(self.action_box.itemData(idx) or '') + c = unicode_type(self.action_box.itemData(idx) or '') if c == val: self.action_box.setCurrentIndex(idx) return @@ -169,7 +170,7 @@ class ConditionEditor(QWidget): # {{{ @property def current_val(self): - ans = unicode(self.value_box.text()).strip() + ans = unicode_type(self.value_box.text()).strip() if self.current_col == 'languages': rmap = {lower(v):k for k, v in lang_map().iteritems()} ans = rmap.get(lower(ans), ans) @@ -491,8 +492,8 @@ class RuleEditor(QDialog): # {{{ def update_color_label(self): pal = QApplication.palette() - bg1 = unicode(pal.color(pal.Base).name()) - bg2 = unicode(pal.color(pal.AlternateBase).name()) + bg1 = unicode_type(pal.color(pal.Base).name()) + bg2 = unicode_type(pal.color(pal.AlternateBase).name()) c = self.color_box.color self.color_label.setText('''  {st}  @@ -548,10 +549,10 @@ class RuleEditor(QDialog): # {{{ for i in range(1, model.rowCount()): item = model.item(i, 0) if item.checkState() == Qt.Checked: - fnames.append(lower(unicode(item.text()))) + fnames.append(lower(unicode_type(item.text()))) fname = ' : '.join(fnames) else: - fname = lower(unicode(self.filename_box.currentText())) + fname = lower(unicode_type(self.filename_box.currentText())) return fname def update_icon_filenames_in_box(self): @@ -610,7 +611,7 @@ class RuleEditor(QDialog): # {{{ self.update_icon_filenames_in_box() for i in range(self.column_box.count()): - c = unicode(self.column_box.itemData(i) or '') + c = unicode_type(self.column_box.itemData(i) or '') if col == c: self.column_box.setCurrentIndex(i) break @@ -664,13 +665,13 @@ class RuleEditor(QDialog): # {{{ else: r.color = self.color_box.color idx = self.column_box.currentIndex() - col = unicode(self.column_box.itemData(idx) or '') + col = unicode_type(self.column_box.itemData(idx) or '') for c in self.conditions: condition = c.condition if condition is not None: r.add_condition(*condition) if self.rule_kind == 'icon': - kind = unicode(self.kind_box.itemData( + kind = unicode_type(self.kind_box.itemData( self.kind_box.currentIndex()) or '') else: kind = self.rule_kind diff --git a/src/calibre/gui2/preferences/columns.py b/src/calibre/gui2/preferences/columns.py index f504641c8d..0cd0fe5bea 100644 --- a/src/calibre/gui2/preferences/columns.py +++ b/src/calibre/gui2/preferences/columns.py @@ -14,6 +14,7 @@ from calibre.gui2.preferences import ConfigWidgetBase, test_widget from calibre.gui2.preferences.columns_ui import Ui_Form from calibre.gui2.preferences.create_custom_column import CreateCustomColumn from calibre.gui2 import error_dialog, question_dialog, ALL_COLUMNS +from polyglot.builtins import unicode_type class ConfigWidget(ConfigWidgetBase, Ui_Form): @@ -192,7 +193,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): if idx < 0: return error_dialog(self, '', _('You must select a column to delete it'), show=True) - col = unicode(self.opt_columns.item(idx, 0).data(Qt.UserRole) or '') + col = unicode_type(self.opt_columns.item(idx, 0).data(Qt.UserRole) or '') if col not in self.custcols: return error_dialog(self, '', _('The selected column is not a custom column'), show=True) @@ -221,7 +222,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): model = self.gui.library_view.model() row = self.opt_columns.currentRow() try: - key = unicode(self.opt_columns.item(row, 0).data(Qt.UserRole)) + key = unicode_type(self.opt_columns.item(row, 0).data(Qt.UserRole)) except: key = '' CreateCustomColumn(self, row, key, model.orig_headers, ALL_COLUMNS) @@ -234,12 +235,12 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): def apply_custom_column_changes(self): model = self.gui.library_view.model() db = model.db - config_cols = [unicode(self.opt_columns.item(i, 0).data(Qt.UserRole) or '') + config_cols = [unicode_type(self.opt_columns.item(i, 0).data(Qt.UserRole) or '') for i in range(self.opt_columns.rowCount())] if not config_cols: config_cols = ['title'] removed_cols = set(model.column_map) - set(config_cols) - hidden_cols = {unicode(self.opt_columns.item(i, 0).data(Qt.UserRole) or '') + hidden_cols = {unicode_type(self.opt_columns.item(i, 0).data(Qt.UserRole) or '') for i in range(self.opt_columns.rowCount()) if self.opt_columns.item(i, 0).checkState()==Qt.Unchecked} hidden_cols = hidden_cols.union(removed_cols) # Hide removed cols diff --git a/src/calibre/gui2/preferences/create_custom_column.py b/src/calibre/gui2/preferences/create_custom_column.py index e315f47ff3..a67fe945e7 100644 --- a/src/calibre/gui2/preferences/create_custom_column.py +++ b/src/calibre/gui2/preferences/create_custom_column.py @@ -16,6 +16,7 @@ from PyQt5.Qt import ( ) from calibre.gui2 import error_dialog +from polyglot.builtins import unicode_type class CreateCustomColumn(QDialog): @@ -112,7 +113,7 @@ class CreateCustomColumn(QDialog): self.column_type_box.addItem(self.column_types[t]['text']) self.column_type_box.currentIndexChanged.connect(self.datatype_changed) - all_colors = [unicode(s) for s in list(QColor.colorNames())] + all_colors = [unicode_type(s) for s in list(QColor.colorNames())] self.enum_colors_label.setToolTip('

' + ', '.join(all_colors) + '

') if not self.editing_col: @@ -185,7 +186,7 @@ class CreateCustomColumn(QDialog): self.exec_() def shortcut_activated(self, url): # {{{ - which = unicode(url).split(':')[-1] + which = unicode_type(url).split(':')[-1] self.column_type_box.setCurrentIndex({ 'yesno': self.column_types_map['bool'], 'tags' : self.column_types_map['*text'], @@ -464,7 +465,7 @@ class CreateCustomColumn(QDialog): self.allow_half_stars.setVisible(col_type == 'rating') def accept(self): - col = unicode(self.column_name_box.text()).strip() + col = unicode_type(self.column_name_box.text()).strip() if not col: return self.simple_error('', _('No lookup name was provided')) if col.startswith('#'): @@ -475,7 +476,7 @@ class CreateCustomColumn(QDialog): if col.endswith('_index'): return self.simple_error('', _('Lookup names cannot end with _index, ' 'because these names are reserved for the index of a series column.')) - col_heading = unicode(self.column_heading_box.text()).strip() + col_heading = unicode_type(self.column_heading_box.text()).strip() coldef = self.column_types[self.column_type_box.currentIndex()] col_type = coldef['datatype'] if col_type[0] == '*': @@ -511,33 +512,33 @@ class CreateCustomColumn(QDialog): display_dict = {} if col_type == 'datetime': - if unicode(self.format_box.text()).strip(): - display_dict = {'date_format':unicode(self.format_box.text()).strip()} + if unicode_type(self.format_box.text()).strip(): + display_dict = {'date_format':unicode_type(self.format_box.text()).strip()} else: display_dict = {'date_format': None} elif col_type == 'composite': - if not unicode(self.composite_box.text()).strip(): + if not unicode_type(self.composite_box.text()).strip(): return self.simple_error('', _('You must enter a template for' ' composite columns')) - display_dict = {'composite_template':unicode(self.composite_box.text()).strip(), + display_dict = {'composite_template':unicode_type(self.composite_box.text()).strip(), 'composite_sort': ['text', 'number', 'date', 'bool'] [self.composite_sort_by.currentIndex()], 'make_category': self.composite_make_category.isChecked(), 'contains_html': self.composite_contains_html.isChecked(), } elif col_type == 'enumeration': - if not unicode(self.enum_box.text()).strip(): + if not unicode_type(self.enum_box.text()).strip(): return self.simple_error('', _('You must enter at least one' ' value for enumeration columns')) - l = [v.strip() for v in unicode(self.enum_box.text()).split(',') if v.strip()] + l = [v.strip() for v in unicode_type(self.enum_box.text()).split(',') if v.strip()] l_lower = [v.lower() for v in l] for i,v in enumerate(l_lower): if v in l_lower[i+1:]: return self.simple_error('', _('The value "{0}" is in the ' 'list more than once, perhaps with different case').format(l[i])) - c = unicode(self.enum_colors.text()) + c = unicode_type(self.enum_colors.text()) if c: - c = [v.strip() for v in unicode(self.enum_colors.text()).split(',')] + c = [v.strip() for v in unicode_type(self.enum_colors.text()).split(',')] else: c = [] if len(c) != 0 and len(c) != len(l): @@ -552,8 +553,8 @@ class CreateCustomColumn(QDialog): elif col_type == 'text' and is_multiple: display_dict = {'is_names': self.is_names.isChecked()} elif col_type in ['int', 'float']: - if unicode(self.format_box.text()).strip(): - display_dict = {'number_format':unicode(self.format_box.text()).strip()} + if unicode_type(self.format_box.text()).strip(): + display_dict = {'number_format':unicode_type(self.format_box.text()).strip()} else: display_dict = {'number_format': None} elif col_type == 'comments': diff --git a/src/calibre/gui2/preferences/emailp.py b/src/calibre/gui2/preferences/emailp.py index 09ec17c46b..bbe8bed228 100644 --- a/src/calibre/gui2/preferences/emailp.py +++ b/src/calibre/gui2/preferences/emailp.py @@ -17,6 +17,7 @@ from calibre.utils.config import ConfigProxy from calibre.utils.icu import numeric_sort_key from calibre.gui2 import gprefs from calibre.utils.smtp import config as smtp_prefs +from polyglot.builtins import unicode_type class EmailAccounts(QAbstractTableModel): # {{{ @@ -30,12 +31,12 @@ class EmailAccounts(QAbstractTableModel): # {{{ self.sorted_on = (0, True) self.account_order = self.accounts.keys() self.do_sort() - self.headers = map(unicode, [_('Email'), _('Formats'), _('Subject'), + self.headers = map(unicode_type, [_('Email'), _('Formats'), _('Subject'), _('Auto send'), _('Alias'), _('Auto send only tags')]) self.default_font = QFont() self.default_font.setBold(True) self.default_font = (self.default_font) - self.tooltips =[None] + list(map(unicode, map(textwrap.fill, + self.tooltips =[None] + list(map(unicode_type, map(textwrap.fill, [_('Formats to email. The first matching format will be sent.'), _('Subject of the email to use when sending. When left blank ' 'the title will be used for the subject. Also, the same ' @@ -136,21 +137,21 @@ class EmailAccounts(QAbstractTableModel): # {{{ if col == 3: self.accounts[account][1] ^= True elif col == 2: - self.subjects[account] = unicode(value or '') + self.subjects[account] = unicode_type(value or '') elif col == 4: self.aliases.pop(account, None) - aval = unicode(value or '').strip() + aval = unicode_type(value or '').strip() if aval: self.aliases[account] = aval elif col == 5: self.tags.pop(account, None) - aval = unicode(value or '').strip() + aval = unicode_type(value or '').strip() if aval: self.tags[account] = aval elif col == 1: - self.accounts[account][0] = re.sub(',+', ',', re.sub(r'\s+', ',', unicode(value or '').upper())) + self.accounts[account][0] = re.sub(',+', ',', re.sub(r'\s+', ',', unicode_type(value or '').upper())) elif col == 0: - na = unicode(value or '') + na = unicode_type(value or '') from email.utils import parseaddr addr = parseaddr(na)[-1] if not addr: diff --git a/src/calibre/gui2/preferences/history.py b/src/calibre/gui2/preferences/history.py index 96a9519b6d..dc1ab07f50 100644 --- a/src/calibre/gui2/preferences/history.py +++ b/src/calibre/gui2/preferences/history.py @@ -11,6 +11,7 @@ import textwrap from PyQt5.Qt import QComboBox, Qt from calibre.gui2 import config as gui_conf +from polyglot.builtins import unicode_type class HistoryBox(QComboBox): @@ -37,14 +38,11 @@ class HistoryBox(QComboBox): self.setCurrentIndex(self.findText(val, Qt.MatchFixedString)) def save_history(self, opt_name): - history = [unicode(self.itemText(i)) for i in range(self.count())] + history = [unicode_type(self.itemText(i)) for i in range(self.count())] ct = self.text() if ct not in history: history = [ct] + history gui_conf[opt_name] = history[:10] def text(self): - return unicode(self.currentText()).strip() - - - + return unicode_type(self.currentText()).strip() diff --git a/src/calibre/gui2/preferences/look_feel.py b/src/calibre/gui2/preferences/look_feel.py index 7a771b3202..0ba64accf0 100644 --- a/src/calibre/gui2/preferences/look_feel.py +++ b/src/calibre/gui2/preferences/look_feel.py @@ -36,6 +36,7 @@ from calibre.gui2.preferences.coloring import EditRules from calibre.gui2.library.alternate_views import auto_height, CM_TO_INCH from calibre.gui2.widgets2 import Dialog from calibre.gui2.actions.show_quickview import get_quickview_action_plugin +from polyglot.builtins import unicode_type class BusyCursor(object): @@ -541,8 +542,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.tabWidget.setCurrentIndex(0) keys = [QKeySequence('F11', QKeySequence.PortableText), QKeySequence( 'Ctrl+Shift+F', QKeySequence.PortableText)] - keys = [unicode(x.toString(QKeySequence.NativeText)) for x in keys] - self.fs_help_msg.setText(unicode(self.fs_help_msg.text())%( + keys = [unicode_type(x.toString(QKeySequence.NativeText)) for x in keys] + self.fs_help_msg.setText(unicode_type(self.fs_help_msg.text())%( _(' or ').join(keys))) self.size_calculated.connect(self.update_cg_cache_size, type=Qt.QueuedConnection) self.tabWidget.currentChanged.connect(self.tab_changed) @@ -727,7 +728,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): def update_font_display(self): font = self.build_font_obj() fi = QFontInfo(font) - name = unicode(fi.family()) + name = unicode_type(fi.family()) self.font_display.setFont(font) self.font_display.setText(name + ' [%dpt]'%fi.pointSize()) @@ -737,7 +738,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): if fd.exec_() == fd.Accepted: font = fd.selectedFont() fi = QFontInfo(font) - self.current_font = [unicode(fi.family()), fi.pointSize(), + self.current_font = [unicode_type(fi.family()), fi.pointSize(), fi.weight(), fi.italic(), font.stretch()] self.update_font_display() self.changed_signal.emit() diff --git a/src/calibre/gui2/preferences/main.py b/src/calibre/gui2/preferences/main.py index 78aa064ca8..3b8cc99c45 100644 --- a/src/calibre/gui2/preferences/main.py +++ b/src/calibre/gui2/preferences/main.py @@ -21,6 +21,7 @@ from calibre.gui2 import (gprefs, min_available_height, available_width, from calibre.gui2.dialogs.message_box import Icon from calibre.gui2.preferences import init_gui, AbortCommit, get_plugin from calibre.customize.ui import preferences_plugins +from polyglot.builtins import unicode_type ICON_SIZE = 32 @@ -293,8 +294,8 @@ class Preferences(QDialog): if isinstance(g, QLabel): buddy = g.buddy() if buddy is not None and hasattr(buddy, 'toolTip'): - htext = unicode(buddy.toolTip()).strip() - etext = unicode(g.toolTip()).strip() + htext = unicode_type(buddy.toolTip()).strip() + etext = unicode_type(g.toolTip()).strip() if htext and not etext: g.setToolTip(htext) g.setWhatsThis(htext) diff --git a/src/calibre/gui2/preferences/plugboard.py b/src/calibre/gui2/preferences/plugboard.py index 40f7457437..5005e87735 100644 --- a/src/calibre/gui2/preferences/plugboard.py +++ b/src/calibre/gui2/preferences/plugboard.py @@ -24,6 +24,7 @@ from calibre.library.save_to_disk import plugboard_any_format_value, \ from calibre.srv.content import plugboard_content_server_value, plugboard_content_server_formats from calibre.gui2.email import plugboard_email_value, plugboard_email_formats from calibre.utils.formatter import validation_formatter +from polyglot.builtins import unicode_type class ConfigWidget(ConfigWidgetBase, Ui_Form): @@ -153,7 +154,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.clear_fields(new_boxes=False) return self.clear_fields(new_boxes=True) - self.current_device = unicode(txt) + self.current_device = unicode_type(txt) fpb = self.current_plugboards.get(self.current_format, None) if fpb is None: print('edit_device_changed: none format!') @@ -176,7 +177,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.clear_fields(new_boxes=False) return self.clear_fields(new_boxes=True) - txt = unicode(txt) + txt = unicode_type(txt) fpb = self.current_plugboards.get(txt, None) if fpb is None: print('edit_format_changed: none editable format!') @@ -208,7 +209,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.clear_fields(edit_boxes=False) return self.clear_fields(edit_boxes=True) - self.current_device = unicode(txt) + self.current_device = unicode_type(txt) if self.current_format in self.current_plugboards and \ self.current_device in self.current_plugboards[self.current_format]: @@ -292,7 +293,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.new_device.setCurrentIndex(0) if txt: self.clear_fields(edit_boxes=True) - self.current_format = unicode(txt) + self.current_format = unicode_type(txt) self.check_if_writer_disabled(self.current_format) else: self.clear_fields(edit_boxes=False) @@ -301,7 +302,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): pb = [] comments_in_dests = False for i in range(0, len(self.source_widgets)): - s = unicode(self.source_widgets[i].text()) + s = unicode_type(self.source_widgets[i].text()) if s: d = self.dest_widgets[i].currentIndex() if d != 0: diff --git a/src/calibre/gui2/preferences/plugins.py b/src/calibre/gui2/preferences/plugins.py index 24be3fcd5e..704cbc39c6 100644 --- a/src/calibre/gui2/preferences/plugins.py +++ b/src/calibre/gui2/preferences/plugins.py @@ -22,6 +22,7 @@ from calibre.gui2.dialogs.confirm_delete import confirm from calibre.utils.search_query_parser import SearchQueryParser from calibre.utils.icu import lower from calibre.constants import iswindows +from polyglot.builtins import unicode_type class AdaptSQP(SearchQueryParser): @@ -271,7 +272,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): if not idx.isValid(): idx = self._plugin_model.index(0, 0) idx = self._plugin_model.find_next(idx, - unicode(self.search.currentText())) + unicode_type(self.search.currentText())) self.highlight_index(idx) def find_previous(self, *args): @@ -279,7 +280,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): if not idx.isValid(): idx = self._plugin_model.index(0, 0) idx = self._plugin_model.find_next(idx, - unicode(self.search.currentText()), backwards=True) + unicode_type(self.search.currentText()), backwards=True) self.highlight_index(idx) def toggle_plugin(self, *args): @@ -317,7 +318,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): plugin = add_plugin(path) except NameConflict as e: return error_dialog(self, _('Already exists'), - unicode(e), show=True) + unicode_type(e), show=True) self._plugin_model.beginResetModel() self._plugin_model.populate() self._plugin_model.endResetModel() @@ -339,7 +340,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): index = self.plugin_view.currentIndex() if index.isValid(): if not index.parent().isValid(): - name = unicode(index.data() or '') + name = unicode_type(index.data() or '') return error_dialog(self, _('Error'), '

'+ _('Select an actual plugin under %s to customize')%name, show=True, show_copy_button=False) diff --git a/src/calibre/gui2/preferences/save_template.py b/src/calibre/gui2/preferences/save_template.py index 237dc25045..374d089214 100644 --- a/src/calibre/gui2/preferences/save_template.py +++ b/src/calibre/gui2/preferences/save_template.py @@ -13,6 +13,7 @@ from calibre.gui2.preferences.save_template_ui import Ui_Form from calibre.library.save_to_disk import FORMAT_ARG_DESCS, preprocess_template from calibre.utils.formatter import validation_formatter from calibre.gui2.dialogs.template_dialog import TemplateDialog +from polyglot.builtins import unicode_type class SaveTemplate(QWidget, Ui_Form): @@ -82,6 +83,6 @@ class SaveTemplate(QWidget, Ui_Form): self.opt_template.set_value(val) def save_settings(self, config, name): - val = unicode(self.opt_template.text()) + val = unicode_type(self.opt_template.text()) config.set(name, val) self.opt_template.save_history(self.option_name+'_template_history') diff --git a/src/calibre/gui2/preferences/search.py b/src/calibre/gui2/preferences/search.py index 03741ac0be..7384075e02 100644 --- a/src/calibre/gui2/preferences/search.py +++ b/src/calibre/gui2/preferences/search.py @@ -14,6 +14,7 @@ from calibre.gui2 import config, error_dialog, gprefs from calibre.utils.config import prefs from calibre.utils.icu import sort_key from calibre.library.caches import set_use_primary_find_in_search +from polyglot.builtins import unicode_type class ConfigWidget(ConfigWidgetBase, Ui_Form): @@ -143,13 +144,13 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): def gst_save_clicked(self): idx = self.gst_names.currentIndex() - name = icu_lower(unicode(self.gst_names.currentText())) + name = icu_lower(unicode_type(self.gst_names.currentText())) if not name: return error_dialog(self.gui, _('Grouped search terms'), _('The search term cannot be blank'), show=True) if idx != 0: - orig_name = unicode(self.gst_names.itemData(idx) or '') + orig_name = unicode_type(self.gst_names.itemData(idx) or '') else: orig_name = '' if name != orig_name: @@ -163,7 +164,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): _('That name is already used for User category'), show=True) - val = [v.strip() for v in unicode(self.gst_value.text()).split(',') if v.strip()] + val = [v.strip() for v in unicode_type(self.gst_value.text()).split(',') if v.strip()] if not val: return error_dialog(self.gui, _('Grouped search terms'), _('The value box cannot be empty'), show=True) @@ -180,7 +181,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): if self.gst_names.currentIndex() == 0: return error_dialog(self.gui, _('Grouped search terms'), _('The empty grouped search term cannot be deleted'), show=True) - name = unicode(self.gst_names.currentText()) + name = unicode_type(self.gst_names.currentText()) if name in self.gst: del self.gst[name] self.fill_gst_box(select='') @@ -215,7 +216,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): if idx == 0: self.gst_value.setText('') else: - name = unicode(self.gst_names.itemData(idx) or '') + name = unicode_type(self.gst_names.itemData(idx) or '') self.gst_value.setText(','.join(self.gst[name])) self.gst_value.blockSignals(False) @@ -229,13 +230,13 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.db.new_api.set_pref('grouped_search_terms', self.gst) self.db.field_metadata.add_grouped_search_terms(self.gst) self.db.new_api.set_pref('similar_authors_search_key', - unicode(self.similar_authors_search_key.currentText())) + unicode_type(self.similar_authors_search_key.currentText())) self.db.new_api.set_pref('similar_tags_search_key', - unicode(self.similar_tags_search_key.currentText())) + unicode_type(self.similar_tags_search_key.currentText())) self.db.new_api.set_pref('similar_series_search_key', - unicode(self.similar_series_search_key.currentText())) + unicode_type(self.similar_series_search_key.currentText())) self.db.new_api.set_pref('similar_publisher_search_key', - unicode(self.similar_publisher_search_key.currentText())) + unicode_type(self.similar_publisher_search_key.currentText())) return ConfigWidgetBase.commit(self) def refresh_gui(self, gui): diff --git a/src/calibre/gui2/preferences/template_functions.py b/src/calibre/gui2/preferences/template_functions.py index f33c6627d1..e89afe0066 100644 --- a/src/calibre/gui2/preferences/template_functions.py +++ b/src/calibre/gui2/preferences/template_functions.py @@ -16,6 +16,7 @@ from calibre.gui2.widgets import PythonHighlighter from calibre.utils.formatter_functions import (formatter_functions, compile_user_function, compile_user_template_functions, load_user_template_functions) +from polyglot.builtins import unicode_type class ConfigWidget(ConfigWidgetBase, Ui_Form): @@ -133,7 +134,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.delete_button.setEnabled(True) def delete_button_clicked(self): - name = unicode(self.function_name.currentText()) + name = unicode_type(self.function_name.currentText()) if name in self.builtins: error_dialog(self.gui, _('Template functions'), _('You cannot delete a built-in function'), show=True) @@ -150,7 +151,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): def create_button_clicked(self): self.changed_signal.emit() - name = unicode(self.function_name.currentText()) + name = unicode_type(self.function_name.currentText()) if name in self.funcs: error_dialog(self.gui, _('Template functions'), _('Name %s already used')%(name,), show=True) @@ -166,8 +167,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): if not box.exec_(): return try: - prog = unicode(self.program.toPlainText()) - cls = compile_user_function(name, unicode(self.documentation.toPlainText()), + prog = unicode_type(self.program.toPlainText()) + cls = compile_user_function(name, unicode_type(self.documentation.toPlainText()), self.argument_count.value(), prog) self.funcs[name] = cls self.build_function_names_box(scroll_to=name) @@ -184,7 +185,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.program.setReadOnly(False) def function_index_changed(self, txt): - txt = unicode(txt) + txt = unicode_type(txt) self.create_button.setEnabled(False) if not txt: self.argument_count.clear() diff --git a/src/calibre/gui2/preferences/texture_chooser.py b/src/calibre/gui2/preferences/texture_chooser.py index bf50e95ac6..fa45a7b94c 100644 --- a/src/calibre/gui2/preferences/texture_chooser.py +++ b/src/calibre/gui2/preferences/texture_chooser.py @@ -15,6 +15,7 @@ from PyQt5.Qt import ( from calibre.constants import config_dir from calibre.gui2 import choose_files, error_dialog from calibre.utils.icu import sort_key +from polyglot.builtins import unicode_type def texture_dir(): @@ -84,7 +85,7 @@ class TextureChooser(QDialog): self.update_remove_state() if initial: - existing = {unicode(i.data(Qt.UserRole) or ''):i for i in (self.images.item(c) for c in xrange(self.images.count()))} + existing = {unicode_type(i.data(Qt.UserRole) or ''):i for i in (self.images.item(c) for c in xrange(self.images.count()))} item = existing.get(initial, None) if item is not None: item.setSelected(True) @@ -115,7 +116,7 @@ class TextureChooser(QDialog): path = path[0] fname = os.path.basename(path) name = fname.rpartition('.')[0] - existing = {unicode(i.data(Qt.UserRole) or ''):i for i in (self.images.item(c) for c in xrange(self.images.count()))} + existing = {unicode_type(i.data(Qt.UserRole) or ''):i for i in (self.images.item(c) for c in xrange(self.images.count()))} dest = os.path.join(self.tdir, fname) with open(path, 'rb') as s, open(dest, 'wb') as f: shutil.copyfileobj(s, f) @@ -134,7 +135,7 @@ class TextureChooser(QDialog): @property def selected_fname(self): try: - return unicode(self.selected_item.data(Qt.UserRole) or '') + return unicode_type(self.selected_item.data(Qt.UserRole) or '') except (AttributeError, TypeError): pass @@ -144,7 +145,7 @@ class TextureChooser(QDialog): if self.selected_fname.startswith(':'): return error_dialog(self, _('Cannot remove'), _('Cannot remove builtin textures'), show=True) - os.remove(unicode(self.selected_item.data(Qt.UserRole+1) or '')) + os.remove(unicode_type(self.selected_item.data(Qt.UserRole+1) or '')) self.images.takeItem(self.images.row(self.selected_item)) diff --git a/src/calibre/gui2/preferences/toolbar.py b/src/calibre/gui2/preferences/toolbar.py index e528c814f3..43d3a62492 100644 --- a/src/calibre/gui2/preferences/toolbar.py +++ b/src/calibre/gui2/preferences/toolbar.py @@ -12,6 +12,7 @@ from calibre.gui2.preferences.toolbar_ui import Ui_Form from calibre.gui2 import gprefs, warning_dialog, error_dialog from calibre.gui2.preferences import ConfigWidgetBase, test_widget, AbortCommit from calibre.utils.icu import primary_sort_key +from polyglot.builtins import unicode_type class FakeAction(object): @@ -277,7 +278,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.help_text.setText(tt) def what_changed(self, idx): - key = unicode(self.what.itemData(idx) or '') + key = unicode_type(self.what.itemData(idx) or '') if key == 'blank': self.actions_widget.setVisible(False) self.spacer_widget.setVisible(True) diff --git a/src/calibre/gui2/preferences/tweaks.py b/src/calibre/gui2/preferences/tweaks.py index d89e3171be..61e1a2d7b4 100644 --- a/src/calibre/gui2/preferences/tweaks.py +++ b/src/calibre/gui2/preferences/tweaks.py @@ -19,6 +19,7 @@ from calibre import isbytestring from calibre.utils.icu import lower from calibre.utils.search_query_parser import (ParseException, SearchQueryParser) +from polyglot.builtins import unicode_type from PyQt5.Qt import ( QAbstractListModel, Qt, QStyledItemDelegate, QStyle, QStyleOptionViewItem, @@ -99,7 +100,7 @@ class Tweak(object): # {{{ val = self.custom_values.get(key, val) ans.append('%s = %r'%(key, val)) ans = '\n'.join(ans) - if isinstance(ans, unicode): + if isinstance(ans, unicode_type): ans = ans.encode('utf-8') return ans @@ -489,7 +490,7 @@ class ConfigWidget(ConfigWidgetBase): if d.exec_() == d.Accepted: g, l = {}, {} try: - exec(unicode(d.edit.toPlainText()), g, l) + exec(unicode_type(d.edit.toPlainText()), g, l) except: import traceback return error_dialog(self, _('Failed'), @@ -530,7 +531,7 @@ class ConfigWidget(ConfigWidgetBase): if idx.isValid(): l, g = {}, {} try: - exec(unicode(self.edit_tweak.toPlainText()), g, l) + exec(unicode_type(self.edit_tweak.toPlainText()), g, l) except: import traceback error_dialog(self.gui, _('Failed'), @@ -586,7 +587,7 @@ class ConfigWidget(ConfigWidgetBase): if not idx.isValid(): idx = self._model.index(0) idx = self._model.find_next(idx, - unicode(self.search.currentText())) + unicode_type(self.search.currentText())) self.highlight_index(idx) def find_previous(self, *args): @@ -594,7 +595,7 @@ class ConfigWidget(ConfigWidgetBase): if not idx.isValid(): idx = self._model.index(0) idx = self._model.find_next(idx, - unicode(self.search.currentText()), backwards=True) + unicode_type(self.search.currentText()), backwards=True) self.highlight_index(idx) diff --git a/src/calibre/gui2/proceed.py b/src/calibre/gui2/proceed.py index a8cd4647b7..d06211c6a0 100644 --- a/src/calibre/gui2/proceed.py +++ b/src/calibre/gui2/proceed.py @@ -16,6 +16,7 @@ from PyQt5.Qt import ( from calibre.constants import __version__ from calibre.gui2.dialogs.message_box import ViewLog +from polyglot.builtins import unicode_type Question = namedtuple('Question', 'payload callback cancel_callback ' 'title msg html_log log_viewer_title log_is_file det_msg ' @@ -170,9 +171,9 @@ class ProceedQuestion(QWidget): def copy_to_clipboard(self, *args): QApplication.clipboard().setText( 'calibre, version %s\n%s: %s\n\n%s' % - (__version__, unicode(self.windowTitle()), - unicode(self.msg_label.text()), - unicode(self.det_msg.toPlainText()))) + (__version__, unicode_type(self.windowTitle()), + unicode_type(self.msg_label.text()), + unicode_type(self.det_msg.toPlainText()))) self.copy_button.setText(_('Copied')) def action_clicked(self): @@ -210,7 +211,7 @@ class ProceedQuestion(QWidget): self.show_question() def toggle_det_msg(self, *args): - vis = unicode(self.det_msg_toggle.text()) == self.hide_det_msg + vis = unicode_type(self.det_msg_toggle.text()) == self.hide_det_msg self.det_msg_toggle.setText(self.show_det_msg if vis else self.hide_det_msg) self.det_msg.setVisible(not vis) diff --git a/src/calibre/gui2/qt_file_dialogs.py b/src/calibre/gui2/qt_file_dialogs.py index 2b0ed66e5d..632e243789 100644 --- a/src/calibre/gui2/qt_file_dialogs.py +++ b/src/calibre/gui2/qt_file_dialogs.py @@ -11,6 +11,7 @@ from PyQt5.Qt import QFileDialog, QObject from calibre.gui2.linux_file_dialogs import dialog_name, image_extensions from calibre.utils.filenames import expanduser +from polyglot.builtins import unicode_type def select_initial_dir(q): @@ -96,7 +97,7 @@ class FileDialog(QObject): ftext, "", opts) if fs and fs[0]: for f in fs[0]: - f = unicode(f) + f = unicode_type(f) if not f: continue if not os.path.exists(f): @@ -108,11 +109,11 @@ class FileDialog(QObject): else: if mode == QFileDialog.Directory: opts |= QFileDialog.ShowDirsOnly - f = unicode(QFileDialog.getExistingDirectory(parent, title, initial_dir, opts)) + f = unicode_type(QFileDialog.getExistingDirectory(parent, title, initial_dir, opts)) if os.path.exists(f): self.selected_files.append(f) if self.selected_files: - self.selected_files = [unicode(q) for q in self.selected_files] + self.selected_files = [unicode_type(q) for q in self.selected_files] saved_loc = self.selected_files[0] if os.path.isfile(saved_loc): saved_loc = os.path.dirname(saved_loc) @@ -122,7 +123,7 @@ class FileDialog(QObject): def get_files(self): if self.selected_files is None: - return tuple(os.path.abspath(unicode(i)) for i in self.fd.selectedFiles()) + return tuple(os.path.abspath(unicode_type(i)) for i in self.fd.selectedFiles()) return tuple(self.selected_files) diff --git a/src/calibre/gui2/save.py b/src/calibre/gui2/save.py index bc0b9a0e7a..1c268c7fe7 100644 --- a/src/calibre/gui2/save.py +++ b/src/calibre/gui2/save.py @@ -25,6 +25,7 @@ from calibre.gui2.dialogs.progress import ProgressDialog from calibre.utils.formatter_functions import load_user_template_functions from calibre.utils.ipc.pool import Pool, Failure from calibre.library.save_to_disk import sanitize_args, get_path_components, find_plugboard, plugboard_save_to_disk_value +from polyglot.builtins import unicode_type BookId = namedtuple('BookId', 'title authors') @@ -158,7 +159,7 @@ class Saver(QObject): except Failure as err: error_dialog(self.pd, _('Critical failure'), _( 'Could not save books to disk, click "Show details" for more information'), - det_msg=unicode(err.failure_message) + '\n' + unicode(err.details), show=True) + det_msg=unicode_type(err.failure_message) + '\n' + unicode_type(err.details), show=True) self.pd.canceled = True self.do_one_signal.emit() @@ -272,7 +273,7 @@ class Saver(QObject): except Failure as err: error_dialog(self.pd, _('Critical failure'), _( 'Could not save books to disk, click "Show details" for more information'), - det_msg=unicode(err.failure_message) + '\n' + unicode(err.details), show=True) + det_msg=unicode_type(err.failure_message) + '\n' + unicode_type(err.details), show=True) self.pd.canceled = True else: self.pd.value += 1 @@ -306,7 +307,7 @@ class Saver(QObject): except Failure as err: error_dialog(self.pd, _('Critical failure'), _( 'Could not save books to disk, click "Show details" for more information'), - det_msg=unicode(err.failure_message) + '\n' + unicode(err.details), show=True) + det_msg=unicode_type(err.failure_message) + '\n' + unicode_type(err.details), show=True) self.pd.canceled = True except RuntimeError: pass # tasks not completed diff --git a/src/calibre/gui2/search_box.py b/src/calibre/gui2/search_box.py index c95a8d5d32..c8c011b7d5 100644 --- a/src/calibre/gui2/search_box.py +++ b/src/calibre/gui2/search_box.py @@ -20,14 +20,15 @@ from calibre.gui2.dialogs.confirm_delete import confirm from calibre.gui2.dialogs.saved_search_editor import SavedSearchEditor from calibre.gui2.dialogs.search import SearchDialog from calibre.utils.icu import primary_sort_key +from polyglot.builtins import unicode_type QT_HIDDEN_CLEAR_ACTION = '_q_qlineeditclearaction' -class AsYouType(unicode): +class AsYouType(unicode_type): def __new__(cls, text): - self = unicode.__new__(cls, text) + self = unicode_type.__new__(cls, text) self.as_you_type = True return self @@ -185,7 +186,7 @@ class SearchBox2(QComboBox): # {{{ if isinstance(ok, basestring): self.setToolTip(ok) ok = False - if not unicode(self.currentText()).strip(): + if not unicode_type(self.currentText()).strip(): self.clear(emit_search=False) return self._in_a_search = ok @@ -208,7 +209,7 @@ class SearchBox2(QComboBox): # {{{ if event.key() in (Qt.Key_Return, Qt.Key_Enter): self.do_search() self.focus_to_library.emit() - elif self.as_you_type and unicode(event.text()): + elif self.as_you_type and unicode_type(event.text()): self.timer.start(1500) # Comes from the combobox itself @@ -240,7 +241,7 @@ class SearchBox2(QComboBox): # {{{ def _do_search(self, store_in_history=True, as_you_type=False): self.hide_completer_popup() - text = unicode(self.currentText()).strip() + text = unicode_type(self.currentText()).strip() if not text: return self.clear() if as_you_type: @@ -258,7 +259,7 @@ class SearchBox2(QComboBox): # {{{ self.insertItem(0, t) self.setCurrentIndex(0) self.block_signals(False) - history = [unicode(self.itemText(i)) for i in + history = [unicode_type(self.itemText(i)) for i in range(self.count())] config[self.opt_name] = history @@ -301,7 +302,7 @@ class SearchBox2(QComboBox): # {{{ @property def current_text(self): - return unicode(self.lineEdit().text()) + return unicode_type(self.lineEdit().text()) # }}} @@ -365,7 +366,7 @@ class SavedSearchBox(QComboBox): # {{{ def saved_search_selected(self, qname): from calibre.gui2.ui import get_gui db = get_gui().current_db - qname = unicode(qname) + qname = unicode_type(qname) if qname is None or not qname.strip(): self.search_box.clear() return @@ -392,9 +393,9 @@ class SavedSearchBox(QComboBox): # {{{ def save_search_button_clicked(self): from calibre.gui2.ui import get_gui db = get_gui().current_db - name = unicode(self.currentText()) + name = unicode_type(self.currentText()) if not name.strip(): - name = unicode(self.search_box.text()).replace('"', '') + name = unicode_type(self.search_box.text()).replace('"', '') name = name.replace('\\', '') if not name: error_dialog(self, _('Create saved search'), @@ -406,7 +407,7 @@ class SavedSearchBox(QComboBox): # {{{ _('There is no search to save'), show=True) return db.saved_search_delete(name) - db.saved_search_add(name, unicode(self.search_box.text())) + db.saved_search_add(name, unicode_type(self.search_box.text())) # now go through an initialization cycle to ensure that the combobox has # the new search in it, that it is selected, and that the search box # references the new search instead of the text in the search. @@ -427,10 +428,10 @@ class SavedSearchBox(QComboBox): # {{{ 'permanently deleted. Are you sure?') + '

', 'saved_search_delete', self): return - ss = db.saved_search_lookup(unicode(self.currentText())) + ss = db.saved_search_lookup(unicode_type(self.currentText())) if ss is None: return - db.saved_search_delete(unicode(self.currentText())) + db.saved_search_delete(unicode_type(self.currentText())) self.clear() self.search_box.clear() self.changed.emit() @@ -442,7 +443,7 @@ class SavedSearchBox(QComboBox): # {{{ idx = self.currentIndex() if idx < 0: return - self.search_box.set_search_string(db.saved_search_lookup(unicode(self.currentText()))) + self.search_box.set_search_string(db.saved_search_lookup(unicode_type(self.currentText()))) # }}} @@ -466,7 +467,7 @@ class SearchBoxMixin(object): # {{{ self.search.setMaximumWidth(self.width()-150) self.action_focus_search = QAction(self) shortcuts = list( - map(lambda x:unicode(x.toString(QKeySequence.PortableText)), + map(lambda x:unicode_type(x.toString(QKeySequence.PortableText)), QKeySequence.keyBindings(QKeySequence.Find))) shortcuts += ['/', 'Alt+S'] self.keyboard.register_shortcut('start search', _('Start search'), @@ -474,7 +475,7 @@ class SearchBoxMixin(object): # {{{ self.action_focus_search.triggered.connect(self.focus_search_box) self.addAction(self.action_focus_search) self.search.setStatusTip(re.sub(r'<\w+>', ' ', - unicode(self.search.toolTip()))) + unicode_type(self.search.toolTip()))) self.set_highlight_only_button_icon() self.highlight_only_button.clicked.connect(self.highlight_only_clicked) tt = _('Enable or disable search highlighting.') + '

' diff --git a/src/calibre/gui2/search_restriction_mixin.py b/src/calibre/gui2/search_restriction_mixin.py index ba7f512e30..b6c4bd5c7d 100644 --- a/src/calibre/gui2/search_restriction_mixin.py +++ b/src/calibre/gui2/search_restriction_mixin.py @@ -18,6 +18,7 @@ from calibre.gui2.widgets import ComboBoxWithHelp from calibre.utils.icu import sort_key from calibre.utils.search_query_parser import ParseException from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type class SelectNames(QDialog): # {{{ @@ -51,7 +52,7 @@ class SelectNames(QDialog): # {{{ @property def names(self): for item in self._names.selectedItems(): - yield unicode(item.data(Qt.DisplayRole) or '') + yield unicode_type(item.data(Qt.DisplayRole) or '') @property def match_type(self): @@ -185,7 +186,7 @@ class CreateVirtualLibrary(QDialog): # {{{ def search_text_changed(self, txt): db = self.gui.current_db searches = [_('Saved searches recognized in the expression:')] - txt = unicode(txt) + txt = unicode_type(txt) while txt: p = txt.partition('search:') if p[1]: # found 'search:' @@ -219,7 +220,7 @@ class CreateVirtualLibrary(QDialog): # {{{ self.saved_searches_label.setPlainText('') def name_text_edited(self, new_name): - self.new_name = unicode(new_name) + self.new_name = unicode_type(new_name) def name_index_changed(self, dex): if self.editing and (self.vl_text.text() != self.original_search or @@ -235,12 +236,12 @@ class CreateVirtualLibrary(QDialog): # {{{ return self.new_name = self.editing = self.vl_name.currentText() self.original_index = dex - self.original_search = unicode(self.vl_name.itemData(dex) or '') + self.original_search = unicode_type(self.vl_name.itemData(dex) or '') self.vl_text.setText(self.original_search) def link_activated(self, url): db = self.gui.current_db - f, txt = unicode(url).partition('.')[0::2] + f, txt = unicode_type(url).partition('.')[0::2] if f == 'search': names = db.saved_search_names() else: @@ -260,7 +261,7 @@ class CreateVirtualLibrary(QDialog): # {{{ self.vl_text.setCursorPosition(0) def accept(self): - n = unicode(self.vl_name.currentText()).strip() + n = unicode_type(self.vl_name.currentText()).strip() if not n: error_dialog(self.gui, _('No name'), _('You must provide a name for the new virtual library'), @@ -280,7 +281,7 @@ class CreateVirtualLibrary(QDialog): # {{{ default_yes=False): return - v = unicode(self.vl_text.text()).strip() + v = unicode_type(self.vl_text.text()).strip() if not v: error_dialog(self.gui, _('No search string'), _('You must provide a search to define the new virtual library'), @@ -513,7 +514,7 @@ class SearchRestrictionMixin(object): current_restriction_text = None if self.search_restriction.count() > 1: - txt = unicode(self.search_restriction.itemText(2)) + txt = unicode_type(self.search_restriction.itemText(2)) if txt.startswith('*'): current_restriction_text = txt self.search_restriction.clear() @@ -561,14 +562,14 @@ class SearchRestrictionMixin(object): def apply_text_search_restriction(self, search): if not self.search_restriction_list_built: self.build_search_restriction_list() - search = unicode(search) + search = unicode_type(search) if not search: self.search_restriction.setCurrentIndex(0) self._apply_search_restriction('', '') else: s = '*' + search if self.search_restriction.count() > 1: - txt = unicode(self.search_restriction.itemText(2)) + txt = unicode_type(self.search_restriction.itemText(2)) if txt.startswith('*'): self.search_restriction.setItemText(2, s) else: @@ -582,12 +583,12 @@ class SearchRestrictionMixin(object): if not self.search_restriction_list_built: self.build_search_restriction_list() if i == 1: - self.apply_text_search_restriction(unicode(self.search.currentText())) - elif i == 2 and unicode(self.search_restriction.currentText()).startswith('*'): + self.apply_text_search_restriction(unicode_type(self.search.currentText())) + elif i == 2 and unicode_type(self.search_restriction.currentText()).startswith('*'): self.apply_text_search_restriction( - unicode(self.search_restriction.currentText())[1:]) + unicode_type(self.search_restriction.currentText())[1:]) else: - r = unicode(self.search_restriction.currentText()) + r = unicode_type(self.search_restriction.currentText()) if r is not None and r != '': restriction = 'search:"%s"'%(r) else: diff --git a/src/calibre/gui2/shortcuts.py b/src/calibre/gui2/shortcuts.py index 279d3dd124..77944aada5 100644 --- a/src/calibre/gui2/shortcuts.py +++ b/src/calibre/gui2/shortcuts.py @@ -17,6 +17,7 @@ from PyQt5.Qt import ( from calibre.gui2 import error_dialog from calibre.utils.config import XMLConfig from calibre.utils.icu import sort_key +from polyglot.builtins import unicode_type DEFAULTS = Qt.UserRole DESCRIPTION = Qt.UserRole + 1 @@ -118,7 +119,7 @@ class Customize(QFrame): dup_desc = self.dup_check(sequence, self.key) if dup_desc is not None: error_dialog(self, _('Already assigned'), - unicode(sequence.toString(QKeySequence.NativeText)) + ' ' + + unicode_type(sequence.toString(QKeySequence.NativeText)) + ' ' + _('already assigned to') + ' ' + dup_desc, show=True) self.clear_clicked(which=which) @@ -169,12 +170,12 @@ class Delegate(QStyledItemDelegate): def setEditorData(self, editor, index): defs = index.data(DEFAULTS) - defs = _(' or ').join([unicode(x.toString(x.NativeText)) for x in defs]) - editor.key = unicode(index.data(KEY)) + defs = _(' or ').join([unicode_type(x.toString(x.NativeText)) for x in defs]) + editor.key = unicode_type(index.data(KEY)) editor.default_shortcuts.setText(_('&Default') + ': %s' % defs) editor.default_shortcuts.setChecked(True) editor.header.setText('%s: %s'%(_('Customize shortcuts for'), - unicode(index.data(DESCRIPTION)))) + unicode_type(index.data(DESCRIPTION)))) custom = index.data(CUSTOM) if custom: editor.custom.setChecked(True) @@ -250,7 +251,7 @@ class Shortcuts(QAbstractListModel): return self.descriptions[key] def get_shortcuts(self, key): - return [unicode(x.toString(x.NativeText)) for x in + return [unicode_type(x.toString(x.NativeText)) for x in self.get_sequences(key)] def data(self, index, role): @@ -279,7 +280,7 @@ class Shortcuts(QAbstractListModel): def set_data(self, index, custom): key = self.order[index.row()] if custom: - self.custom[key] = [unicode(x.toString(QKeySequence.PortableText)) for x in custom] + self.custom[key] = [unicode_type(x.toString(QKeySequence.PortableText)) for x in custom] elif key in self.custom: del self.custom[key] diff --git a/src/calibre/gui2/store/basic_config.py b/src/calibre/gui2/store/basic_config.py index f7f1652d68..c888b7fdcf 100644 --- a/src/calibre/gui2/store/basic_config.py +++ b/src/calibre/gui2/store/basic_config.py @@ -9,6 +9,7 @@ __docformat__ = 'restructuredtext en' from PyQt5.Qt import QWidget from calibre.gui2.store.basic_config_widget_ui import Ui_Form +from polyglot.builtins import unicode_type class BasicStoreConfigWidget(QWidget, Ui_Form): @@ -38,5 +39,5 @@ class BasicStoreConfig(object): def save_settings(self, config_widget): self.config['open_external'] = config_widget.open_external.isChecked() - tags = unicode(config_widget.tags.text()) + tags = unicode_type(config_widget.tags.text()) self.config['tags'] = tags diff --git a/src/calibre/gui2/store/config/chooser/adv_search_builder.py b/src/calibre/gui2/store/config/chooser/adv_search_builder.py index 50964236d9..e9ffea2316 100644 --- a/src/calibre/gui2/store/config/chooser/adv_search_builder.py +++ b/src/calibre/gui2/store/config/chooser/adv_search_builder.py @@ -13,6 +13,7 @@ from PyQt5.Qt import (QDialog, QDialogButtonBox) from calibre.gui2.store.config.chooser.adv_search_builder_ui import Ui_Dialog from calibre.library.caches import CONTAINS_MATCH, EQUALS_MATCH from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type class AdvSearchBuilderDialog(QDialog, Ui_Dialog): @@ -77,7 +78,7 @@ class AdvSearchBuilderDialog(QDialog, Ui_Dialog): self.mc = '=' else: self.mc = '~' - all, any, phrase, none = map(lambda x: unicode(x.text()), + all, any, phrase, none = map(lambda x: unicode_type(x.text()), (self.all, self.any, self.phrase, self.none)) all, any, none = map(self.tokens, (all, any, none)) phrase = phrase.strip() @@ -96,11 +97,11 @@ class AdvSearchBuilderDialog(QDialog, Ui_Dialog): return ans def token(self): - txt = unicode(self.text.text()).strip() + txt = unicode_type(self.text.text()).strip() if txt: if self.negate.isChecked(): txt = '!'+txt - tok = self.FIELDS[unicode(self.field.currentText())]+txt + tok = self.FIELDS[unicode_type(self.field.currentText())]+txt if re.search(r'\s', tok): tok = '"%s"'%tok return tok @@ -116,25 +117,25 @@ class AdvSearchBuilderDialog(QDialog, Ui_Dialog): ans = [] self.box_last_values = {} - name = unicode(self.name_box.text()).strip() + name = unicode_type(self.name_box.text()).strip() if name: ans.append('name:"' + self.mc + name + '"') - description = unicode(self.description_box.text()).strip() + description = unicode_type(self.description_box.text()).strip() if description: ans.append('description:"' + self.mc + description + '"') - headquarters = unicode(self.headquarters_box.text()).strip() + headquarters = unicode_type(self.headquarters_box.text()).strip() if headquarters: ans.append('headquarters:"' + self.mc + headquarters + '"') - format = unicode(self.format_box.text()).strip() + format = unicode_type(self.format_box.text()).strip() if format: ans.append('format:"' + self.mc + format + '"') - enabled = unicode(self.enabled_combo.currentText()).strip() + enabled = unicode_type(self.enabled_combo.currentText()).strip() if enabled: ans.append('enabled:' + enabled) - drm = unicode(self.drm_combo.currentText()).strip() + drm = unicode_type(self.drm_combo.currentText()).strip() if drm: ans.append('drm:' + drm) - affiliate = unicode(self.affiliate_combo.currentText()).strip() + affiliate = unicode_type(self.affiliate_combo.currentText()).strip() if affiliate: ans.append('affiliate:' + affiliate) if ans: diff --git a/src/calibre/gui2/store/config/chooser/chooser_widget.py b/src/calibre/gui2/store/config/chooser/chooser_widget.py index 0c12b78fe7..51cf23f321 100644 --- a/src/calibre/gui2/store/config/chooser/chooser_widget.py +++ b/src/calibre/gui2/store/config/chooser/chooser_widget.py @@ -10,6 +10,7 @@ from PyQt5.Qt import QWidget, QIcon, QDialog, QComboBox, QLineEdit from calibre.gui2.store.config.chooser.adv_search_builder import AdvSearchBuilderDialog from calibre.gui2.store.config.chooser.chooser_widget_ui import Ui_Form +from polyglot.builtins import unicode_type class StoreChooserWidget(QWidget, Ui_Form): @@ -31,7 +32,7 @@ class StoreChooserWidget(QWidget, Ui_Form): self.results_view.activated.connect(self.results_view.model().toggle_plugin) def do_search(self): - self.results_view.model().search(unicode(self.query.text())) + self.results_view.model().search(unicode_type(self.query.text())) def build_adv_search(self): adv = AdvSearchBuilderDialog(self) diff --git a/src/calibre/gui2/store/config/chooser/models.py b/src/calibre/gui2/store/config/chooser/models.py index ad314581cc..42a3094c5f 100644 --- a/src/calibre/gui2/store/config/chooser/models.py +++ b/src/calibre/gui2/store/config/chooser/models.py @@ -13,6 +13,7 @@ from calibre.db.search import _match, CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH from calibre.utils.config_base import prefs from calibre.utils.icu import sort_key from calibre.utils.search_query_parser import SearchQueryParser +from polyglot.builtins import unicode_type class Matches(QAbstractItemModel): @@ -182,7 +183,7 @@ class Matches(QAbstractItemModel): return descending = order == Qt.DescendingOrder self.matches.sort(None, - lambda x: sort_key(unicode(self.data_as_text(x, col))), + lambda x: sort_key(unicode_type(self.data_as_text(x, col))), descending) if reset: self.beginResetModel(), self.endResetModel() diff --git a/src/calibre/gui2/store/search/adv_search_builder.py b/src/calibre/gui2/store/search/adv_search_builder.py index b992712b1b..770ba2f53e 100644 --- a/src/calibre/gui2/store/search/adv_search_builder.py +++ b/src/calibre/gui2/store/search/adv_search_builder.py @@ -13,6 +13,7 @@ from PyQt5.Qt import (QDialog, QDialogButtonBox) from calibre.gui2.store.search.adv_search_builder_ui import Ui_Dialog from calibre.library.caches import CONTAINS_MATCH, EQUALS_MATCH from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type class AdvSearchBuilderDialog(QDialog, Ui_Dialog): @@ -77,7 +78,7 @@ class AdvSearchBuilderDialog(QDialog, Ui_Dialog): self.mc = '=' else: self.mc = '~' - all, any, phrase, none = map(lambda x: unicode(x.text()), + all, any, phrase, none = map(lambda x: unicode_type(x.text()), (self.all, self.any, self.phrase, self.none)) all, any, none = map(self.tokens, (all, any, none)) phrase = phrase.strip() @@ -96,11 +97,11 @@ class AdvSearchBuilderDialog(QDialog, Ui_Dialog): return ans def token(self): - txt = unicode(self.text.text()).strip() + txt = unicode_type(self.text.text()).strip() if txt: if self.negate.isChecked(): txt = '!'+txt - tok = self.FIELDS[unicode(self.field.currentText())]+txt + tok = self.FIELDS[unicode_type(self.field.currentText())]+txt if re.search(r'\s', tok): tok = '"%s"'%tok return tok @@ -116,16 +117,16 @@ class AdvSearchBuilderDialog(QDialog, Ui_Dialog): ans = [] self.box_last_values = {} - title = unicode(self.title_box.text()).strip() + title = unicode_type(self.title_box.text()).strip() if title: ans.append('title:"' + self.mc + title + '"') - author = unicode(self.author_box.text()).strip() + author = unicode_type(self.author_box.text()).strip() if author: ans.append('author:"' + self.mc + author + '"') - price = unicode(self.price_box.text()).strip() + price = unicode_type(self.price_box.text()).strip() if price: ans.append('price:"' + self.mc + price + '"') - format = unicode(self.format_box.text()).strip() + format = unicode_type(self.format_box.text()).strip() if format: ans.append('format:"' + self.mc + format + '"') drm = '' if self.drm_combo.currentIndex() == 0 else 'true' if self.drm_combo.currentIndex() == 1 else 'false' diff --git a/src/calibre/gui2/store/search/models.py b/src/calibre/gui2/store/search/models.py index b7ac6e11b6..7f21d130b6 100644 --- a/src/calibre/gui2/store/search/models.py +++ b/src/calibre/gui2/store/search/models.py @@ -19,6 +19,7 @@ from calibre.gui2.store.search.download_thread import DetailsThreadPool, \ CoverThreadPool from calibre.utils.icu import sort_key from calibre.utils.search_query_parser import SearchQueryParser +from polyglot.builtins import unicode_type def comparable_price(text): @@ -291,7 +292,7 @@ class Matches(QAbstractItemModel): return descending = order == Qt.DescendingOrder self.all_matches.sort(None, - lambda x: sort_key(unicode(self.data_as_text(x, col))), + lambda x: sort_key(unicode_type(self.data_as_text(x, col))), descending) self.reorder_matches() if reset: diff --git a/src/calibre/gui2/store/search/search.py b/src/calibre/gui2/store/search/search.py index e7d9698a54..a552bad3e0 100644 --- a/src/calibre/gui2/store/search/search.py +++ b/src/calibre/gui2/store/search/search.py @@ -23,6 +23,7 @@ from calibre.gui2.store.search.download_thread import SearchThreadPool, \ CacheUpdateThreadPool from calibre.gui2.store.search.search_ui import Ui_Dialog from calibre.utils.filenames import ascii_filename +from polyglot.builtins import unicode_type class SearchDialog(QDialog, Ui_Dialog): @@ -66,7 +67,7 @@ class SearchDialog(QDialog, Ui_Dialog): self.setup_store_checks() # Set the search query - if isinstance(query, (str, unicode)): + if isinstance(query, (str, unicode_type)): self.search_edit.setText(query) elif isinstance(query, dict): if 'author' in query: @@ -184,11 +185,11 @@ class SearchDialog(QDialog, Ui_Dialog): # Don't start a search if there is nothing to search for. query = [] if self.search_title.text(): - query.append(u'title2:"~%s"' % unicode(self.search_title.text()).replace('"', ' ')) + query.append(u'title2:"~%s"' % unicode_type(self.search_title.text()).replace('"', ' ')) if self.search_author.text(): - query.append(u'author2:"%s"' % unicode(self.search_author.text()).replace('"', ' ')) + query.append(u'author2:"%s"' % unicode_type(self.search_author.text()).replace('"', ' ')) if self.search_edit.text(): - query.append(unicode(self.search_edit.text())) + query.append(unicode_type(self.search_edit.text())) query = " ".join(query) if not query.strip(): error_dialog(self, _('No query'), @@ -410,7 +411,7 @@ class SearchDialog(QDialog, Ui_Dialog): self.searching = False else: self.searching = True - if unicode(self.search.text()) != self.STOP_TEXT: + if unicode_type(self.search.text()) != self.STOP_TEXT: self.search.setText(self.STOP_TEXT) if not self.pi.isAnimated(): self.pi.startAnimation() @@ -434,7 +435,7 @@ class SearchDialog(QDialog, Ui_Dialog): self.save_state() def exec_(self): - if unicode(self.search_edit.text()).strip() or unicode(self.search_title.text()).strip() or unicode(self.search_author.text()).strip(): + if unicode_type(self.search_edit.text()).strip() or unicode_type(self.search_title.text()).strip() or unicode_type(self.search_author.text()).strip(): self.do_search() return QDialog.exec_(self) diff --git a/src/calibre/gui2/store/web_control.py b/src/calibre/gui2/store/web_control.py index e3d3d464d3..802e55e232 100644 --- a/src/calibre/gui2/store/web_control.py +++ b/src/calibre/gui2/store/web_control.py @@ -19,6 +19,7 @@ from calibre.gui2.ebook_download import show_download_info from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.filenames import ascii_filename from calibre.web import get_download_filename +from polyglot.builtins import unicode_type class NPWebView(QWebView): @@ -70,7 +71,7 @@ class NPWebView(QWebView): if not self.gui: return - url = unicode(request.url().toString(NO_URL_FORMATTING)) + url = unicode_type(request.url().toString(NO_URL_FORMATTING)) cf = self.get_cookies() filename = get_download_filename(url, cf) @@ -112,15 +113,15 @@ class NPWebView(QWebView): for c in self.page().networkAccessManager().cookieJar().allCookies(): cookie = [] - domain = unicode(c.domain()) + domain = unicode_type(c.domain()) cookie.append(domain) cookie.append('TRUE' if domain.startswith('.') else 'FALSE') - cookie.append(unicode(c.path())) + cookie.append(unicode_type(c.path())) cookie.append('TRUE' if c.isSecure() else 'FALSE') - cookie.append(unicode(c.expirationDate().toTime_t())) - cookie.append(unicode(c.name())) - cookie.append(unicode(c.value())) + cookie.append(unicode_type(c.expirationDate().toTime_t())) + cookie.append(unicode_type(c.name())) + cookie.append(unicode_type(c.value())) cf.write('\t'.join(cookie)) cf.write('\n') diff --git a/src/calibre/gui2/tag_browser/model.py b/src/calibre/gui2/tag_browser/model.py index c517228ffb..a50dcfbed0 100644 --- a/src/calibre/gui2/tag_browser/model.py +++ b/src/calibre/gui2/tag_browser/model.py @@ -2,7 +2,7 @@ # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai from __future__ import (unicode_literals, division, absolute_import, print_function) -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type __license__ = 'GPL v3' __copyright__ = '2011, Kovid Goyal ' @@ -191,7 +191,7 @@ class TagTreeItem(object): # {{{ else: name = tag.name if role == Qt.DisplayRole: - return unicode(name) + return unicode_type(name) if role == Qt.EditRole: return (tag.original_name) if role == Qt.DecorationRole: @@ -745,7 +745,7 @@ class TagsModel(QAbstractItemModel): # {{{ return ans def dropMimeData(self, md, action, row, column, parent): - fmts = {unicode(x) for x in md.formats()} + fmts = {unicode_type(x) for x in md.formats()} if not fmts.intersection(set(self.mimeTypes())): return False if "application/calibre+from_library" in fmts: @@ -1071,7 +1071,7 @@ class TagsModel(QAbstractItemModel): # {{{ # set up to reposition at the same item. We can do this except if # working with the last item and that item is deleted, in which case # we position at the parent label - val = unicode(value or '').strip() + val = unicode_type(value or '').strip() if not val: error_dialog(self.gui_parent, _('Item is blank'), _('An item cannot be set to nothing. Delete it instead.')).exec_() @@ -1138,7 +1138,7 @@ class TagsModel(QAbstractItemModel): # {{{ _('The saved search name %s is already used.')%val).exec_() return False self.use_position_based_index_on_next_recount = True - self.db.saved_search_rename(unicode(item.data(role) or ''), val) + self.db.saved_search_rename(unicode_type(item.data(role) or ''), val) item.tag.name = val self.search_item_renamed.emit() # Does a refresh else: diff --git a/src/calibre/gui2/tag_browser/ui.py b/src/calibre/gui2/tag_browser/ui.py index d3de5410b3..5e3378fa52 100644 --- a/src/calibre/gui2/tag_browser/ui.py +++ b/src/calibre/gui2/tag_browser/ui.py @@ -23,6 +23,7 @@ from calibre.ebooks.metadata import title_sort from calibre.gui2.dialogs.tag_categories import TagCategories from calibre.gui2.dialogs.tag_list_editor import TagListEditor from calibre.gui2.dialogs.edit_authors_dialog import EditAuthorsDialog +from polyglot.builtins import unicode_type class TagBrowserMixin(object): # {{{ @@ -121,7 +122,7 @@ class TagBrowserMixin(object): # {{{ if new_cat not in user_cats: break i += 1 - n = new_name + unicode(i) + n = new_name + unicode_type(i) # Add the new category user_cats[new_cat] = [] db.new_api.set_pref('user_categories', user_cats) @@ -267,7 +268,7 @@ class TagBrowserMixin(object): # {{{ m.delete_item_from_all_user_categories(orig_name[item], category) for old_id in to_rename: m.rename_item_in_all_user_categories(orig_name[old_id], - category, unicode(to_rename[old_id])) + category, unicode_type(to_rename[old_id])) db.new_api.remove_items(category, to_delete) db.new_api.rename_items(category, to_rename, change_index=False) @@ -591,7 +592,7 @@ class TagBrowserWidget(QFrame): # {{{ @property def find_text(self): - return unicode(self.item_search.currentText()).strip() + return unicode_type(self.item_search.currentText()).strip() def find(self): model = self.tags_view.model() diff --git a/src/calibre/gui2/tag_browser/view.py b/src/calibre/gui2/tag_browser/view.py index 3445db6215..9e74fc44d4 100644 --- a/src/calibre/gui2/tag_browser/view.py +++ b/src/calibre/gui2/tag_browser/view.py @@ -24,6 +24,7 @@ from calibre.gui2.tag_browser.model import (TagTreeItem, TAG_SEARCH_STATES, TagsModel, DRAG_IMAGE_ROLE, COUNT_ROLE) from calibre.gui2 import config, gprefs, choose_files, pixmap_to_data, rating_font, empty_index from calibre.utils.icu import sort_key +from polyglot.builtins import unicode_type class TagDelegate(QStyledItemDelegate): # {{{ @@ -63,7 +64,7 @@ class TagDelegate(QStyledItemDelegate): # {{{ text = index.data(Qt.DisplayRole) hover = option.state & style.State_MouseOver if hover or gprefs['tag_browser_show_counts']: - count = unicode(index.data(COUNT_ROLE)) + count = unicode_type(index.data(COUNT_ROLE)) width = painter.fontMetrics().boundingRect(count).width() r = QRect(tr) r.setRight(r.right() - 1), r.setLeft(r.right() - width - 4) @@ -377,7 +378,7 @@ class TagsView(QTreeView): # {{{ with open(os.path.join(d, 'icon_' + sanitize_file_name_unicode(key)+'.png'), 'wb') as f: f.write(pixmap_to_data(p, format='PNG')) path = os.path.basename(f.name) - self._model.set_custom_category_icon(key, unicode(path)) + self._model.set_custom_category_icon(key, unicode_type(path)) self.recount() except: import traceback @@ -504,7 +505,7 @@ class TagsView(QTreeView): # {{{ if not item.category_key.startswith('@'): while item.parent != self._model.root_item: item = item.parent - category = unicode(item.name or '') + category = unicode_type(item.name or '') key = item.category_key # Verify that we are working with a field that we know something about if key not in self.db.field_metadata: diff --git a/src/calibre/gui2/tag_mapper.py b/src/calibre/gui2/tag_mapper.py index f03e0bd524..cb2baad4fa 100644 --- a/src/calibre/gui2/tag_mapper.py +++ b/src/calibre/gui2/tag_mapper.py @@ -20,6 +20,7 @@ from calibre.gui2.ui import get_gui from calibre.gui2.widgets2 import Dialog from calibre.utils.config import JSONConfig from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type tag_maps = JSONConfig('tag-map-rules') @@ -171,14 +172,14 @@ class RuleEdit(QWidget): def rule(self, rule): def sc(name): c = getattr(self, name) - idx = c.findData(unicode(rule.get(name, ''))) + idx = c.findData(unicode_type(rule.get(name, ''))) if idx < 0: idx = 0 c.setCurrentIndex(idx) sc('action'), sc('match_type') ac = self.action.currentData() - self.query.setText(intelligent_strip(ac, unicode(rule.get('query', '')))) - self.replace.setText(intelligent_strip(ac, unicode(rule.get('replace', '')))) + self.query.setText(intelligent_strip(ac, unicode_type(rule.get('query', '')))) + self.replace.setText(intelligent_strip(ac, unicode_type(rule.get('replace', '')))) def validate(self): rule = self.rule diff --git a/src/calibre/gui2/toc/location.py b/src/calibre/gui2/toc/location.py index 4602c87613..af90566fb6 100644 --- a/src/calibre/gui2/toc/location.py +++ b/src/calibre/gui2/toc/location.py @@ -19,6 +19,7 @@ from PyQt5.QtWebKit import QWebElement from calibre.ebooks.oeb.display.webview import load_html from calibre.gui2 import error_dialog, question_dialog, gprefs, secure_web_page from calibre.utils.logging import default_log +from polyglot.builtins import unicode_type class Page(QWebPage): # {{{ @@ -36,10 +37,10 @@ class Page(QWebPage): # {{{ self.setLinkDelegationPolicy(self.DelegateAllLinks) def javaScriptConsoleMessage(self, msg, lineno, msgid): - self.log(u'JS:', unicode(msg)) + self.log(u'JS:', unicode_type(msg)) def javaScriptAlert(self, frame, msg): - self.log(unicode(msg)) + self.log(unicode_type(msg)) @pyqtSlot(result=bool) def shouldInterruptJavaScript(self): @@ -47,8 +48,8 @@ class Page(QWebPage): # {{{ @pyqtSlot(QWebElement, str, str, float) def onclick(self, elem, loc, totals, frac): - elem_id = unicode(elem.attribute('id')) or None - tag = unicode(elem.tagName()).lower() + elem_id = unicode_type(elem.attribute('id')) or None + tag = unicode_type(elem.tagName()).lower() self.elem_clicked.emit(tag, frac, elem_id, json.loads(str(loc)), json.loads(str(totals))) def load_js(self): @@ -184,7 +185,7 @@ class ItemEdit(QWidget): return super(ItemEdit, self).keyPressEvent(ev) def find(self, forwards=True): - text = unicode(self.search_text.text()).strip() + text = unicode_type(self.search_text.text()).strip() flags = QWebPage.FindFlags(0) if forwards else QWebPage.FindBackward d = self.dest_list if d.count() == 1: @@ -195,9 +196,9 @@ class ItemEdit(QWidget): _('No match found for: %s')%text, show=True) delta = 1 if forwards else -1 - current = unicode(d.currentItem().data(Qt.DisplayRole) or '') + current = unicode_type(d.currentItem().data(Qt.DisplayRole) or '') next_index = (d.currentRow() + delta)%d.count() - next = unicode(d.item(next_index).data(Qt.DisplayRole) or '') + next = unicode_type(d.item(next_index).data(Qt.DisplayRole) or '') msg = '

'+_('No matches for %(text)s found in the current file [%(current)s].' ' Do you want to search in the %(which)s file [%(next)s]?') msg = msg%dict(text=text, current=current, next=next, @@ -220,7 +221,7 @@ class ItemEdit(QWidget): self.dest_list.addItems(spine_names) def current_changed(self, item): - name = self.current_name = unicode(item.data(Qt.DisplayRole) or '') + name = self.current_name = unicode_type(item.data(Qt.DisplayRole) or '') self.current_frag = None path = self.container.name_to_abspath(name) # Ensure encoding map is populated @@ -260,7 +261,7 @@ class ItemEdit(QWidget): if toc.dest: for i in xrange(self.dest_list.count()): litem = self.dest_list.item(i) - if unicode(litem.data(Qt.DisplayRole) or '') == toc.dest: + if unicode_type(litem.data(Qt.DisplayRole) or '') == toc.dest: dest_index = i frag = toc.frag break @@ -308,4 +309,4 @@ class ItemEdit(QWidget): @property def result(self): return (self.current_item, self.current_where, self.current_name, - self.current_frag, unicode(self.name.text())) + self.current_frag, unicode_type(self.name.text())) diff --git a/src/calibre/gui2/toc/main.py b/src/calibre/gui2/toc/main.py index fd986c8137..986543c682 100644 --- a/src/calibre/gui2/toc/main.py +++ b/src/calibre/gui2/toc/main.py @@ -10,7 +10,7 @@ __docformat__ = 'restructuredtext en' import sys, os, textwrap from threading import Thread from functools import partial -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from PyQt5.Qt import (QPushButton, QFrame, QMenu, QInputDialog, QCheckBox, QDialog, QVBoxLayout, QDialogButtonBox, QSize, QStackedWidget, QWidget, @@ -77,7 +77,7 @@ class XPathDialog(QDialog): # {{{ name, ok = QInputDialog.getText(self, _('Choose name'), _('Choose a name for these settings')) if ok: - name = unicode(name).strip() + name = unicode_type(name).strip() if name: saved = self.prefs.get('xpath_toc_settings', {}) # in JSON all keys have to be strings @@ -340,7 +340,7 @@ class ItemView(QFrame): # {{{ def populate_item_pane(self): item = self.current_item - name = unicode(item.data(0, Qt.DisplayRole) or '') + name = unicode_type(item.data(0, Qt.DisplayRole) or '') self.item_pane.heading.setText('

%s

'%name) self.icon_label.setPixmap(item.data(0, Qt.DecorationRole ).pixmap(32, 32)) @@ -584,33 +584,33 @@ class TreeWidget(QTreeWidget): # {{{ self.push_history() from calibre.utils.titlecase import titlecase for item in self.selectedItems(): - t = unicode(item.data(0, Qt.DisplayRole) or '') + t = unicode_type(item.data(0, Qt.DisplayRole) or '') item.setData(0, Qt.DisplayRole, titlecase(t)) def upper_case(self): self.push_history() for item in self.selectedItems(): - t = unicode(item.data(0, Qt.DisplayRole) or '') + t = unicode_type(item.data(0, Qt.DisplayRole) or '') item.setData(0, Qt.DisplayRole, icu_upper(t)) def lower_case(self): self.push_history() for item in self.selectedItems(): - t = unicode(item.data(0, Qt.DisplayRole) or '') + t = unicode_type(item.data(0, Qt.DisplayRole) or '') item.setData(0, Qt.DisplayRole, icu_lower(t)) def swap_case(self): self.push_history() from calibre.utils.icu import swapcase for item in self.selectedItems(): - t = unicode(item.data(0, Qt.DisplayRole) or '') + t = unicode_type(item.data(0, Qt.DisplayRole) or '') item.setData(0, Qt.DisplayRole, swapcase(t)) def capitalize(self): self.push_history() from calibre.utils.icu import capitalize for item in self.selectedItems(): - t = unicode(item.data(0, Qt.DisplayRole) or '') + t = unicode_type(item.data(0, Qt.DisplayRole) or '') item.setData(0, Qt.DisplayRole, capitalize(t)) def bulk_rename(self): @@ -648,7 +648,7 @@ class TreeWidget(QTreeWidget): # {{{ item = self.currentItem() def key(k): - sc = unicode(QKeySequence(k | Qt.CTRL).toString(QKeySequence.NativeText)) + sc = unicode_type(QKeySequence(k | Qt.CTRL).toString(QKeySequence.NativeText)) return ' [%s]'%sc if item is not None: @@ -657,7 +657,7 @@ class TreeWidget(QTreeWidget): # {{{ m.addAction(QIcon(I('modified.png')), _('Bulk rename all selected items'), self.bulk_rename) m.addAction(QIcon(I('trash.png')), _('Remove all selected items'), self.del_items) m.addSeparator() - ci = unicode(item.data(0, Qt.DisplayRole) or '') + ci = unicode_type(item.data(0, Qt.DisplayRole) or '') p = item.parent() or self.invisibleRootItem() idx = p.indexOfChild(item) if idx > 0: @@ -758,12 +758,12 @@ class TOCView(QWidget): # {{{ def event(self, e): if e.type() == e.StatusTip: - txt = unicode(e.tip()) or self.default_msg + txt = unicode_type(e.tip()) or self.default_msg self.hl.setText(txt) return super(TOCView, self).event(e) def item_title(self, item): - return unicode(item.data(0, Qt.DisplayRole) or '') + return unicode_type(item.data(0, Qt.DisplayRole) or '') def del_items(self): self.tocw.del_items() @@ -818,7 +818,7 @@ class TOCView(QWidget): # {{{ def data_changed(self, top_left, bottom_right): for r in xrange(top_left.row(), bottom_right.row()+1): idx = self.tocw.model().index(r, 0, top_left.parent()) - new_title = unicode(idx.data(Qt.DisplayRole) or '').strip() + new_title = unicode_type(idx.data(Qt.DisplayRole) or '').strip() toc = idx.data(Qt.UserRole) if toc is not None: toc.title = new_title or _('(Untitled)') @@ -910,7 +910,7 @@ class TOCView(QWidget): # {{{ def process_node(parent, toc_parent): for i in xrange(parent.childCount()): item = parent.child(i) - title = unicode(item.data(0, Qt.DisplayRole) or '').strip() + title = unicode_type(item.data(0, Qt.DisplayRole) or '').strip() toc = item.data(0, Qt.UserRole) dest, frag = toc.dest, toc.frag toc = toc_parent.add(title, dest, frag) diff --git a/src/calibre/gui2/tools.py b/src/calibre/gui2/tools.py index ee13557ac6..fb5112124e 100644 --- a/src/calibre/gui2/tools.py +++ b/src/calibre/gui2/tools.py @@ -22,6 +22,7 @@ from calibre.ebooks.conversion.config import ( GuiRecommendations, load_defaults, load_specifics, save_specifics, get_input_format_for_book, NoSupportedInputFormats) from calibre.gui2.convert import bulk_defaults_for_input_format +from polyglot.builtins import unicode_type def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{ @@ -64,7 +65,7 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, # {{{ temp_files = [in_file] try: - dtitle = unicode(mi.title) + dtitle = unicode_type(mi.title) except: dtitle = repr(mi.title) desc = _('Convert book %(num)d of %(total)d (%(title)s)') % \ @@ -225,7 +226,7 @@ class QueueBulk(QProgressDialog): if x[0] == 'debug_pipeline': lrecs.remove(x) try: - dtitle = unicode(mi.title) + dtitle = unicode_type(mi.title) except: dtitle = repr(mi.title) if len(dtitle) > 50: diff --git a/src/calibre/gui2/tweak_book/char_select.py b/src/calibre/gui2/tweak_book/char_select.py index 3fdd6ae5e2..d44b985da2 100644 --- a/src/calibre/gui2/tweak_book/char_select.py +++ b/src/calibre/gui2/tweak_book/char_select.py @@ -22,6 +22,7 @@ from calibre.gui2.tweak_book import tprefs from calibre.gui2.tweak_book.widgets import Dialog, BusyCursor from calibre.utils.icu import safe_chr as chr from calibre.utils.unicode_names import character_name_from_code, points_for_word +from polyglot.builtins import unicode_type ROOT = QModelIndex() @@ -766,7 +767,7 @@ class CharSelect(Dialog): self.char_view.setFocus(Qt.OtherFocusReason) def do_search(self): - text = unicode(self.search.text()).strip() + text = unicode_type(self.search.text()).strip() if not text: return self.clear_search() with BusyCursor(): diff --git a/src/calibre/gui2/tweak_book/check.py b/src/calibre/gui2/tweak_book/check.py index 6e87c2eaf7..fa299ca6d2 100644 --- a/src/calibre/gui2/tweak_book/check.py +++ b/src/calibre/gui2/tweak_book/check.py @@ -17,6 +17,7 @@ from calibre.ebooks.oeb.polish.check.main import run_checks, fix_errors from calibre.gui2 import NO_URL_FORMATTING from calibre.gui2.tweak_book import tprefs from calibre.gui2.tweak_book.widgets import BusyCursor +from polyglot.builtins import unicode_type def icon_for_level(level): @@ -100,7 +101,7 @@ class Check(QSplitter): def copy_to_clipboard(self): items = [] for item in (self.items.item(i) for i in xrange(self.items.count())): - msg = unicode(item.text()) + msg = unicode_type(item.text()) msg = prefix_for_level(item.data(Qt.UserRole).level) + msg items.append(msg) if items: @@ -116,7 +117,7 @@ class Check(QSplitter): msg, _('Click to run a check on the book'), _('Run check'))) def link_clicked(self, url): - url = unicode(url.toString(NO_URL_FORMATTING)) + url = unicode_type(url.toString(NO_URL_FORMATTING)) if url == 'activate:item': self.current_item_activated() elif url == 'run:check': diff --git a/src/calibre/gui2/tweak_book/completion/basic.py b/src/calibre/gui2/tweak_book/completion/basic.py index d8a0329160..4a46dd9774 100644 --- a/src/calibre/gui2/tweak_book/completion/basic.py +++ b/src/calibre/gui2/tweak_book/completion/basic.py @@ -21,6 +21,7 @@ from calibre.gui2.tweak_book.completion.utils import control, data, DataError from calibre.utils.ipc import eintr_retry_call from calibre.utils.matcher import Matcher from calibre.utils.icu import numeric_sort_key +from polyglot.builtins import unicode_type Request = namedtuple('Request', 'id type data query') @@ -66,10 +67,10 @@ def get_data(data_conn, data_type, data=None): return result -class Name(unicode): +class Name(unicode_type): def __new__(self, name, mime_type, spine_names): - ans = unicode.__new__(self, name) + ans = unicode_type.__new__(self, name) ans.mime_type = mime_type ans.in_spine = name in spine_names return ans diff --git a/src/calibre/gui2/tweak_book/completion/utils.py b/src/calibre/gui2/tweak_book/completion/utils.py index 67f7a588e5..b8d4a2ae0e 100644 --- a/src/calibre/gui2/tweak_book/completion/utils.py +++ b/src/calibre/gui2/tweak_book/completion/utils.py @@ -3,6 +3,8 @@ from __future__ import (unicode_literals, division, absolute_import, print_function) +from polyglot.builtins import unicode_type + __license__ = 'GPL v3' __copyright__ = '2014, Kovid Goyal ' @@ -24,4 +26,4 @@ class DataError(Exception): self.tb = tb def traceback(self): - return unicode(self) + '\n' + self.tb + return unicode_type(self) + '\n' + self.tb diff --git a/src/calibre/gui2/tweak_book/diff/main.py b/src/calibre/gui2/tweak_book/diff/main.py index 6b872327c0..6b01d12d90 100644 --- a/src/calibre/gui2/tweak_book/diff/main.py +++ b/src/calibre/gui2/tweak_book/diff/main.py @@ -24,6 +24,7 @@ from calibre.gui2.tweak_book.widgets import Dialog from calibre.gui2.widgets2 import HistoryLineEdit2 from calibre.utils.filenames import samefile from calibre.utils.icu import numeric_sort_key +from polyglot.builtins import unicode_type class BusyWidget(QWidget): # {{{ @@ -129,7 +130,7 @@ def get_decoded_raw(name): def string_diff(left, right, left_syntax=None, right_syntax=None, left_name='left', right_name='right'): - left, right = unicode(left), unicode(right) + left, right = unicode_type(left), unicode_type(right) cache = Cache() cache.set_left(left_name, left), cache.set_right(right_name, right) changed_names = {} if left == right else {left_name:right_name} @@ -316,7 +317,7 @@ class Diff(Dialog): pass def do_search(self, reverse): - text = unicode(self.search.text()) + text = unicode_type(self.search.text()) if not text.strip(): return v = self.view.view.left if self.lb.isChecked() else self.view.view.right diff --git a/src/calibre/gui2/tweak_book/diff/view.py b/src/calibre/gui2/tweak_book/diff/view.py index 8726efee39..1484fae7f6 100644 --- a/src/calibre/gui2/tweak_book/diff/view.py +++ b/src/calibre/gui2/tweak_book/diff/view.py @@ -12,7 +12,7 @@ from math import ceil from functools import partial from collections import namedtuple, OrderedDict from difflib import SequenceMatcher -from polyglot.builtins import zip +from polyglot.builtins import unicode_type, zip import regex from PyQt5.Qt import ( @@ -66,7 +66,7 @@ def beautify_text(raw, syntax): else: root = parse(raw, line_numbers=False) pretty_html_tree(None, root) - return etree.tostring(root, encoding=unicode) + return etree.tostring(root, encoding=unicode_type) class LineNumberMap(dict): # {{{ @@ -79,7 +79,7 @@ class LineNumberMap(dict): # {{{ return self def __setitem__(self, k, v): - v = unicode(v) + v = unicode_type(v) dict.__setitem__(self, k, v) self.max_width = max(self.max_width, len(v)) @@ -166,7 +166,7 @@ class TextBrowser(PlainTextEdit): # {{{ def show_context_menu(self, pos): m = QMenu(self) a = m.addAction - i = unicode(self.textCursor().selectedText()).rstrip('\0') + i = unicode_type(self.textCursor().selectedText()).rstrip('\0') if i: a(QIcon(I('edit-copy.png')), _('Copy to clipboard'), self.copy).setShortcut(QKeySequence.Copy) @@ -215,7 +215,7 @@ class TextBrowser(PlainTextEdit): # {{{ headers = dict(self.headers) if lnum in headers: cpos = self.search_header_pos - lines = unicode(self.toPlainText()).splitlines() + lines = unicode_type(self.toPlainText()).splitlines() for hn, text in self.headers: lines[hn] = text prefix, postfix = lines[lnum][:cpos], lines[lnum][cpos:] @@ -306,7 +306,7 @@ class TextBrowser(PlainTextEdit): # {{{ while block.isValid() and top <= ev.rect().bottom(): r = ev.rect() if block.isVisible() and bottom >= r.top(): - text = unicode(self.line_number_map.get(num, '')) + text = unicode_type(self.line_number_map.get(num, '')) is_start = text != '-' and num in change_starts if is_start: painter.save() diff --git a/src/calibre/gui2/tweak_book/editor/insert_resource.py b/src/calibre/gui2/tweak_book/editor/insert_resource.py index e477f1fc60..196deba219 100644 --- a/src/calibre/gui2/tweak_book/editor/insert_resource.py +++ b/src/calibre/gui2/tweak_book/editor/insert_resource.py @@ -28,6 +28,7 @@ from calibre.gui2.tweak_book.file_list import name_is_ok from calibre.ptempfile import PersistentTemporaryFile from calibre.utils.localization import get_lang, canonicalize_lang from calibre.utils.icu import numeric_sort_key +from polyglot.builtins import unicode_type class ChooseName(Dialog): # {{{ @@ -59,13 +60,13 @@ class ChooseName(Dialog): # {{{ return False def verify(self): - return name_is_ok(unicode(self.name_edit.text()), self.show_error) + return name_is_ok(unicode_type(self.name_edit.text()), self.show_error) def accept(self): if not self.verify(): return error_dialog(self, _('No name specified'), _( 'You must specify a file name for the new file, with an extension.'), show=True) - n = unicode(self.name_edit.text()).replace('\\', '/') + n = unicode_type(self.name_edit.text()).replace('\\', '/') name, ext = n.rpartition('.')[0::2] self.filename = name + '.' + ext.lower() super(ChooseName, self).accept() @@ -111,7 +112,7 @@ class ImageDelegate(QStyledItemDelegate): def paint(self, painter, option, index): QStyledItemDelegate.paint(self, painter, option, empty_index) # draw the hover and selection highlights - name = unicode(index.data(Qt.DisplayRole) or '') + name = unicode_type(index.data(Qt.DisplayRole) or '') cover = self.cover_cache.get(name, None) if cover is None: cover = self.cover_cache[name] = QPixmap() @@ -340,16 +341,16 @@ class InsertImage(Dialog): def activated(self, index): if self.for_browsing: - return self.image_activated.emit(unicode(index.data() or '')) + return self.image_activated.emit(unicode_type(index.data() or '')) self.chosen_image_is_external = False self.accept() def accept(self): - self.chosen_image = unicode(self.view.currentIndex().data() or '') + self.chosen_image = unicode_type(self.view.currentIndex().data() or '') super(InsertImage, self).accept() def filter_changed(self, *args): - f = unicode(self.filter.text()) + f = unicode_type(self.filter.text()) self.fm.setFilterFixedString(f) # }}} @@ -418,8 +419,8 @@ class ChooseFolder(Dialog): # {{{ def create_folder(self, item): text, ok = QInputDialog.getText(self, _('Folder name'), _('Enter a name for the new folder')) - if ok and unicode(text): - c = QTreeWidgetItem(item, (unicode(text),)) + if ok and unicode_type(text): + c = QTreeWidgetItem(item, (unicode_type(text),)) c.setIcon(0, QIcon(I('mimetypes/dir.png'))) for item in self.folders.selectedItems(): item.setSelected(False) @@ -429,7 +430,7 @@ class ChooseFolder(Dialog): # {{{ def folder_path(self, item): ans = [] while item is not self.root: - ans.append(unicode(item.text(0))) + ans.append(unicode_type(item.text(0))) item = item.parent() return tuple(reversed(ans)) @@ -478,15 +479,15 @@ class NewBook(Dialog): # {{{ def accept(self): with tprefs: - tprefs.set('previous_new_book_authors', unicode(self.authors.text())) + tprefs.set('previous_new_book_authors', unicode_type(self.authors.text())) tprefs.set('previous_new_book_lang', (self.languages.lang_codes or [get_lang()])[0]) self.languages.update_recently_used() super(NewBook, self).accept() @property def mi(self): - mi = Metadata(unicode(self.title.text()).strip() or _('Unknown')) - mi.authors = string_to_authors(unicode(self.authors.text()).strip()) or [_('Unknown')] + mi = Metadata(unicode_type(self.title.text()).strip() or _('Unknown')) + mi.authors = string_to_authors(unicode_type(self.authors.text()).strip()) or [_('Unknown')] mi.languages = self.languages.lang_codes or [get_lang()] return mi diff --git a/src/calibre/gui2/tweak_book/editor/smarts/html.py b/src/calibre/gui2/tweak_book/editor/smarts/html.py index e26e55d64e..c8eb521dc2 100644 --- a/src/calibre/gui2/tweak_book/editor/smarts/html.py +++ b/src/calibre/gui2/tweak_book/editor/smarts/html.py @@ -23,6 +23,7 @@ from calibre.gui2.tweak_book.editor.smarts.utils import ( no_modifiers, get_leading_whitespace_on_block, get_text_before_cursor, get_text_after_cursor, smart_home, smart_backspace, smart_tab, expand_tabs) from calibre.utils.icu import utf16_length +from polyglot.builtins import unicode_type get_offset = itemgetter(0) PARAGRAPH_SEPARATOR = '\u2029' @@ -213,7 +214,7 @@ def find_closing_tag(tag, max_tags=sys.maxint): def select_tag(cursor, tag): cursor.setPosition(tag.start_block.position() + tag.start_offset) cursor.setPosition(tag.end_block.position() + tag.end_offset + 1, cursor.KeepAnchor) - return unicode(cursor.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') + return unicode_type(cursor.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') def rename_tag(cursor, opening_tag, closing_tag, new_name, insert=False): @@ -321,10 +322,10 @@ class Smarts(NullSmarts): a = QTextEdit.ExtraSelection() a.cursor, a.format = editor.textCursor(), editor.match_paren_format a.cursor.setPosition(tag.start_block.position()), a.cursor.movePosition(a.cursor.EndOfBlock, a.cursor.KeepAnchor) - text = unicode(a.cursor.selectedText()) + text = unicode_type(a.cursor.selectedText()) start_pos = utf16_length(text[:tag.start_offset]) a.cursor.setPosition(tag.end_block.position()), a.cursor.movePosition(a.cursor.EndOfBlock, a.cursor.KeepAnchor) - text = unicode(a.cursor.selectedText()) + text = unicode_type(a.cursor.selectedText()) end_pos = utf16_length(text[:tag.end_offset + 1]) a.cursor.setPosition(tag.start_block.position() + start_pos) a.cursor.setPosition(tag.end_block.position() + end_pos, a.cursor.KeepAnchor) diff --git a/src/calibre/gui2/tweak_book/editor/snippets.py b/src/calibre/gui2/tweak_book/editor/snippets.py index 0d0f710f40..e8648c767f 100644 --- a/src/calibre/gui2/tweak_book/editor/snippets.py +++ b/src/calibre/gui2/tweak_book/editor/snippets.py @@ -24,8 +24,9 @@ from calibre.gui2.tweak_book.widgets import Dialog, PlainTextEdit from calibre.utils.config import JSONConfig from calibre.utils.icu import string_length as strlen from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import codepoint_to_chr, unicode_type -string_length = lambda x: strlen(unicode(x)) # Needed on narrow python builds, as subclasses of unicode dont work +string_length = lambda x: strlen(unicode_type(x)) # Needed on narrow python builds, as subclasses of unicode dont work KEY = Qt.Key_J MODIFIER = Qt.META if isosx else Qt.CTRL @@ -94,7 +95,7 @@ escape = unescape = None def escape_funcs(): global escape, unescape if escape is None: - escapem = {('\\' + x):unichr(i+1) for i, x in enumerate('\\${}')} + escapem = {('\\' + x):codepoint_to_chr(i+1) for i, x in enumerate('\\${}')} escape_pat = re.compile('|'.join(map(re.escape, escapem))) escape = lambda x: escape_pat.sub(lambda m: escapem[m.group()], x.replace(r'\\', '\x01')) unescapem = {v:k[1] for k, v in escapem.iteritems()} @@ -103,7 +104,7 @@ def escape_funcs(): return escape, unescape -class TabStop(unicode): +class TabStop(unicode_type): def __new__(self, raw, start_offset, tab_stops, is_toplevel=True): if raw.endswith('}'): @@ -114,7 +115,7 @@ class TabStop(unicode): for c in child_stops: c.parent = self tab_stops.extend(child_stops) - self = unicode.__new__(self, uraw) + self = unicode_type.__new__(self, uraw) if num.endswith('*'): self.takes_selection = True num = num[:-1] @@ -122,7 +123,7 @@ class TabStop(unicode): self.takes_selection = False self.num = int(num) else: - self = unicode.__new__(self, '') + self = unicode_type.__new__(self, '') self.num = int(raw[1:]) self.takes_selection = False self.start = start_offset @@ -134,7 +135,7 @@ class TabStop(unicode): def __repr__(self): return 'TabStop(text=%s num=%d start=%d is_mirror=%s takes_selection=%s is_toplevel=%s)' % ( - unicode.__repr__(self), self.num, self.start, self.is_mirror, self.takes_selection, self.is_toplevel) + unicode_type.__repr__(self), self.num, self.start, self.is_mirror, self.takes_selection, self.is_toplevel) def parse_template(template, start_offset=0, is_toplevel=True, grouped=True): diff --git a/src/calibre/gui2/tweak_book/editor/syntax/base.py b/src/calibre/gui2/tweak_book/editor/syntax/base.py index dc6a12171e..6618805549 100644 --- a/src/calibre/gui2/tweak_book/editor/syntax/base.py +++ b/src/calibre/gui2/tweak_book/editor/syntax/base.py @@ -14,6 +14,7 @@ from PyQt5.Qt import QTextCursor, QTextBlockUserData, QTextLayout, QTimer from ..themes import highlight_to_char_format from calibre.gui2.tweak_book.widgets import BusyCursor from calibre.utils.icu import utf16_length +from polyglot.builtins import unicode_type is_wide_build = sys.maxunicode >= 0x10ffff @@ -215,7 +216,7 @@ class SyntaxHighlighter(object): start_state = self.user_data_factory().state ud.clear(state=start_state, doc_name=self.doc_name) # Ensure no stale user data lingers formats = [] - for i, num, fmt in run_loop(ud, self.state_map, self.formats, unicode(block.text())): + for i, num, fmt in run_loop(ud, self.state_map, self.formats, unicode_type(block.text())): if fmt is not None: r = QTextLayout.FormatRange() r.start, r.length, r.format = i, num, fmt @@ -239,4 +240,3 @@ class SyntaxHighlighter(object): elif r.start + r.length >= preedit_start: r.length += preedit_length layout.setAdditionalFormats(formats) - diff --git a/src/calibre/gui2/tweak_book/editor/text.py b/src/calibre/gui2/tweak_book/editor/text.py index e1e9452a03..d28ae4e5d4 100644 --- a/src/calibre/gui2/tweak_book/editor/text.py +++ b/src/calibre/gui2/tweak_book/editor/text.py @@ -8,7 +8,7 @@ import os import re import textwrap import unicodedata -from polyglot.builtins import map +from polyglot.builtins import unicode_type, map from PyQt5.Qt import ( QColor, QColorDialog, QFont, QFontDatabase, QKeySequence, QPainter, QPalette, @@ -68,7 +68,7 @@ _dff = None def default_font_family(): global _dff if _dff is None: - families = set(map(unicode, QFontDatabase().families())) + families = set(map(unicode_type, QFontDatabase().families())) for x in ('Ubuntu Mono', 'Consolas', 'Liberation Mono'): if x in families: _dff = x @@ -280,7 +280,7 @@ class TextEdit(PlainTextEdit): if self.smarts.override_tab_stop_width is not None: self.tw = self.smarts.override_tab_stop_width self.setTabStopWidth(self.tw * self.space_width) - self.setPlainText(unicodedata.normalize('NFC', unicode(text))) + self.setPlainText(unicodedata.normalize('NFC', unicode_type(text))) if process_template and QPlainTextEdit.find(self, '%CURSOR%'): c = self.textCursor() c.insertText('') @@ -314,7 +314,7 @@ class TextEdit(PlainTextEdit): c.movePosition(c.NextBlock, n=lnum - 1) c.movePosition(c.StartOfLine) c.movePosition(c.EndOfLine, c.KeepAnchor) - text = unicode(c.selectedText()).rstrip('\0') + text = unicode_type(c.selectedText()).rstrip('\0') if col is None: c.movePosition(c.StartOfLine) lt = text.lstrip() @@ -373,7 +373,7 @@ class TextEdit(PlainTextEdit): if wrap: pos = m_end if reverse else m_start c.setPosition(pos, c.KeepAnchor) - raw = unicode(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') + raw = unicode_type(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') m = pat.search(raw) if m is None: return False @@ -406,7 +406,7 @@ class TextEdit(PlainTextEdit): if self.current_search_mark is None: return 0 c = self.current_search_mark.cursor - raw = unicode(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') + raw = unicode_type(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') if template is None: count = len(pat.findall(raw)) else: @@ -420,7 +420,7 @@ class TextEdit(PlainTextEdit): if getattr(template.func, 'append_final_output_to_marked', False): retval = template.end() if retval: - raw += unicode(retval) + raw += unicode_type(retval) else: template.end() show_function_debug_output(template) @@ -443,7 +443,7 @@ class TextEdit(PlainTextEdit): c = self.textCursor() c.beginEditBlock() c.movePosition(c.Start), c.movePosition(c.End, c.KeepAnchor) - text = unicode(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') + text = unicode_type(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') from calibre.ebooks.oeb.polish.css import sort_sheet text = sort_sheet(current_container(), text).cssText c.insertText(text) @@ -464,7 +464,7 @@ class TextEdit(PlainTextEdit): if wrap and not complete: pos = c.End if reverse else c.Start c.movePosition(pos, c.KeepAnchor) - raw = unicode(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') + raw = unicode_type(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') m = pat.search(raw) if m is None: return False @@ -509,7 +509,7 @@ class TextEdit(PlainTextEdit): if not found: return False else: - raw = unicode(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') + raw = unicode_type(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') m = pat.search(raw) if m is None: return False @@ -542,7 +542,7 @@ class TextEdit(PlainTextEdit): return match_pos, match_word while True: - text = unicode(c.selectedText()).rstrip('\0') + text = unicode_type(c.selectedText()).rstrip('\0') idx, word = find_first_word(text) if idx == -1: return False @@ -579,7 +579,7 @@ class TextEdit(PlainTextEdit): def replace(self, pat, template, saved_match='gui'): c = self.textCursor() - raw = unicode(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') + raw = unicode_type(c.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0') m = pat.fullmatch(raw) if m is None: # This can happen if either the user changed the selected text or @@ -606,7 +606,7 @@ class TextEdit(PlainTextEdit): self.setTextCursor(c) return True base = r'''%%s\s*=\s*['"]{0,1}%s''' % regex.escape(anchor) - raw = unicode(self.toPlainText()) + raw = unicode_type(self.toPlainText()) m = regex.search(base % 'id', raw) if m is None: m = regex.search(base % 'name', raw) @@ -713,7 +713,7 @@ class TextEdit(PlainTextEdit): c = self.textCursor() c.setPosition(block.position() + r.start) c.setPosition(c.position() + r.length, c.KeepAnchor) - return unicode(c.selectedText()) + return unicode_type(c.selectedText()) def spellcheck_locale_for_cursor(self, c): with store_locale: @@ -750,7 +750,7 @@ class TextEdit(PlainTextEdit): c = self.cursorForPosition(ev.pos()) fmt = self.syntax_format_for_cursor(c) if fmt is not None: - tt = unicode(fmt.toolTip()) + tt = unicode_type(fmt.toolTip()) if tt: QToolTip.setFont(self.tooltip_font) QToolTip.setPalette(self.tooltip_palette) @@ -785,7 +785,7 @@ class TextEdit(PlainTextEdit): right = max(c.anchor(), c.position()) # For speed we use QPlainTextEdit's toPlainText as we dont care about # spaces in this context - raw = unicode(QPlainTextEdit.toPlainText(self)) + raw = unicode_type(QPlainTextEdit.toPlainText(self)) # Make sure the left edge is not within a <> gtpos = raw.find('>', left) ltpos = raw.find('<', left) @@ -829,7 +829,7 @@ class TextEdit(PlainTextEdit): c = self.textCursor() c.setPosition(left) c.setPosition(right, c.KeepAnchor) - prev_text = unicode(c.selectedText()).rstrip('\0') + prev_text = unicode_type(c.selectedText()).rstrip('\0') c.insertText(prefix + prev_text + suffix) if prev_text: right = c.position() @@ -932,10 +932,10 @@ version="1.1" width="100%%" height="100%%" viewBox="0 0 {w} {h}" preserveAspectR c = self.textCursor() has_selection = c.hasSelection() if has_selection: - text = unicode(c.selectedText()).rstrip('\0') + text = unicode_type(c.selectedText()).rstrip('\0') else: c.setPosition(c.position() - min(c.positionInBlock(), 6), c.KeepAnchor) - text = unicode(c.selectedText()).rstrip('\0') + text = unicode_type(c.selectedText()).rstrip('\0') m = re.search(r'[a-fA-F0-9]{2,6}$', text) if m is None: return False @@ -977,7 +977,7 @@ version="1.1" width="100%%" height="100%%" viewBox="0 0 {w} {h}" preserveAspectR from calibre.gui2.tweak_book.editor.smarts.css import find_rule block = None if self.syntax == 'css': - raw = unicode(self.toPlainText()) + raw = unicode_type(self.toPlainText()) line, col = find_rule(raw, rule_address) if line is not None: block = self.document().findBlockByNumber(line - 1) diff --git a/src/calibre/gui2/tweak_book/editor/themes.py b/src/calibre/gui2/tweak_book/editor/themes.py index 25a11f5f1a..d4ced42f75 100644 --- a/src/calibre/gui2/tweak_book/editor/themes.py +++ b/src/calibre/gui2/tweak_book/editor/themes.py @@ -18,6 +18,7 @@ from calibre.gui2 import error_dialog from calibre.gui2.tweak_book import tprefs from calibre.gui2.tweak_book.editor import syntax_text_char_format from calibre.gui2.tweak_book.widgets import Dialog +from polyglot.builtins import unicode_type underline_styles = {'single', 'dash', 'dot', 'dash_dot', 'dash_dot_dot', 'wave', 'spell'} @@ -345,7 +346,7 @@ class CreateNewTheme(Dialog): @property def theme_name(self): - return unicode(self._name.text()).strip() + return unicode_type(self._name.text()).strip() def accept(self): if not self.theme_name: @@ -474,7 +475,7 @@ class Property(QWidget): l.addStretch(1) def us_changed(self): - self.data['underline'] = unicode(self.underline.currentText()) or None + self.data['underline'] = unicode_type(self.underline.currentText()) or None self.changed.emit() # Help text {{{ @@ -618,7 +619,7 @@ class ThemeEditor(Dialog): data[k] = dict(THEMES[default_theme()][k]._asdict()) for nk, nv in data[k].iteritems(): if isinstance(nv, QBrush): - data[k][nk] = unicode(nv.color().name()) + data[k][nk] = unicode_type(nv.color().name()) if extra or missing: tprefs['custom_themes'][name] = data return data @@ -632,7 +633,7 @@ class ThemeEditor(Dialog): c.setParent(None) c.deleteLater() self.properties = [] - name = unicode(self.theme.currentText()) + name = unicode_type(self.theme.currentText()) if not name: return data = self.update_theme(name) @@ -649,7 +650,7 @@ class ThemeEditor(Dialog): @property def theme_name(self): - return unicode(self.theme.currentText()) + return unicode_type(self.theme.currentText()) def changed(self): name = self.theme_name @@ -660,7 +661,7 @@ class ThemeEditor(Dialog): d = CreateNewTheme(self) if d.exec_() == d.Accepted: name = '*' + d.theme_name - base = unicode(d.base.currentText()) + base = unicode_type(d.base.currentText()) theme = {} for key, val in THEMES[base].iteritems(): theme[key] = {k:col_to_string(v.color()) if isinstance(v, QBrush) else v for k, v in val._asdict().iteritems()} diff --git a/src/calibre/gui2/tweak_book/editor/widget.py b/src/calibre/gui2/tweak_book/editor/widget.py index 4f5827b632..4f9132f994 100644 --- a/src/calibre/gui2/tweak_book/editor/widget.py +++ b/src/calibre/gui2/tweak_book/editor/widget.py @@ -24,6 +24,7 @@ from calibre.gui2.tweak_book.editor import SPELL_PROPERTY, LINK_PROPERTY, TAG_NA from calibre.gui2.tweak_book.editor.help import help_url from calibre.gui2.tweak_book.editor.text import TextEdit from calibre.utils.icu import utf16_length +from polyglot.builtins import unicode_type def create_icon(text, palette=None, sz=None, divider=2, fill='white'): @@ -211,7 +212,7 @@ class Editor(QMainWindow): def get_raw_data(self): # The EPUB spec requires NFC normalization, see section 1.3.6 of # http://www.idpf.org/epub/20/spec/OPS_2.0.1_draft.htm - return unicodedata.normalize('NFC', unicode(self.editor.toPlainText()).rstrip('\0')) + return unicodedata.normalize('NFC', unicode_type(self.editor.toPlainText()).rstrip('\0')) def replace_data(self, raw, only_if_different=True): if isinstance(raw, bytes): @@ -462,7 +463,7 @@ class Editor(QMainWindow): if not c.atStart(): c.clearSelection() c.movePosition(c.PreviousCharacter, c.KeepAnchor) - char = unicode(c.selectedText()).rstrip('\0') + char = unicode_type(c.selectedText()).rstrip('\0') return (c.blockNumber() + 1, col, char) def cut(self): @@ -486,7 +487,7 @@ class Editor(QMainWindow): def fix_html(self): if self.syntax == 'html': from calibre.ebooks.oeb.polish.pretty import fix_html - self.editor.replace_text(fix_html(current_container(), unicode(self.editor.toPlainText())).decode('utf-8')) + self.editor.replace_text(fix_html(current_container(), unicode_type(self.editor.toPlainText())).decode('utf-8')) return True return False @@ -494,7 +495,7 @@ class Editor(QMainWindow): from calibre.ebooks.oeb.polish.pretty import pretty_html, pretty_css, pretty_xml if self.syntax in {'css', 'html', 'xml'}: func = {'css':pretty_css, 'xml':pretty_xml}.get(self.syntax, pretty_html) - original_text = unicode(self.editor.toPlainText()) + original_text = unicode_type(self.editor.toPlainText()) prettied_text = func(current_container(), name, original_text).decode('utf-8') if original_text != prettied_text: self.editor.replace_text(prettied_text) diff --git a/src/calibre/gui2/tweak_book/file_list.py b/src/calibre/gui2/tweak_book/file_list.py index 7b714520f2..21f278381f 100644 --- a/src/calibre/gui2/tweak_book/file_list.py +++ b/src/calibre/gui2/tweak_book/file_list.py @@ -39,7 +39,7 @@ from calibre.gui2.tweak_book import ( from calibre.gui2.tweak_book.editor import syntax_from_mime from calibre.gui2.tweak_book.templates import template_for from calibre.utils.icu import numeric_sort_key -from polyglot.builtins import iteritems +from polyglot.builtins import iteritems, unicode_type try: from PyQt5 import sip @@ -111,7 +111,7 @@ def get_bulk_rename_settings(parent, number, msg=None, sanitize=sanitize_file_na ans = {'prefix': None, 'start': None} if d.exec_() == d.Accepted: - prefix = sanitize(unicode(d.prefix.text())) + prefix = sanitize(unicode_type(d.prefix.text())) previous[category] = prefix tprefs.set('file-list-bulk-rename-prefix', previous) num = d.num.value() @@ -132,7 +132,7 @@ class ItemDelegate(QStyledItemDelegate): # {{{ rename_requested = pyqtSignal(object, object) def setEditorData(self, editor, index): - name = unicode(index.data(NAME_ROLE) or '') + name = unicode_type(index.data(NAME_ROLE) or '') # We do this because Qt calls selectAll() unconditionally on the # editor, and we want only a part of the file name to be selected QTimer.singleShot(0, partial(self.set_editor_data, name, editor)) @@ -151,8 +151,8 @@ class ItemDelegate(QStyledItemDelegate): # {{{ editor.selectAll() def setModelData(self, editor, model, index): - newname = unicode(editor.text()) - oldname = unicode(index.data(NAME_ROLE) or '') + newname = unicode_type(editor.text()) + oldname = unicode_type(index.data(NAME_ROLE) or '') if newname != oldname: self.rename_requested.emit(oldname, newname) @@ -170,7 +170,7 @@ class ItemDelegate(QStyledItemDelegate): # {{{ suffix = '%s(%d)' % (NBSP, index.model().rowCount(index)) else: try: - suffix = NBSP + human_readable(current_container().filesize(unicode(index.data(NAME_ROLE) or ''))) + suffix = NBSP + human_readable(current_container().filesize(unicode_type(index.data(NAME_ROLE) or ''))) except EnvironmentError: suffix = NBSP + human_readable(0) br = painter.boundingRect(option.rect, Qt.AlignRight|Qt.AlignVCenter, suffix) @@ -259,13 +259,13 @@ class FileList(QTreeWidget): def current_name(self): ci = self.currentItem() if ci is not None: - return unicode(ci.data(0, NAME_ROLE) or '') + return unicode_type(ci.data(0, NAME_ROLE) or '') return '' def get_state(self): s = {'pos':self.verticalScrollBar().value()} s['expanded'] = {c for c, item in self.categories.iteritems() if item.isExpanded()} - s['selected'] = {unicode(i.data(0, NAME_ROLE) or '') for i in self.selectedItems()} + s['selected'] = {unicode_type(i.data(0, NAME_ROLE) or '') for i in self.selectedItems()} return s def set_state(self, state): @@ -274,21 +274,21 @@ class FileList(QTreeWidget): self.verticalScrollBar().setValue(state['pos']) for parent in self.categories.itervalues(): for c in (parent.child(i) for i in xrange(parent.childCount())): - name = unicode(c.data(0, NAME_ROLE) or '') + name = unicode_type(c.data(0, NAME_ROLE) or '') if name in state['selected']: c.setSelected(True) def item_from_name(self, name): for parent in self.categories.itervalues(): for c in (parent.child(i) for i in xrange(parent.childCount())): - q = unicode(c.data(0, NAME_ROLE) or '') + q = unicode_type(c.data(0, NAME_ROLE) or '') if q == name: return c def select_name(self, name, set_as_current_index=False): for parent in self.categories.itervalues(): for c in (parent.child(i) for i in xrange(parent.childCount())): - q = unicode(c.data(0, NAME_ROLE) or '') + q = unicode_type(c.data(0, NAME_ROLE) or '') c.setSelected(q == name) if q == name: self.scrollToItem(c) @@ -298,7 +298,7 @@ class FileList(QTreeWidget): def select_names(self, names, current_name=None): for parent in self.categories.itervalues(): for c in (parent.child(i) for i in xrange(parent.childCount())): - q = unicode(c.data(0, NAME_ROLE) or '') + q = unicode_type(c.data(0, NAME_ROLE) or '') c.setSelected(q in names) if q == current_name: self.scrollToItem(c) @@ -504,9 +504,9 @@ class FileList(QTreeWidget): container = current_container() ci = self.currentItem() if ci is not None: - cn = unicode(ci.data(0, NAME_ROLE) or '') - mt = unicode(ci.data(0, MIME_ROLE) or '') - cat = unicode(ci.data(0, CATEGORY_ROLE) or '') + cn = unicode_type(ci.data(0, NAME_ROLE) or '') + mt = unicode_type(ci.data(0, MIME_ROLE) or '') + cat = unicode_type(ci.data(0, CATEGORY_ROLE) or '') n = elided_text(cn.rpartition('/')[-1]) m.addAction(QIcon(I('save.png')), _('Export %s') % n, partial(self.export, cn)) if cn not in container.names_that_must_not_be_changed and cn not in container.names_that_must_not_be_removed and mt not in OEB_FONTS: @@ -540,7 +540,7 @@ class FileList(QTreeWidget): selected_map = defaultdict(list) for item in sel: - selected_map[unicode(item.data(0, CATEGORY_ROLE) or '')].append(unicode(item.data(0, NAME_ROLE) or '')) + selected_map[unicode_type(item.data(0, CATEGORY_ROLE) or '')].append(unicode_type(item.data(0, NAME_ROLE) or '')) for items in selected_map.itervalues(): items.sort(key=self.index_of_name) @@ -560,7 +560,7 @@ class FileList(QTreeWidget): for category, parent in self.categories.iteritems(): for i in xrange(parent.childCount()): item = parent.child(i) - if unicode(item.data(0, NAME_ROLE) or '') == name: + if unicode_type(item.data(0, NAME_ROLE) or '') == name: return (category, i) return (None, -1) @@ -583,7 +583,7 @@ class FileList(QTreeWidget): self.mark_requested.emit(name, 'cover') def mark_as_titlepage(self, name): - first = unicode(self.categories['text'].child(0).data(0, NAME_ROLE) or '') == name + first = unicode_type(self.categories['text'].child(0).data(0, NAME_ROLE) or '') == name move_to_start = False if not first: move_to_start = question_dialog(self, _('Not first item'), _( @@ -606,7 +606,7 @@ class FileList(QTreeWidget): ' internally. The filenames you see are automatically generated from the' ' internal structures of the original file.') % current_container().book_type.upper(), show=True) return - names = {unicode(item.data(0, NAME_ROLE) or '') for item in self.selectedItems()} + names = {unicode_type(item.data(0, NAME_ROLE) or '') for item in self.selectedItems()} bad = names & current_container().names_that_must_not_be_changed if bad: error_dialog(self, _('Cannot rename'), @@ -618,7 +618,7 @@ class FileList(QTreeWidget): def request_bulk_rename(self): names = self.request_rename_common() if names is not None: - categories = Counter(unicode(item.data(0, CATEGORY_ROLE) or '') for item in self.selectedItems()) + categories = Counter(unicode_type(item.data(0, CATEGORY_ROLE) or '') for item in self.selectedItems()) settings = get_bulk_rename_settings(self, len(names), category=categories.most_common(1)[0][0], allow_spine_order=True) fmt, num = settings['prefix'], settings['start'] if fmt is not None: @@ -653,7 +653,7 @@ class FileList(QTreeWidget): @property def selected_names(self): - ans = {unicode(item.data(0, NAME_ROLE) or '') for item in self.selectedItems()} + ans = {unicode_type(item.data(0, NAME_ROLE) or '') for item in self.selectedItems()} ans.discard('') return ans @@ -672,9 +672,9 @@ class FileList(QTreeWidget): text = self.categories['text'] children = (text.child(i) for i in xrange(text.childCount())) - spine_removals = [(unicode(item.data(0, NAME_ROLE) or ''), item.isSelected()) for item in children] - other_removals = {unicode(item.data(0, NAME_ROLE) or '') for item in self.selectedItems() - if unicode(item.data(0, CATEGORY_ROLE) or '') != 'text'} + spine_removals = [(unicode_type(item.data(0, NAME_ROLE) or ''), item.isSelected()) for item in children] + other_removals = {unicode_type(item.data(0, NAME_ROLE) or '') for item in self.selectedItems() + if unicode_type(item.data(0, CATEGORY_ROLE) or '') != 'text'} self.delete_requested.emit(spine_removals, other_removals) def delete_done(self, spine_removals, other_removals): @@ -686,7 +686,7 @@ class FileList(QTreeWidget): if category != 'text': for i in xrange(parent.childCount()): child = parent.child(i) - if unicode(child.data(0, NAME_ROLE) or '') in other_removals: + if unicode_type(child.data(0, NAME_ROLE) or '') in other_removals: removals.append(child) # The sorting by index is necessary otherwise Qt crashes with recursive @@ -723,7 +723,7 @@ class FileList(QTreeWidget): if current_order != pre_drop_order: order = [] for child in (text.child(i) for i in xrange(text.childCount())): - name = unicode(child.data(0, NAME_ROLE) or '') + name = unicode_type(child.data(0, NAME_ROLE) or '') linear = bool(child.data(0, LINEAR_ROLE)) order.append([name, linear]) # Ensure that all non-linear items are at the end, any non-linear @@ -734,14 +734,14 @@ class FileList(QTreeWidget): self.reorder_spine.emit(order) def item_double_clicked(self, item, column): - category = unicode(item.data(0, CATEGORY_ROLE) or '') + category = unicode_type(item.data(0, CATEGORY_ROLE) or '') if category: self._request_edit(item) def _request_edit(self, item): - category = unicode(item.data(0, CATEGORY_ROLE) or '') - mime = unicode(item.data(0, MIME_ROLE) or '') - name = unicode(item.data(0, NAME_ROLE) or '') + category = unicode_type(item.data(0, CATEGORY_ROLE) or '') + mime = unicode_type(item.data(0, MIME_ROLE) or '') + name = unicode_type(item.data(0, NAME_ROLE) or '') syntax = {'text':'html', 'styles':'css'}.get(category, None) self.edit_file.emit(name, syntax, mime) @@ -760,7 +760,7 @@ class FileList(QTreeWidget): if backwards: items = reversed(tuple(items)) for item in items: - name = unicode(item.data(0, NAME_ROLE) or '') + name = unicode_type(item.data(0, NAME_ROLE) or '') if seen_current: self._request_edit(item) return True @@ -776,9 +776,9 @@ class FileList(QTreeWidget): def searchable_names(self): ans = {'text':OrderedDict(), 'styles':OrderedDict(), 'selected':OrderedDict(), 'open':OrderedDict()} for item in self.all_files: - category = unicode(item.data(0, CATEGORY_ROLE) or '') - mime = unicode(item.data(0, MIME_ROLE) or '') - name = unicode(item.data(0, NAME_ROLE) or '') + category = unicode_type(item.data(0, CATEGORY_ROLE) or '') + mime = unicode_type(item.data(0, MIME_ROLE) or '') + name = unicode_type(item.data(0, NAME_ROLE) or '') ok = category in {'text', 'styles'} if ok: ans[category][name] = syntax_from_mime(name, mime) @@ -838,7 +838,7 @@ class FileList(QTreeWidget): def link_stylesheets(self, names): s = self.categories['styles'] - sheets = [unicode(s.child(i).data(0, NAME_ROLE) or '') for i in xrange(s.childCount())] + sheets = [unicode_type(s.child(i).data(0, NAME_ROLE) or '') for i in xrange(s.childCount())] if not sheets: return error_dialog(self, _('No stylesheets'), _( 'This book currently has no stylesheets. You must first create a stylesheet' @@ -871,7 +871,7 @@ class FileList(QTreeWidget): l.addWidget(bb) if d.exec_() == d.Accepted: tprefs['remove_existing_links_when_linking_sheets'] = r.isChecked() - sheets = [unicode(s.item(il).text()) for il in xrange(s.count()) if s.item(il).checkState() == Qt.Checked] + sheets = [unicode_type(s.item(il).text()) for il in xrange(s.count()) if s.item(il).checkState() == Qt.Checked] if sheets: self.link_stylesheets_requested.emit(names, sheets, r.isChecked()) @@ -937,7 +937,7 @@ class NewFileDialog(QDialog): # {{{ @property def name_is_ok(self): - return name_is_ok(unicode(self.name.text()), self.show_error) + return name_is_ok(unicode_type(self.name.text()), self.show_error) def update_ok(self, *args): self.ok_button.setEnabled(self.name_is_ok) @@ -947,7 +947,7 @@ class NewFileDialog(QDialog): # {{{ return error_dialog(self, _('No name specified'), _( 'You must specify a name for the new file, with an extension, for example, chapter1.html'), show=True) tprefs['auto_link_stylesheets'] = self.link_css.isChecked() - name = unicode(self.name.text()) + name = unicode_type(self.name.text()) name, ext = name.rpartition('.')[0::2] name = (name + '.' + ext.lower()).replace('\\', '/') mt = guess_type(name) diff --git a/src/calibre/gui2/tweak_book/function_replace.py b/src/calibre/gui2/tweak_book/function_replace.py index 0aad311d26..20f6f1d1cd 100644 --- a/src/calibre/gui2/tweak_book/function_replace.py +++ b/src/calibre/gui2/tweak_book/function_replace.py @@ -23,12 +23,13 @@ from calibre.utils.config import JSONConfig from calibre.utils.icu import capitalize, upper, lower, swapcase from calibre.utils.titlecase import titlecase from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type user_functions = JSONConfig('editor-search-replace-functions') def compile_code(src, name=''): - if not isinstance(src, unicode): + if not isinstance(src, unicode_type): match = re.search(r'coding[:=]\s*([-\w.]+)', src[:200]) enc = match.group(1) if match else 'utf-8' src = src.decode(enc) diff --git a/src/calibre/gui2/tweak_book/live_css.py b/src/calibre/gui2/tweak_book/live_css.py index 487585900a..fa32e84c7e 100644 --- a/src/calibre/gui2/tweak_book/live_css.py +++ b/src/calibre/gui2/tweak_book/live_css.py @@ -18,6 +18,7 @@ from calibre.gui2.tweak_book import editors, actions, tprefs from calibre.gui2.tweak_book.editor.themes import get_theme, theme_color from calibre.gui2.tweak_book.editor.text import default_font_family from css_selectors import parse, SelectorError +from polyglot.builtins import unicode_type class Heading(QWidget): # {{{ @@ -474,7 +475,7 @@ class LiveCSS(QWidget): def read_data(self, sourceline, tags): mf = self.preview.view.page().mainFrame() tags = [x.lower() for x in tags] - result = unicode(mf.evaluateJavaScript( + result = unicode_type(mf.evaluateJavaScript( 'window.calibre_preview_integration.live_css(%s, %s)' % ( json.dumps(sourceline), json.dumps(tags))) or '') try: diff --git a/src/calibre/gui2/tweak_book/manage_fonts.py b/src/calibre/gui2/tweak_book/manage_fonts.py index f43eac865e..3be05b2f4c 100644 --- a/src/calibre/gui2/tweak_book/manage_fonts.py +++ b/src/calibre/gui2/tweak_book/manage_fonts.py @@ -22,6 +22,7 @@ from calibre.gui2.tweak_book.widgets import Dialog, BusyCursor from calibre.utils.icu import primary_sort_key as sort_key from calibre.utils.fonts.scanner import font_scanner, NoFonts from calibre.utils.fonts.metadata import FontMetadata, UnsupportedFont +from polyglot.builtins import unicode_type def show_font_face_rule_for_font_file(file_data, added_name, parent=None): @@ -179,7 +180,7 @@ class ChangeFontFamily(Dialog): @property def family(self): - return unicode(self._family.text()) + return unicode_type(self._family.text()) @property def normalized_family(self): diff --git a/src/calibre/gui2/tweak_book/plugin.py b/src/calibre/gui2/tweak_book/plugin.py index ecd2a50656..e06f862625 100644 --- a/src/calibre/gui2/tweak_book/plugin.py +++ b/src/calibre/gui2/tweak_book/plugin.py @@ -14,6 +14,7 @@ from calibre import prints from calibre.customize.ui import all_edit_book_tool_plugins from calibre.gui2.tweak_book import tprefs, current_container from calibre.gui2.tweak_book.boss import get_boss +from polyglot.builtins import unicode_type class Tool(object): @@ -82,7 +83,7 @@ class Tool(object): :param description: An optional longer description of this action, it will be used in the preferences entry for this shortcut. ''' - short_text = short_text or unicode(qaction.text()).replace('&&', '\0').replace('&', '').replace('\0', '&') + short_text = short_text or unicode_type(qaction.text()).replace('&&', '\0').replace('&', '').replace('\0', '&') self.gui.keyboard.register_shortcut( self.name + '_' + unique_name, short_text, default_keys=default_keys, action=qaction, description=description or '', group=_('Plugins')) diff --git a/src/calibre/gui2/tweak_book/preferences.py b/src/calibre/gui2/tweak_book/preferences.py index ea66fe41ec..6c1b9f720f 100644 --- a/src/calibre/gui2/tweak_book/preferences.py +++ b/src/calibre/gui2/tweak_book/preferences.py @@ -8,7 +8,7 @@ __copyright__ = '2013, Kovid Goyal ' from operator import attrgetter, methodcaller from collections import namedtuple -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from itertools import product from copy import copy, deepcopy @@ -75,7 +75,7 @@ class BasicSettings(QWidget): # {{{ widget.addItem(human or key, key) def getter(w): - ans = unicode(w.itemData(w.currentIndex()) or '') + ans = unicode_type(w.itemData(w.currentIndex()) or '') return {none_val:None}.get(ans, ans) def setter(w, val): @@ -102,7 +102,7 @@ class BasicSettings(QWidget): # {{{ widget.defaults = prefs.defaults[name] def getter(w): - return list(map(unicode, (w.item(i).text() for i in xrange(w.count())))) + return list(map(unicode_type, (w.item(i).text() for i in xrange(w.count())))) def setter(w, val): order_map = {x:i for i, x in enumerate(val)} @@ -342,7 +342,7 @@ class PreviewSettings(BasicSettings): self.setLayout(l) def family_getter(w): - return unicode(w.currentFont().family()) + return unicode_type(w.currentFont().family()) def family_setter(w, val): w.setCurrentFont(QFont(val)) @@ -453,13 +453,13 @@ class ToolbarSettings(QWidget): prefs = prefs or tprefs val = self.original_settings = {} for i in xrange(1, self.bars.count()): - name = unicode(self.bars.itemData(i) or '') + name = unicode_type(self.bars.itemData(i) or '') val[name] = copy(prefs[name]) self.current_settings = deepcopy(val) @property def current_name(self): - return unicode(self.bars.itemData(self.bars.currentIndex()) or '') + return unicode_type(self.bars.itemData(self.bars.currentIndex()) or '') def build_lists(self): from calibre.gui2.tweak_book.plugin import plugin_toolbar_actions @@ -483,12 +483,12 @@ class ToolbarSettings(QWidget): ic = ac.icon() if not ic or ic.isNull(): ic = blank - ans = QListWidgetItem(ic, unicode(ac.text()).replace('&', ''), parent) + ans = QListWidgetItem(ic, unicode_type(ac.text()).replace('&', ''), parent) ans.setData(Qt.UserRole, key) ans.setToolTip(ac.toolTip()) return ans - for key, ac in sorted(all_items.iteritems(), key=lambda k_ac: unicode(k_ac[1].text())): + for key, ac in sorted(all_items.iteritems(), key=lambda k_ac: unicode_type(k_ac[1].text())): if key not in applied: to_item(key, ac, self.available) if name == 'global_book_toolbar' and 'donate' not in applied: @@ -539,7 +539,7 @@ class ToolbarSettings(QWidget): s = self.current_settings[self.current_name] except KeyError: return - names = [unicode(i.data(Qt.UserRole) or '') for i in self.available.selectedItems()] + names = [unicode_type(i.data(Qt.UserRole) or '') for i in self.available.selectedItems()] if not names: return for n in names: @@ -627,7 +627,7 @@ class TemplatesDialog(Dialog): # {{{ @property def current_syntax(self): - return unicode(self.syntaxes.currentText()) + return unicode_type(self.syntaxes.currentText()) def show_template(self): from calibre.gui2.tweak_book.templates import raw_template_for @@ -645,7 +645,7 @@ class TemplatesDialog(Dialog): # {{{ def _save_syntax(self): custom = tprefs['templates'] - custom[self.current_syntax] = unicode(self.editor.toPlainText()) + custom[self.current_syntax] = unicode_type(self.editor.toPlainText()) tprefs['templates'] = custom def restore_defaults(self): diff --git a/src/calibre/gui2/tweak_book/preview.py b/src/calibre/gui2/tweak_book/preview.py index 90b2e383bf..2eec8f531e 100644 --- a/src/calibre/gui2/tweak_book/preview.py +++ b/src/calibre/gui2/tweak_book/preview.py @@ -9,7 +9,7 @@ __copyright__ = '2013, Kovid Goyal ' import time, textwrap, json from bisect import bisect_right from base64 import b64encode -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from threading import Thread from Queue import Queue, Empty from functools import partial @@ -278,7 +278,7 @@ class WebPage(QWebPage): self.init_javascript() def javaScriptConsoleMessage(self, msg, lineno, source_id): - prints('preview js:%s:%s:'%(unicode(source_id), lineno), unicode(msg)) + prints('preview js:%s:%s:'%(unicode_type(source_id), lineno), unicode_type(msg)) def init_javascript(self): if not hasattr(self, 'js'): @@ -294,7 +294,7 @@ class WebPage(QWebPage): @pyqtSlot(str, str, str) def request_sync(self, tag_name, href, sourceline_address): try: - self.sync_requested.emit(unicode(tag_name), unicode(href), json.loads(unicode(sourceline_address))) + self.sync_requested.emit(unicode_type(tag_name), unicode_type(href), json.loads(unicode_type(sourceline_address))) except (TypeError, ValueError, OverflowError, AttributeError): pass @@ -305,7 +305,7 @@ class WebPage(QWebPage): @pyqtSlot(str, str) def request_split(self, loc, totals): actions['split-in-preview'].setChecked(False) - loc, totals = json.loads(unicode(loc)), json.loads(unicode(totals)) + loc, totals = json.loads(unicode_type(loc)), json.loads(unicode_type(totals)) if not loc or not totals: return error_dialog(self.view(), _('Invalid location'), _('Cannot split on the body tag'), show=True) @@ -400,7 +400,7 @@ class WebView(QWebView): p = self.page() mf = p.mainFrame() r = mf.hitTestContent(ev.pos()) - url = unicode(r.linkUrl().toString(NO_URL_FORMATTING)).strip() + url = unicode_type(r.linkUrl().toString(NO_URL_FORMATTING)).strip() ca = self.pageAction(QWebPage.Copy) if ca.isEnabled(): menu.addAction(ca) @@ -483,7 +483,7 @@ class Preview(QWidget): self.bar.addAction(ac) def find(self, direction): - text = unicode(self.search.text()) + text = unicode_type(self.search.text()) self.view.findText(text, QWebPage.FindWrapsAroundDocument | ( QWebPage.FindBackward if direction == 'prev' else QWebPage.FindFlags(0))) diff --git a/src/calibre/gui2/tweak_book/search.py b/src/calibre/gui2/tweak_book/search.py index baa22e4c80..b45f566b2c 100644 --- a/src/calibre/gui2/tweak_book/search.py +++ b/src/calibre/gui2/tweak_book/search.py @@ -34,6 +34,7 @@ from calibre.gui2.tweak_book.widgets import BusyCursor from calibre.gui2.widgets2 import FlowLayout, HistoryComboBox from calibre.utils.icu import primary_contains from calibre.ebooks.conversion.search_replace import REGEX_FLAGS, compile_regular_expression +src/calibre/gui2/tweak_book/preferences.py # The search panel {{{ @@ -365,7 +366,7 @@ class SearchWidget(QWidget): @dynamic_property def find(self): def fget(self): - return unicode(self.find_text.text()) + return unicode_type(self.find_text.text()) def fset(self, val): self.find_text.setText(val) @@ -376,7 +377,7 @@ class SearchWidget(QWidget): def fget(self): if self.mode == 'function': return self.functions.text() - return unicode(self.replace_text.text()) + return unicode_type(self.replace_text.text()) def fset(self, val): self.replace_text.setText(val) @@ -614,7 +615,7 @@ class SearchesModel(QAbstractListModel): return None def do_filter(self, text): - text = unicode(text) + text = unicode_type(text) self.beginResetModel() self.filtered_searches = [] for i, search in enumerate(self.searches): @@ -797,7 +798,7 @@ class EditSearch(QFrame): # {{{ @property def current_search(self): search = self.search.copy() - f = unicode(self.find.toPlainText()) + f = unicode_type(self.find.toPlainText()) search['find'] = f search['dot_all'] = bool(self.dot_all.isChecked()) search['case_sensitive'] = bool(self.case_sensitive.isChecked()) @@ -805,7 +806,7 @@ class EditSearch(QFrame): # {{{ if search['mode'] == 'function': r = self.function.text() else: - r = unicode(self.replace.toPlainText()) + r = unicode_type(self.replace.toPlainText()) search['replace'] = r return search @@ -824,7 +825,7 @@ class EditSearch(QFrame): # {{{ search = self.search search['name'] = n - f = unicode(self.find.toPlainText()) + f = unicode_type(self.find.toPlainText()) if not f: error_dialog(self, _('Must specify find'), _( 'You must specify a find expression'), show=True) @@ -839,7 +840,7 @@ class EditSearch(QFrame): # {{{ 'You must specify a function name in Function-Regex mode'), show=True) return False else: - r = unicode(self.replace.toPlainText()) + r = unicode_type(self.replace.toPlainText()) search['replace'] = r search['dot_all'] = bool(self.dot_all.isChecked()) diff --git a/src/calibre/gui2/tweak_book/spell.py b/src/calibre/gui2/tweak_book/spell.py index 9a2e12a757..d592e98466 100644 --- a/src/calibre/gui2/tweak_book/spell.py +++ b/src/calibre/gui2/tweak_book/spell.py @@ -37,6 +37,7 @@ from calibre.spell.import_from import import_from_oxt from calibre.spell.break_iterator import split_into_words from calibre.utils.localization import calibre_langcode_to_name, get_language, get_lang, canonicalize_lang from calibre.utils.icu import sort_key, primary_sort_key, primary_contains, contains +from polyglot.builtins import unicode_type LANG = 0 COUNTRY = 1 @@ -107,7 +108,7 @@ class AddDictionary(QDialog): # {{{ @property def nickname(self): - return unicode(self.nick.text()).strip() + return unicode_type(self.nick.text()).strip() def accept(self): nick = self.nickname @@ -117,7 +118,7 @@ class AddDictionary(QDialog): # {{{ if nick in {d.name for d in custom_dictionaries()}: return error_dialog(self, _('Nickname already used'), _( 'A dictionary with the nick name "%s" already exists.') % nick, show=True) - oxt = unicode(self.path.text()) + oxt = unicode_type(self.path.text()) try: num = import_from_oxt(oxt, nick) except: @@ -243,7 +244,7 @@ class ManageUserDictionaries(Dialog): name, ok = QInputDialog.getText(self, _('New dictionary'), _( 'Name of the new dictionary')) if ok: - name = unicode(name) + name = unicode_type(name) if name in {d.name for d in dictionaries.all_user_dictionaries}: return error_dialog(self, _('Already used'), _( 'A dictionary with the name %s already exists') % name, show=True) @@ -268,7 +269,7 @@ class ManageUserDictionaries(Dialog): name, ok = QInputDialog.getText(self, _('New name'), _( 'New name for the dictionary')) if ok: - name = unicode(name) + name = unicode_type(name) if name == d.name: return if name in {d.name for d in dictionaries.all_user_dictionaries}: @@ -324,7 +325,7 @@ class ManageUserDictionaries(Dialog): if d.exec_() != d.Accepted: return d.loc.update_recently_used() - word = unicode(w.text()) + word = unicode_type(w.text()) lang = (loc.lang_codes or [canonicalize_lang(get_lang())])[0] if not word: return @@ -365,7 +366,7 @@ class ManageUserDictionaries(Dialog): if not lc: return error_dialog(self, _('Must specify language'), _( 'You must specify a language to import words'), show=True) - words = set(filter(None, [x.strip() for x in unicode(w.toPlainText()).splitlines()])) + words = set(filter(None, [x.strip() for x in unicode_type(w.toPlainText()).splitlines()])) lang = lc[0] words = {(w, lang) for w in words} - self.current_dictionary.words if dictionaries.add_to_user_dictionary(self.current_dictionary.name, words, DictionaryLocale(lang, None)): @@ -465,8 +466,8 @@ class ManageDictionaries(Dialog): # {{{ def data_changed(self, item, column): if column == 0 and item.type() == DICTIONARY: d = item.data(0, Qt.UserRole) - if not d.builtin and unicode(item.text(0)) != d.name: - rename_dictionary(d, unicode(item.text(0))) + if not d.builtin and unicode_type(item.text(0)) != d.name: + rename_dictionary(d, unicode_type(item.text(0))) def build_dictionaries(self, reread=False): all_dictionaries = builtin_dictionaries() | custom_dictionaries(reread=reread) @@ -549,7 +550,7 @@ class ManageDictionaries(Dialog): # {{{ pc.setText((_( 'This is already the preferred variant for the {1} language') if preferred else _( 'Use this as the preferred variant for the {1} language')).format( - unicode(item.text(0)), unicode(item.parent().text(0)))) + unicode_type(item.text(0)), unicode_type(item.parent().text(0)))) pc.setEnabled(not preferred) def set_preferred_country(self): @@ -558,9 +559,9 @@ class ManageDictionaries(Dialog): # {{{ bf.setBold(True) for x in (item.parent().child(i) for i in xrange(item.parent().childCount())): x.setData(0, Qt.FontRole, bf if x is item else None) - lc = unicode(item.parent().data(0, Qt.UserRole)) + lc = unicode_type(item.parent().data(0, Qt.UserRole)) pl = dprefs['preferred_locales'] - pl[lc] = '%s-%s' % (lc, unicode(item.data(0, Qt.UserRole))) + pl[lc] = '%s-%s' % (lc, unicode_type(item.data(0, Qt.UserRole))) dprefs['preferred_locales'] = pl def init_dictionary(self, item): @@ -579,8 +580,8 @@ class ManageDictionaries(Dialog): # {{{ bf.setItalic(True) for x in (item.parent().child(i) for i in xrange(item.parent().childCount())): x.setData(0, Qt.FontRole, bf if x is item else None) - cc = unicode(item.parent().data(0, Qt.UserRole)) - lc = unicode(item.parent().parent().data(0, Qt.UserRole)) + cc = unicode_type(item.parent().data(0, Qt.UserRole)) + lc = unicode_type(item.parent().parent().data(0, Qt.UserRole)) d = item.data(0, Qt.UserRole) locale = '%s-%s' % (lc, cc) pl = dprefs['preferred_dictionaries'] @@ -985,7 +986,7 @@ class SpellCheck(Dialog): m.show_only_misspelt = hh.isSectionHidden(3) self.ignore_button = b = QPushButton(_('&Ignore')) - b.ign_text, b.unign_text = unicode(b.text()), _('Un&ignore') + b.ign_text, b.unign_text = unicode_type(b.text()), _('Un&ignore') b.ign_tt = _('Ignore the current word for the rest of this session') b.unign_tt = _('Stop ignoring the current word') b.clicked.connect(self.toggle_ignore) @@ -994,7 +995,7 @@ class SpellCheck(Dialog): h.setStretch(0, 1) l.addWidget(b), l.addSpacing(20) self.add_button = b = QPushButton(_('Add word to &dictionary:')) - b.add_text, b.remove_text = unicode(b.text()), _('Remove from &dictionaries') + b.add_text, b.remove_text = unicode_type(b.text()), _('Remove from &dictionaries') b.add_tt = _('Add the current word to the specified user dictionary') b.remove_tt = _('Remove the current word from all active user dictionaries') b.clicked.connect(self.add_remove) @@ -1059,7 +1060,7 @@ class SpellCheck(Dialog): def search_type_changed(self): tprefs['spell_check_case_sensitive_search'] = bool(self.case_sensitive_search.isChecked()) - if unicode(self.filter_text.text()).strip(): + if unicode_type(self.filter_text.text()).strip(): self.do_filter() def show_next_occurrence(self): @@ -1072,7 +1073,7 @@ class SpellCheck(Dialog): self.find_word.emit(w, self.words_model.words[w]) def initialize_user_dictionaries(self): - ct = unicode(self.user_dictionaries.currentText()) + ct = unicode_type(self.user_dictionaries.currentText()) self.user_dictionaries.clear() self.user_dictionaries.addItems([d.name for d in dictionaries.active_user_dictionaries]) if ct: @@ -1147,7 +1148,7 @@ class SpellCheck(Dialog): w = self.words_model.word_for_row(row) if w is None: return - new_word = unicode(self.suggested_word.text()) + new_word = unicode_type(self.suggested_word.text()) self.change_requested.emit(w, new_word) def change_word_after_update(self, w, new_word): @@ -1203,7 +1204,7 @@ class SpellCheck(Dialog): current = self.words_view.currentIndex() if current.isValid(): if self.user_dictionaries.isVisible(): # add - udname = unicode(self.user_dictionaries.currentText()) + udname = unicode_type(self.user_dictionaries.currentText()) self.words_model.add_word(current.row(), udname) else: self.words_model.remove_word(current.row()) @@ -1225,7 +1226,7 @@ class SpellCheck(Dialog): self.__current_word = None def do_filter(self): - text = unicode(self.filter_text.text()).strip() + text = unicode_type(self.filter_text.text()).strip() with self: self.words_model.filter(text) diff --git a/src/calibre/gui2/tweak_book/text_search.py b/src/calibre/gui2/tweak_book/text_search.py index 33f453aabe..48ad66aea2 100644 --- a/src/calibre/gui2/tweak_book/text_search.py +++ b/src/calibre/gui2/tweak_book/text_search.py @@ -17,6 +17,7 @@ from calibre.gui2.tweak_book import tprefs, editors, current_container from calibre.gui2.tweak_book.search import get_search_regex, InvalidRegex, initialize_search_request from calibre.gui2.tweak_book.widgets import BusyCursor from calibre.gui2.widgets2 import HistoryComboBox +from polyglot.builtins import unicode_type # UI {{{ @@ -182,7 +183,7 @@ def run_text_search(search, current_editor, current_editor_name, searchable_name else: root = current_container().parsed(fname) if hasattr(root, 'xpath'): - raw = tostring(root, method='text', encoding=unicode, with_tail=True) + raw = tostring(root, method='text', encoding=unicode_type, with_tail=True) else: raw = current_container().raw_data(fname) if pat.search(raw) is not None: diff --git a/src/calibre/gui2/tweak_book/toc.py b/src/calibre/gui2/tweak_book/toc.py index 722d0e7361..d2c0de0061 100644 --- a/src/calibre/gui2/tweak_book/toc.py +++ b/src/calibre/gui2/tweak_book/toc.py @@ -16,6 +16,7 @@ from calibre.ebooks.oeb.polish.toc import commit_toc, get_toc from calibre.gui2 import error_dialog from calibre.gui2.toc.main import TOCView, ItemEdit from calibre.gui2.tweak_book import current_container, TOP, actions, tprefs +from polyglot.builtins import unicode_type class TOCEditor(QDialog): @@ -192,8 +193,8 @@ class TOCViewer(QWidget): def emit_navigate(self, *args): item = self.view.currentItem() if item is not None: - dest = unicode(item.data(0, DEST_ROLE) or '') - frag = unicode(item.data(0, FRAG_ROLE) or '') + dest = unicode_type(item.data(0, DEST_ROLE) or '') + frag = unicode_type(item.data(0, FRAG_ROLE) or '') if not frag: frag = TOP self.navigate_requested.emit(dest, frag) diff --git a/src/calibre/gui2/tweak_book/ui.py b/src/calibre/gui2/tweak_book/ui.py index 403b530f81..8e27f78496 100644 --- a/src/calibre/gui2/tweak_book/ui.py +++ b/src/calibre/gui2/tweak_book/ui.py @@ -9,7 +9,7 @@ __copyright__ = '2013, Kovid Goyal ' import os from functools import partial from itertools import product -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from PyQt5.Qt import ( QDockWidget, Qt, QLabel, QIcon, QAction, QApplication, QWidget, QEvent, @@ -273,7 +273,7 @@ class Main(MainWindow): self.cursor_position_widget = CursorPositionWidget(self) self.status_bar.addPermanentWidget(self.cursor_position_widget) self.status_bar_default_msg = la = QLabel(' ' + _('{0} {1} created by {2}').format(__appname__, get_version(), 'Kovid Goyal')) - la.base_template = unicode(la.text()) + la.base_template = unicode_type(la.text()) self.status_bar.addWidget(la) f = self.status_bar.font() f.setBold(True) @@ -324,7 +324,7 @@ class Main(MainWindow): if isinstance(keys, type('')): keys = (keys,) self.keyboard.register_shortcut( - sid, unicode(ac.text()).replace('&', ''), default_keys=keys, description=description, action=ac, group=group) + sid, unicode_type(ac.text()).replace('&', ''), default_keys=keys, description=description, action=ac, group=group) self.addAction(ac) return ac @@ -622,7 +622,7 @@ class Main(MainWindow): if self.plugin_menu_actions: e = b.addMenu(_('&Plugins')) - for ac in sorted(self.plugin_menu_actions, key=lambda x:sort_key(unicode(x.text()))): + for ac in sorted(self.plugin_menu_actions, key=lambda x:sort_key(unicode_type(x.text()))): e.addAction(ac) e = b.addMenu(_('&Help')) @@ -674,7 +674,7 @@ class Main(MainWindow): bar.addAction(actions[ac]) except KeyError: if DEBUG: - prints('Unknown action for toolbar %r: %r' % (unicode(bar.objectName()), ac)) + prints('Unknown action for toolbar %r: %r' % (unicode_type(bar.objectName()), ac)) for x in tprefs['global_book_toolbar']: add(self.global_bar, x) diff --git a/src/calibre/gui2/tweak_book/widgets.py b/src/calibre/gui2/tweak_book/widgets.py index 05ba48c23c..fe70f3033d 100644 --- a/src/calibre/gui2/tweak_book/widgets.py +++ b/src/calibre/gui2/tweak_book/widgets.py @@ -28,6 +28,7 @@ from calibre.gui2.widgets2 import Dialog as BaseDialog, HistoryComboBox from calibre.utils.icu import primary_sort_key, sort_key, primary_contains, numeric_sort_key from calibre.utils.matcher import get_char, Matcher from calibre.gui2.complete2 import EditWithComplete +from polyglot.builtins import unicode_type ROOT = QModelIndex() PARAGRAPH_SEPARATOR = '\u2029' @@ -71,7 +72,7 @@ class InsertTag(Dialog): # {{{ @property def tag(self): - return unicode(self.tag_input.text()).strip() + return unicode_type(self.tag_input.text()).strip() @classmethod def test(cls): @@ -132,7 +133,7 @@ class RationalizeFolders(Dialog): # {{{ def folder_map(self): ans = {} for typ, x in self.TYPE_MAP: - val = unicode(getattr(self, '%s_folder' % typ).text()).strip().strip('/') + val = unicode_type(getattr(self, '%s_folder' % typ).text()).strip().strip('/') ans[typ] = val return ans @@ -244,15 +245,15 @@ class ImportForeign(Dialog): # {{{ self.dest.setText(path) def accept(self): - if not unicode(self.src.text()): + if not unicode_type(self.src.text()): return error_dialog(self, _('Need document'), _( 'You must specify the source file that will be imported.'), show=True) Dialog.accept(self) @property def data(self): - src = unicode(self.src.text()).strip() - dest = unicode(self.dest.text()).strip() + src = unicode_type(self.src.text()).strip() + dest = unicode_type(self.dest.text()).strip() if not dest: dest = src.rpartition('.')[0] + '.epub' return src, dest @@ -450,7 +451,7 @@ class QuickOpen(Dialog): l.addWidget(self.bb, alignment=Qt.AlignBottom) def update_matches(self, text): - text = unicode(text).strip() + text = unicode_type(text).strip() self.help_label.setVisible(False) self.results.setVisible(True) matches = self.matcher(text, limit=100) @@ -546,7 +547,7 @@ class NamesModel(QAbstractListModel): return '\xa0' * 20 def filter(self, query): - query = unicode(query or '') + query = unicode_type(query or '') self.beginResetModel() if not query: self.items = tuple((text, None) for text in self.names) @@ -611,7 +612,7 @@ class AnchorsModel(QAbstractListModel): self.filter('') def filter(self, query): - query = unicode(query or '') + query = unicode_type(query or '') self.beginResetModel() self.items = [x for x in self.names if primary_contains(query, x[0]) or primary_contains(query, x[1])] self.endResetModel() @@ -739,11 +740,11 @@ class InsertLink(Dialog): @property def href(self): - return unicode(self.target.text()).strip() + return unicode_type(self.target.text()).strip() @property def text(self): - return unicode(self.text_edit.text()).strip() + return unicode_type(self.text_edit.text()).strip() @property def template(self): @@ -883,7 +884,7 @@ class InsertSemantics(Dialog): d.exec_() def semantic_type_changed(self): - item_type = unicode(self.semantic_type.itemData(self.semantic_type.currentIndex()) or '') + item_type = unicode_type(self.semantic_type.itemData(self.semantic_type.currentIndex()) or '') name, frag = self.final_type_map.get(item_type, (None, None)) self.show_type(name, frag) @@ -908,8 +909,8 @@ class InsertSemantics(Dialog): self.target.blockSignals(False) def target_text_changed(self): - name, frag = unicode(self.target.text()).partition('#')[::2] - item_type = unicode(self.semantic_type.itemData(self.semantic_type.currentIndex()) or '') + name, frag = unicode_type(self.target.text()).partition('#')[::2] + item_type = unicode_type(self.semantic_type.itemData(self.semantic_type.currentIndex()) or '') self.final_type_map[item_type] = (name, frag or None) def selected_file_changed(self, *args): @@ -1027,7 +1028,7 @@ class FilterCSS(Dialog): # {{{ a('float'), a('clear') if self.opt_colors.isChecked(): a('color'), a('background-color') - for x in unicode(self.others.text()).split(','): + for x in unicode_type(self.others.text()).split(','): x = x.strip() if x: a(x) @@ -1213,7 +1214,7 @@ class PlainTextEdit(QPlainTextEdit): # {{{ return ans.rstrip('\0') def selected_text_from_cursor(self, cursor): - return unicodedata.normalize('NFC', unicode(cursor.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0')) + return unicodedata.normalize('NFC', unicode_type(cursor.selectedText()).replace(PARAGRAPH_SEPARATOR, '\n').rstrip('\0')) @property def selected_text(self): diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 6336a2411f..5642ba1a24 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -1,7 +1,6 @@ #!/usr/bin/env python2 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -from __future__ import with_statement -from __future__ import print_function +from __future__ import print_function, with_statement __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' @@ -54,6 +53,7 @@ from calibre.gui2.dbus_export.widgets import factory from calibre.gui2.open_with import register_keyboard_shortcuts from calibre.library import current_library_name from calibre.srv.library_broker import GuiLibraryBroker +from polyglot.builtins import unicode_type class Listener(Thread): # {{{ @@ -600,7 +600,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ if self.content_server is not None and \ self.content_server.exception is not None: error_dialog(self, _('Failed to start Content server'), - unicode(self.content_server.exception)).exec_() + unicode_type(self.content_server.exception)).exec_() @property def current_db(self): @@ -888,7 +888,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ pass if not minz: self.job_error_dialog.show_error(dialog_title, - _('Failed')+': '+unicode(job.description), + _('Failed')+': '+unicode_type(job.description), det_msg=job.details, retry_func=retry_func) def read_settings(self): diff --git a/src/calibre/gui2/update.py b/src/calibre/gui2/update.py index a688129e15..394e5cc674 100644 --- a/src/calibre/gui2/update.py +++ b/src/calibre/gui2/update.py @@ -2,7 +2,7 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal ' import re, binascii, cPickle, ssl, json -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from threading import Thread, Event from PyQt5.Qt import (QObject, pyqtSignal, Qt, QUrl, QDialog, QGridLayout, @@ -56,7 +56,7 @@ def get_newest_version(): except UnicodeDecodeError: version = u'' ans = NO_CALIBRE_UPDATE - m = re.match(unicode(r'(\d+)\.(\d+).(\d+)$'), version) + m = re.match(unicode_type(r'(\d+)\.(\d+).(\d+)$'), version) if m is not None: ans = tuple(map(int, (m.group(1), m.group(2), m.group(3)))) return ans @@ -195,7 +195,7 @@ class UpdateMixin(object): has_plugin_updates = number_of_plugin_updates > 0 self.plugin_update_found(number_of_plugin_updates) version_url = binascii.hexlify(cPickle.dumps((calibre_version, number_of_plugin_updates), -1)) - calibre_version = u'.'.join(map(unicode, calibre_version)) + calibre_version = u'.'.join(map(unicode_type, calibre_version)) if not has_calibre_update and not has_plugin_updates: self.status_bar.update_label.setVisible(False) @@ -246,7 +246,7 @@ class UpdateMixin(object): plugin.qaction.setToolTip(_('Install and configure user plugins')) def update_link_clicked(self, url): - url = unicode(url) + url = unicode_type(url) if url.startswith('update:'): calibre_version, number_of_plugin_updates = cPickle.loads(binascii.unhexlify(url[len('update:'):])) self.update_found(calibre_version, number_of_plugin_updates, force=True) diff --git a/src/calibre/gui2/viewer/bookmarkmanager.py b/src/calibre/gui2/viewer/bookmarkmanager.py index 708976d619..31bb7d57be 100644 --- a/src/calibre/gui2/viewer/bookmarkmanager.py +++ b/src/calibre/gui2/viewer/bookmarkmanager.py @@ -14,6 +14,7 @@ from PyQt5.Qt import ( from calibre.gui2 import choose_save_file, choose_files from calibre.utils.icu import sort_key +from polyglot.builtins import unicode_type class BookmarksList(QListWidget): @@ -146,7 +147,7 @@ class BookmarkManager(QWidget): def item_changed(self, item): self.bookmarks_list.blockSignals(True) - title = unicode(item.data(Qt.DisplayRole)) + title = unicode_type(item.data(Qt.DisplayRole)) if not title: title = _('Unknown') item.setData(Qt.DisplayRole, title) diff --git a/src/calibre/gui2/viewer/config.py b/src/calibre/gui2/viewer/config.py index 78fe6aceae..cc5e71c188 100644 --- a/src/calibre/gui2/viewer/config.py +++ b/src/calibre/gui2/viewer/config.py @@ -22,6 +22,7 @@ from calibre.gui2 import min_available_height, error_dialog from calibre.gui2.languages import LanguagesEdit from calibre.gui2.shortcuts import ShortcutConfig from calibre.gui2.viewer.config_ui import Ui_Dialog +from polyglot.builtins import unicode_type def config(defaults=None): @@ -197,7 +198,7 @@ class ConfigDialog(QDialog, Ui_Dialog): _('Choose a name for this theme')) if not ok: return - themename = unicode(themename).strip() + themename = unicode_type(themename).strip() if not themename: return c = config('') @@ -380,7 +381,7 @@ class ConfigDialog(QDialog, Ui_Dialog): col = QColorDialog.getColor(initial, self, title, QColorDialog.ShowAlphaChannel) if col.isValid(): - name = unicode(col.name()) + name = unicode_type(col.name()) setattr(self, 'current_%s_color'%which, name) self.update_sample_colors() @@ -405,15 +406,15 @@ class ConfigDialog(QDialog, Ui_Dialog): return QDialog.accept(self, *args) def save_options(self, c): - c.set('serif_family', unicode(self.serif_family.currentFont().family())) - c.set('sans_family', unicode(self.sans_family.currentFont().family())) - c.set('mono_family', unicode(self.mono_family.currentFont().family())) + c.set('serif_family', unicode_type(self.serif_family.currentFont().family())) + c.set('sans_family', unicode_type(self.sans_family.currentFont().family())) + c.set('mono_family', unicode_type(self.mono_family.currentFont().family())) c.set('default_font_size', self.default_font_size.value()) c.set('minimum_font_size', self.minimum_font_size.value()) c.set('mono_font_size', self.mono_font_size.value()) c.set('standard_font', {0:'serif', 1:'sans', 2:'mono'}[ self.standard_font.currentIndex()]) - c.set('user_css', unicode(self.css.toPlainText())) + c.set('user_css', unicode_type(self.css.toPlainText())) c.set('remember_window_size', self.opt_remember_window_size.isChecked()) c.set('fit_images', self.opt_fit_images.isChecked()) c.set('max_fs_width', int(self.max_fs_width.value())) diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index 37be8b36ee..430b3d940b 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -7,7 +7,7 @@ __docformat__ = 'restructuredtext en' import math, json from base64 import b64encode from functools import partial -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from PyQt5.Qt import ( QSize, QSizePolicy, QUrl, Qt, QPainter, QPalette, QBrush, @@ -149,7 +149,7 @@ class Document(QWebPage): # {{{ def findText(self, q, flags): if self.hyphenatable: - q = unicode(q) + q = unicode_type(q) hyphenated_q = self.javascript( 'hyphenate_text(%s, "%s")' % (json.dumps(q, ensure_ascii=False), self.loaded_lang), typ='string') if hyphenated_q and QWebPage.findText(self, hyphenated_q, flags): @@ -320,7 +320,7 @@ class Document(QWebPage): # {{{ @pyqtSlot(str) def debug(self, msg): - prints(unicode(msg)) + prints(unicode_type(msg)) @pyqtSlot(int) def jump_to_cfi_finished(self, job_id): @@ -393,7 +393,7 @@ class Document(QWebPage): # {{{ return ans def elem_outer_xml(self, elem): - return unicode(elem.toOuterXml()) + return unicode_type(elem.toOuterXml()) def bookmark(self): pos = self.page_position.current_pos @@ -512,7 +512,7 @@ class Document(QWebPage): # {{{ self.setPreferredContentsSize(s) def extract_node(self): - return unicode(self.mainFrame().evaluateJavaScript( + return unicode_type(self.mainFrame().evaluateJavaScript( 'window.calibre_extract.extract()')) # }}} @@ -670,7 +670,7 @@ class DocumentView(QWebView): # {{{ self.manager.selection_changed(self.selected_text, self.selected_html) def _selectedText(self): - t = unicode(self.selectedText()).strip() + t = unicode_type(self.selectedText()).strip() if not t: return u'' if len(t) > 40: @@ -699,7 +699,7 @@ class DocumentView(QWebView): # {{{ table = None parent = elem while not parent.isNull(): - if (unicode(parent.tagName()) == u'table' or unicode(parent.localName()) == u'table'): + if (unicode_type(parent.tagName()) == u'table' or unicode_type(parent.localName()) == u'table'): table = parent break parent = parent.parent() @@ -727,10 +727,10 @@ class DocumentView(QWebView): # {{{ self.search_online_action.setText(text) for x, sc in (('search_online', 'Search online'), ('dictionary', 'Lookup word'), ('search', 'Next occurrence')): ac = getattr(self, '%s_action' % x) - menu.addAction(ac.icon(), '%s [%s]' % (unicode(ac.text()), ','.join(self.shortcuts.get_shortcuts(sc))), ac.trigger) + menu.addAction(ac.icon(), '%s [%s]' % (unicode_type(ac.text()), ','.join(self.shortcuts.get_shortcuts(sc))), ac.trigger) if from_touch and self.manager is not None: - word = unicode(mf.evaluateJavaScript('window.calibre_utils.word_at_point(%f, %f)' % (ev.pos().x(), ev.pos().y())) or '') + word = unicode_type(mf.evaluateJavaScript('window.calibre_utils.word_at_point(%f, %f)' % (ev.pos().x(), ev.pos().y())) or '') if word: menu.addAction(self.dictionary_action.icon(), _('Lookup %s in the dictionary') % word, partial(self.manager.lookup, word)) menu.addAction(self.search_online_action.icon(), _('Search for %s online') % word, partial(self.do_search_online, word)) @@ -790,18 +790,18 @@ class DocumentView(QWebView): # {{{ def lookup(self, *args): if self.manager is not None: - t = unicode(self.selectedText()).strip() + t = unicode_type(self.selectedText()).strip() if t: self.manager.lookup(t.split()[0]) def search_next(self): if self.manager is not None: - t = unicode(self.selectedText()).strip() + t = unicode_type(self.selectedText()).strip() if t: self.manager.search.set_search_string(t) def search_online(self): - t = unicode(self.selectedText()).strip() + t = unicode_type(self.selectedText()).strip() if t: self.do_search_online(t) @@ -839,7 +839,7 @@ class DocumentView(QWebView): # {{{ return (l, d.ypos, r, d.ypos + d.window_height) def link_hovered(self, link, text, context): - link, text = unicode(link), unicode(text) + link, text = unicode_type(link), unicode_type(text) if link: self.setCursor(Qt.PointingHandCursor) else: diff --git a/src/calibre/gui2/viewer/footnote.py b/src/calibre/gui2/viewer/footnote.py index 9f57c2b9ea..51ee28268d 100644 --- a/src/calibre/gui2/viewer/footnote.py +++ b/src/calibre/gui2/viewer/footnote.py @@ -18,6 +18,7 @@ from PyQt5.QtWebKit import QWebSettings from calibre import prints from calibre.constants import DEBUG, FAKE_PROTOCOL, FAKE_HOST from calibre.ebooks.oeb.display.webview import load_html +from polyglot.builtins import unicode_type class FootnotesPage(QWebPage): @@ -60,7 +61,7 @@ class FootnotesPage(QWebPage): def javaScriptConsoleMessage(self, msg, lineno, source_id): if DEBUG: - prints('FootnoteView:%s:%s:'%(unicode(source_id), lineno), unicode(msg)) + prints('FootnoteView:%s:%s:'%(unicode_type(source_id), lineno), unicode_type(msg)) class FootnotesView(QWidget): diff --git a/src/calibre/gui2/viewer/image_popup.py b/src/calibre/gui2/viewer/image_popup.py index 19ecbed6ff..74e7a1a009 100644 --- a/src/calibre/gui2/viewer/image_popup.py +++ b/src/calibre/gui2/viewer/image_popup.py @@ -12,6 +12,7 @@ from PyQt5.Qt import (QDialog, QPixmap, QUrl, QScrollArea, QLabel, QSizePolicy, Qt, QTransform, QSvgRenderer, QImage, QPainter) from calibre.gui2 import choose_save_file, gprefs, NO_URL_FORMATTING, max_available_height +from polyglot.builtins import unicode_type def render_svg(widget, path): @@ -122,7 +123,7 @@ class ImageView(QDialog): if geom is not None: self.restoreGeometry(geom) try: - self.current_image_name = unicode(self.current_url.toString(NO_URL_FORMATTING)).rpartition('/')[-1] + self.current_image_name = unicode_type(self.current_url.toString(NO_URL_FORMATTING)).rpartition('/')[-1] except AttributeError: self.current_image_name = self.current_url title = _('View image: %s')%self.current_image_name diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index 2bdf3630b0..4d788093fe 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -33,6 +33,7 @@ from calibre.utils.config import Config, JSONConfig, StringConfig from calibre.utils.ipc import RC, viewer_socket_address from calibre.utils.localization import canonicalize_lang, get_lang, lang_as_iso639_1 from calibre.utils.zipfile import BadZipfile +from polyglot.builtins import unicode_type try: from calibre.utils.monotonic import monotonic @@ -672,11 +673,11 @@ class EbookViewer(MainWindow): tt = '%(action)s [%(sc)s]\n'+_('Current magnification: %(mag).1f') sc = _(' or ').join(self.view.shortcuts.get_shortcuts('Font larger')) self.action_font_size_larger.setToolTip( - tt %dict(action=unicode(self.action_font_size_larger.text()), + tt %dict(action=unicode_type(self.action_font_size_larger.text()), mag=val, sc=sc)) sc = _(' or ').join(self.view.shortcuts.get_shortcuts('Font smaller')) self.action_font_size_smaller.setToolTip( - tt %dict(action=unicode(self.action_font_size_smaller.text()), + tt %dict(action=unicode_type(self.action_font_size_smaller.text()), mag=val, sc=sc)) self.action_font_size_larger.setEnabled(self.view.multiplier < 3) self.action_font_size_smaller.setEnabled(self.view.multiplier > 0.2) @@ -703,10 +704,10 @@ class EbookViewer(MainWindow): self.load_path(self.iterator.spine[index]) def find_next(self): - self.find(unicode(self.search.text()), repeat=True) + self.find(unicode_type(self.search.text()), repeat=True) def find_previous(self): - self.find(unicode(self.search.text()), repeat=True, backwards=True) + self.find(unicode_type(self.search.text()), repeat=True, backwards=True) def do_search(self, text, backwards): self.pending_search = None @@ -725,7 +726,7 @@ class EbookViewer(MainWindow): self.history.add(self.pos.value()) path = self.iterator.spine[self.iterator.spine.index(path)] if url.hasFragment(): - frag = unicode(url.fragment()) + frag = unicode_type(url.fragment()) if path != self.current_page: self.pending_anchor = frag self.load_path(path) @@ -931,7 +932,7 @@ class EbookViewer(MainWindow): num += 1 title, ok = QInputDialog.getText(self, _('Add bookmark'), _('Enter title for bookmark:'), text=bm) - title = unicode(title).strip() + title = unicode_type(title).strip() if ok and title: bm = self.view.bookmark() bm['spine'] = self.current_index diff --git a/src/calibre/gui2/viewer/ui.py b/src/calibre/gui2/viewer/ui.py index aa5f1d4301..f5ddabe73c 100644 --- a/src/calibre/gui2/viewer/ui.py +++ b/src/calibre/gui2/viewer/ui.py @@ -22,6 +22,7 @@ from calibre.gui2.viewer.bookmarkmanager import BookmarkManager from calibre.gui2.viewer.toc import TOCView, TOCSearch from calibre.gui2.viewer.footnote import FootnotesView from calibre.utils.localization import is_rtl +from polyglot.builtins import unicode_type class DoubleSpinBox(QDoubleSpinBox): # {{{ @@ -61,7 +62,7 @@ class Reference(QLineEdit): # {{{ self.editingFinished.connect(self.editing_finished) def editing_finished(self): - text = unicode(self.text()) + text = unicode_type(self.text()) self.setText('') self.goto.emit(text) # }}} @@ -215,7 +216,7 @@ class Main(MainWindow): def __init__(self, debug_javascript): MainWindow.__init__(self, None) self.setWindowTitle(_('E-book viewer')) - self.base_window_title = unicode(self.windowTitle()) + self.base_window_title = unicode_type(self.windowTitle()) self.setObjectName('EbookViewer') self.setWindowIcon(QIcon(I('viewer.png'))) self.setDockOptions(self.AnimatedDocks | self.AllowTabbedDocks) @@ -383,7 +384,7 @@ class Main(MainWindow): ac.setObjectName(name) (tb or self.tool_bar).addAction(ac) if sc_name: - ac.setToolTip(unicode(ac.text()) + (' [%s]' % _(' or ').join(self.view.shortcuts.get_shortcuts(sc_name)))) + ac.setToolTip(unicode_type(ac.text()) + (' [%s]' % _(' or ').join(self.view.shortcuts.get_shortcuts(sc_name)))) if menu_name is not None: menu_name += '_menu' m = QMenu() diff --git a/src/calibre/gui2/widgets.py b/src/calibre/gui2/widgets.py index e99cd3e99b..492e167307 100644 --- a/src/calibre/gui2/widgets.py +++ b/src/calibre/gui2/widgets.py @@ -23,6 +23,7 @@ from calibre.gui2.progress_indicator import ProgressIndicator as _ProgressIndica from calibre.gui2.dnd import (dnd_has_image, dnd_get_image, dnd_get_files, image_extensions, dnd_has_extension, DownloadDialog) from calibre.utils.localization import localize_user_manual_link +from polyglot.builtins import unicode_type history = XMLConfig('history') @@ -83,7 +84,7 @@ class FilenamePattern(QWidget, Ui_Form): # {{{ # Get all items in the combobox. If we are reseting # to defaults we don't want to lose what the user # has added. - val_hist = [unicode(self.re.lineEdit().text())] + [unicode(self.re.itemText(i)) for i in xrange(self.re.count())] + val_hist = [unicode_type(self.re.lineEdit().text())] + [unicode_type(self.re.itemText(i)) for i in xrange(self.re.count())] self.re.clear() if defaults: @@ -106,7 +107,7 @@ class FilenamePattern(QWidget, Ui_Form): # {{{ def do_test(self): from calibre.ebooks.metadata import authors_to_string from calibre.ebooks.metadata.meta import metadata_from_filename - fname = unicode(self.filename.text()) + fname = unicode_type(self.filename.text()) ext = os.path.splitext(fname)[1][1:].lower() if ext not in BOOK_EXTENSIONS: return warning_dialog(self, _('Test file name invalid'), @@ -154,7 +155,7 @@ class FilenamePattern(QWidget, Ui_Form): # {{{ self.comments.setText(mi.comments if mi.comments else _('No match')) def pattern(self): - pat = unicode(self.re.lineEdit().text()) + pat = unicode_type(self.re.lineEdit().text()) return re.compile(pat) def commit(self): @@ -162,7 +163,7 @@ class FilenamePattern(QWidget, Ui_Form): # {{{ prefs['filename_pattern'] = pat history = [] - history_pats = [unicode(self.re.lineEdit().text())] + [unicode(self.re.itemText(i)) for i in xrange(self.re.count())] + history_pats = [unicode_type(self.re.lineEdit().text())] + [unicode_type(self.re.itemText(i)) for i in xrange(self.re.count())] for p in history_pats[:24]: # Ensure we don't have duplicate items. if p and p not in history: @@ -485,23 +486,23 @@ class LineEditECM(object): # {{{ def upper_case(self): from calibre.utils.icu import upper - self.setText(upper(unicode(self.text()))) + self.setText(upper(unicode_type(self.text()))) def lower_case(self): from calibre.utils.icu import lower - self.setText(lower(unicode(self.text()))) + self.setText(lower(unicode_type(self.text()))) def swap_case(self): from calibre.utils.icu import swapcase - self.setText(swapcase(unicode(self.text()))) + self.setText(swapcase(unicode_type(self.text()))) def title_case(self): from calibre.utils.titlecase import titlecase - self.setText(titlecase(unicode(self.text()))) + self.setText(titlecase(unicode_type(self.text()))) def capitalize(self): from calibre.utils.icu import capitalize - self.setText(capitalize(unicode(self.text()))) + self.setText(capitalize(unicode_type(self.text()))) # }}} @@ -583,13 +584,13 @@ class CompleteLineEdit(EnLineEdit): # {{{ self.space_before_sep = space_before def text_changed(self, text): - all_text = unicode(text) + all_text = unicode_type(text) text = all_text[:self.cursorPosition()] prefix = text.split(self.separator)[-1].strip() text_items = [] for t in all_text.split(self.separator): - t1 = unicode(t).strip() + t1 = unicode_type(t).strip() if t1 != '': text_items.append(t) text_items = list(set(text_items)) @@ -597,8 +598,8 @@ class CompleteLineEdit(EnLineEdit): # {{{ def complete_text(self, text): cursor_pos = self.cursorPosition() - before_text = unicode(self.text())[:cursor_pos] - after_text = unicode(self.text())[cursor_pos:] + before_text = unicode_type(self.text())[:cursor_pos] + after_text = unicode_type(self.text())[cursor_pos:] prefix_len = len(before_text.split(self.separator)[-1].lstrip()) if self.space_before_sep: complete_text_pat = '%s%s %s %s' @@ -627,7 +628,7 @@ class EnComboBox(QComboBox): # {{{ self.setMinimumContentsLength(20) def text(self): - return unicode(self.currentText()) + return unicode_type(self.currentText()) def setText(self, text): idx = self.findText(text, Qt.MatchFixedString|Qt.MatchCaseSensitive) @@ -683,11 +684,11 @@ class HistoryLineEdit(QComboBox): # {{{ def save_history(self): items = [] - ct = unicode(self.currentText()) + ct = unicode_type(self.currentText()) if ct: items.append(ct) for i in range(self.count()): - item = unicode(self.itemText(i)) + item = unicode_type(self.itemText(i)) if item not in items: items.append(item) self.blockSignals(True) @@ -1081,7 +1082,7 @@ class Splitter(QSplitter): parent.addAction(self.action_toggle) if hasattr(parent, 'keyboard'): parent.keyboard.register_shortcut('splitter %s %s'%(name, - label), unicode(self.action_toggle.text()), + label), unicode_type(self.action_toggle.text()), default_keys=(shortcut,), action=self.action_toggle) else: self.action_toggle.setShortcut(shortcut) diff --git a/src/calibre/gui2/widgets2.py b/src/calibre/gui2/widgets2.py index 492bf08a4c..c941a0d39e 100644 --- a/src/calibre/gui2/widgets2.py +++ b/src/calibre/gui2/widgets2.py @@ -19,6 +19,7 @@ from calibre.ebooks.metadata import rating_to_stars from calibre.gui2 import gprefs, rating_font from calibre.gui2.complete2 import LineEdit, EditWithComplete from calibre.gui2.widgets import history +from polyglot.builtins import unicode_type class HistoryMixin(object): @@ -44,7 +45,7 @@ class HistoryMixin(object): self.lineEdit().editingFinished.connect(self.save_history) def save_history(self): - ct = unicode(self.text()) + ct = unicode_type(self.text()) if len(ct) > 2: try: self.history.remove(ct) @@ -91,7 +92,7 @@ class ColorButton(QPushButton): return self._color def fset(self, val): - val = unicode(val or '') + val = unicode_type(val or '') col = QColor(val) orig = self._color if col.isValid(): @@ -111,7 +112,7 @@ class ColorButton(QPushButton): def choose_color(self): col = QColorDialog.getColor(QColor(self._color or Qt.white), self, _('Choose a color')) if col.isValid(): - self.color = unicode(col.name()) + self.color = unicode_type(col.name()) def access_key(k): diff --git a/src/calibre/gui2/wizard/__init__.py b/src/calibre/gui2/wizard/__init__.py index 39b9aaa119..93b0d9ba1b 100644 --- a/src/calibre/gui2/wizard/__init__.py +++ b/src/calibre/gui2/wizard/__init__.py @@ -25,6 +25,7 @@ from calibre.utils.localization import localize_user_manual_link from calibre.utils.config import dynamic, prefs from calibre.gui2 import choose_dir, error_dialog +from polyglot.builtins import unicode_type if iswindows: winutil = plugins['winutil'][0] @@ -503,14 +504,14 @@ class KindlePage(QWizardPage, KindleUI): self.to_address.setText(accs[0][0]) def x(): - t = unicode(self.to_address.text()) + t = unicode_type(self.to_address.text()) if t.strip(): return t.strip() self.send_email_widget.initialize(x) def commit(self): - x = unicode(self.to_address.text()).strip() + x = unicode_type(self.to_address.text()).strip() parts = x.split('@') if (len(parts) >= 2 and parts[0] and self.send_email_widget.set_email_settings(True)): @@ -571,7 +572,7 @@ class StanzaPage(QWizardPage, StanzaUI): for p in range(8080, 8100): try: s.bind(('0.0.0.0', p)) - t = unicode(self.instructions.text()) + t = unicode_type(self.instructions.text()) t = re.sub(r':\d+', ':'+str(p), t) self.instructions.setText(t) return p @@ -720,7 +721,7 @@ class LibraryPage(QWizardPage, LibraryUI): return False def validatePage(self): - newloc = unicode(self.location.text()) + newloc = unicode_type(self.location.text()) if not self.is_library_dir_suitable(newloc): self.show_library_dir_error(newloc) return False @@ -750,11 +751,11 @@ class LibraryPage(QWizardPage, LibraryUI): self.show_library_dir_error(x) def show_library_dir_error(self, x): - if not isinstance(x, unicode): + if not isinstance(x, unicode_type): try: x = x.decode(filesystem_encoding) except: - x = unicode(repr(x)) + x = unicode_type(repr(x)) error_dialog(self, _('Bad location'), _('You must choose an empty folder for ' 'the calibre library. %s is not empty.')%x, show=True) @@ -788,7 +789,7 @@ class LibraryPage(QWizardPage, LibraryUI): def isComplete(self): try: - lp = unicode(self.location.text()) + lp = unicode_type(self.location.text()) ans = bool(lp) and os.path.exists(lp) and os.path.isdir(lp) and os.access(lp, os.W_OK) except: @@ -796,7 +797,7 @@ class LibraryPage(QWizardPage, LibraryUI): return ans def commit(self): - newloc = unicode(self.location.text()) + newloc = unicode_type(self.location.text()) try: dln = self.default_library_name if (dln and os.path.exists(dln) and not os.listdir(dln) and newloc != dln): @@ -887,8 +888,8 @@ class Wizard(QWizard): QWizard.accept(self) def set_finish_text(self, *args): - bt = unicode("" + self.buttonText(self.FinishButton) + "").replace('&', '') - t = unicode(self.finish_page.finish_text.text()) + bt = unicode_type("" + self.buttonText(self.FinishButton) + "").replace('&', '') + t = unicode_type(self.finish_page.finish_text.text()) if '%s' in t: self.finish_page.finish_text.setText(t%bt) diff --git a/src/calibre/gui2/wizard/send_email.py b/src/calibre/gui2/wizard/send_email.py index e6331f6970..b77cb68c70 100644 --- a/src/calibre/gui2/wizard/send_email.py +++ b/src/calibre/gui2/wizard/send_email.py @@ -20,6 +20,7 @@ from calibre import prints from calibre.gui2.wizard.send_email_ui import Ui_Form from calibre.utils.smtp import config as smtp_prefs from calibre.gui2 import error_dialog, question_dialog +from polyglot.builtins import unicode_type class TestEmail(QDialog): @@ -68,7 +69,7 @@ class TestEmail(QDialog): def run_test(self): try: - tb = self.test_func(unicode(self.to.text())) or _('Email successfully sent') + tb = self.test_func(unicode_type(self.to.text())) or _('Email successfully sent') except Exception: import traceback tb = traceback.format_exc() @@ -130,7 +131,7 @@ class RelaySetup(QDialog): self.service = service def accept(self): - un = unicode(self.username.text()) + un = unicode_type(self.username.text()) if self.service.get('at_in_username', False) and '@' not in un: return error_dialog(self, _('Incorrect username'), _('%s needs the full email address as your username') % @@ -263,14 +264,14 @@ class SendEmail(QWidget, Ui_Form): self.relay_tls.setChecked(True) def set_email_settings(self, to_set): - from_ = unicode(self.email_from.text()).strip() + from_ = unicode_type(self.email_from.text()).strip() if to_set and not from_: error_dialog(self, _('Bad configuration'), _('You must set the From email address')).exec_() return False - username = unicode(self.relay_username.text()).strip() - password = unicode(self.relay_password.text()).strip() - host = unicode(self.relay_host.text()).strip() + username = unicode_type(self.relay_username.text()).strip() + password = unicode_type(self.relay_password.text()).strip() + host = unicode_type(self.relay_host.text()).strip() enc_method = ('TLS' if self.relay_tls.isChecked() else 'SSL' if self.relay_ssl.isChecked() else 'NONE') if host: diff --git a/src/calibre/library/add_to_library.py b/src/calibre/library/add_to_library.py index 3ec82673f1..fc3e6dcaad 100644 --- a/src/calibre/library/add_to_library.py +++ b/src/calibre/library/add_to_library.py @@ -9,6 +9,7 @@ import os from hashlib import sha1 from calibre.ebooks import BOOK_EXTENSIONS +from polyglot.builtins import unicode_type def find_folders_under(root, db, add_root=True, # {{{ @@ -105,7 +106,7 @@ class FormatCollection(object): # {{{ def books_in_folder(folder, one_per_folder, # {{{ cancel_callback=lambda : False): - assert not isinstance(folder, unicode) + assert not isinstance(folder, unicode_type) dirpath = os.path.abspath(folder) if one_per_folder: diff --git a/src/calibre/library/caches.py b/src/calibre/library/caches.py index 9ac22bd6a9..238fddac59 100644 --- a/src/calibre/library/caches.py +++ b/src/calibre/library/caches.py @@ -20,6 +20,7 @@ from calibre.db.search import CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH, _match from calibre.ebooks.metadata import title_sort, author_to_author_sort from calibre.ebooks.metadata.opf2 import metadata_to_opf from calibre import prints +from polyglot.builtins import unicode_type class MetadataBackup(Thread): # {{{ @@ -136,7 +137,7 @@ del y, c, n, u def force_to_bool(val): - if isinstance(val, (str, unicode)): + if isinstance(val, (str, unicode_type)): try: val = icu_lower(val) if not val: @@ -347,7 +348,7 @@ class ResultCache(SearchQueryParser): # {{{ if item is None: continue v = item[loc] - if isinstance(v, (str, unicode)): + if isinstance(v, (str, unicode_type)): v = parse_date(v) if v is None or v <= UNDEFINED_DATE: matches.add(item[0]) @@ -358,7 +359,7 @@ class ResultCache(SearchQueryParser): # {{{ if item is None: continue v = item[loc] - if isinstance(v, (str, unicode)): + if isinstance(v, (str, unicode_type)): v = parse_date(v) if v is not None and v > UNDEFINED_DATE: matches.add(item[0]) @@ -402,7 +403,7 @@ class ResultCache(SearchQueryParser): # {{{ if item is None or item[loc] is None: continue v = item[loc] - if isinstance(v, (str, unicode)): + if isinstance(v, (str, unicode_type)): v = parse_date(v) if relop(v, qd, field_count): matches.add(item[0]) @@ -729,7 +730,7 @@ class ResultCache(SearchQueryParser): # {{{ # everything else, or 'all' matches matchkind, query = self._matchkind(query) - if not isinstance(query, unicode): + if not isinstance(query, unicode_type): query = query.decode('utf-8') db_col = {} @@ -914,7 +915,7 @@ class ResultCache(SearchQueryParser): # {{{ self.marked_ids_dict = dict.fromkeys(id_dict, u'true') else: # Ensure that all the items in the dict are text - self.marked_ids_dict = dict(izip(id_dict.iterkeys(), imap(unicode, + self.marked_ids_dict = dict(izip(id_dict.iterkeys(), imap(unicode_type, id_dict.itervalues()))) # Set the values in the cache diff --git a/src/calibre/library/catalogs/csv_xml.py b/src/calibre/library/catalogs/csv_xml.py index f4d8719bd3..5364a9f9be 100644 --- a/src/calibre/library/catalogs/csv_xml.py +++ b/src/calibre/library/catalogs/csv_xml.py @@ -11,6 +11,7 @@ from collections import namedtuple from calibre.customize import CatalogPlugin from calibre.library.catalogs import FIELDS from calibre.customize.conversion import DummyReporter +from polyglot.builtins import unicode_type class CSV_XML(CatalogPlugin): @@ -153,14 +154,14 @@ class CSV_XML(CatalogPlugin): item = u'%.2g' % (item / 2.0) # Convert HTML to markdown text - if type(item) is unicode: + if type(item) is unicode_type: opening_tag = re.search('<(\\w+)(\x20|>)', item) if opening_tag: closing_tag = re.search('<\\/%s>$' % opening_tag.group(1), item) if closing_tag: item = html2text(item) - outstr.append(u'"%s"' % unicode(item).replace('"', '""')) + outstr.append(u'"%s"' % unicode_type(item).replace('"', '""')) outfile.write(u','.join(outstr) + u'\n') outfile.close() @@ -176,8 +177,8 @@ class CSV_XML(CatalogPlugin): for field in fields: if field.startswith('#'): val = db.get_field(r['id'], field, index_is_id=True) - if not isinstance(val, (str, unicode)): - val = unicode(val) + if not isinstance(val, (str, unicode_type)): + val = unicode_type(val) item = getattr(E, field.replace('#', '_'))(val) record.append(item) @@ -187,11 +188,11 @@ class CSV_XML(CatalogPlugin): val = r[field] if not val: continue - if not isinstance(val, (str, unicode)): + if not isinstance(val, (str, unicode_type)): if (fm.get(field, {}).get('datatype', None) == 'rating' and val): val = u'%.2g' % (val / 2.0) - val = unicode(val) + val = unicode_type(val) item = getattr(E, field)(val) record.append(item) diff --git a/src/calibre/library/catalogs/epub_mobi_builder.py b/src/calibre/library/catalogs/epub_mobi_builder.py index 7826d5b898..44bbc7f166 100644 --- a/src/calibre/library/catalogs/epub_mobi_builder.py +++ b/src/calibre/library/catalogs/epub_mobi_builder.py @@ -26,6 +26,7 @@ from calibre.utils.icu import capitalize, collation_order, sort_key from calibre.utils.img import scale_image from calibre.utils.zipfile import ZipFile from calibre.utils.localization import get_lang, lang_as_iso639_1 +from polyglot.builtins import unicode_type class Formatter(TemplateFormatter): @@ -583,7 +584,7 @@ class CatalogBuilder(object): for rule in self.prefix_rules: # Literal comparison for Tags field if rule['field'].lower() == 'tags' or rule['field'] == _('Tags'): - if rule['pattern'].lower() in map(unicode.lower, record['tags']): + if rule['pattern'].lower() in map(unicode_type.lower, record['tags']): if self.DEBUG and self.opts.verbose: self.opts.log.info(" %s '%s' by %s (%s: Tags includes '%s')" % (rule['prefix'], record['title'], @@ -613,7 +614,7 @@ class CatalogBuilder(object): # locale version field_contents = _(repr(field_contents)) try: - if re.search(rule['pattern'], unicode(field_contents), + if re.search(rule['pattern'], unicode_type(field_contents), re.IGNORECASE) is not None: if self.DEBUG: _log_prefix_rule_match_info(rule, record, field_contents) @@ -685,14 +686,14 @@ class CatalogBuilder(object): if icu_upper(c[0]) != last_c: last_c = icu_upper(c[0]) if last_c in exceptions.keys(): - last_c = exceptions[unicode(last_c)] + last_c = exceptions[unicode_type(last_c)] last_ordnum = ordnum cl_list[idx] = last_c else: if last_ordnum != ordnum: last_c = icu_upper(c[0:ordlen]) if last_c in exceptions.keys(): - last_c = exceptions[unicode(last_c)] + last_c = exceptions[unicode_type(last_c)] last_ordnum = ordnum else: last_c = cl_list[idx-1] @@ -702,7 +703,7 @@ class CatalogBuilder(object): if last_ordnum != ordnum: last_c = icu_upper(c[0:ordlen]) if last_c in exceptions.keys(): - last_c = exceptions[unicode(last_c)] + last_c = exceptions[unicode_type(last_c)] last_ordnum = ordnum else: last_c = cl_list[idx-1] @@ -1325,7 +1326,7 @@ class CatalogBuilder(object): """ # Kindle TOC descriptions won't render certain characters # Fix up - massaged = unicode(BeautifulStoneSoup(description, convertEntities=BeautifulStoneSoup.HTML_ENTITIES)) + massaged = unicode_type(BeautifulStoneSoup(description, convertEntities=BeautifulStoneSoup.HTML_ENTITIES)) # Replace '&' with '&' massaged = re.sub("&", "&", massaged) @@ -4473,7 +4474,7 @@ class CatalogBuilder(object): Return: (str): legal XHTML anchor string of unicode character name """ - fullname = u''.join(unicodedata.name(unicode(cc)) for cc in c) + fullname = u''.join(unicodedata.name(unicode_type(cc)) for cc in c) terms = fullname.split() return "_".join(terms) @@ -4648,7 +4649,7 @@ class CatalogBuilder(object): lost_cr.group(2), lost_cr.group(3))) # Extract pre-built elements - annotations, etc. - if not isinstance(comments, unicode): + if not isinstance(comments, unicode_type): comments = comments.decode('utf-8', 'replace') soup = BeautifulSoup(comments) elems = soup.findAll('div') @@ -4822,7 +4823,7 @@ class CatalogBuilder(object): # locale version field_contents = _(repr(field_contents)) - matched = re.search(pat, unicode(field_contents), + matched = re.search(pat, unicode_type(field_contents), re.IGNORECASE) if matched is not None: if self.opts.verbose: diff --git a/src/calibre/library/comments.py b/src/calibre/library/comments.py index dc458268b9..e194584d16 100644 --- a/src/calibre/library/comments.py +++ b/src/calibre/library/comments.py @@ -13,6 +13,7 @@ from calibre.ebooks.BeautifulSoup import BeautifulSoup, Tag, NavigableString, \ CData, Comment, Declaration, ProcessingInstruction from calibre import prepare_string_for_xml from calibre.utils.html2text import html2text +from polyglot.builtins import unicode_type # Hackish - ignoring sentences ending or beginning in numbers to avoid # confusion with decimal points. @@ -49,7 +50,7 @@ def comments_to_html(comments): ''' if not comments: return u'

' - if not isinstance(comments, unicode): + if not isinstance(comments, unicode_type): comments = comments.decode(preferred_encoding, 'replace') if comments.lstrip().startswith('<'): @@ -128,7 +129,7 @@ def comments_to_html(comments): p['class'] = 'description' for t in result.findAll(text=True): - t.replaceWith(prepare_string_for_xml(unicode(t))) + t.replaceWith(prepare_string_for_xml(unicode_type(t))) return result.renderContents(encoding=None) diff --git a/src/calibre/library/custom_columns.py b/src/calibre/library/custom_columns.py index b3fc46013c..3a29ea73ef 100644 --- a/src/calibre/library/custom_columns.py +++ b/src/calibre/library/custom_columns.py @@ -14,6 +14,7 @@ from calibre.constants import preferred_encoding from calibre.library.field_metadata import FieldMetadata from calibre.utils.date import parse_date from calibre.utils.config import tweaks +from polyglot.builtins import unicode_type class CustomColumns(object): @@ -130,23 +131,23 @@ class CustomColumns(object): if d['is_multiple']: if x is None: return [] - if isinstance(x, (str, unicode, bytes)): + if isinstance(x, (str, unicode_type, bytes)): x = x.split(d['multiple_seps']['ui_to_list']) x = [y.strip() for y in x if y.strip()] x = [y.decode(preferred_encoding, 'replace') if not isinstance(y, - unicode) else y for y in x] + unicode_type) else y for y in x] return [u' '.join(y.split()) for y in x] else: - return x if x is None or isinstance(x, unicode) else \ + return x if x is None or isinstance(x, unicode_type) else \ x.decode(preferred_encoding, 'replace') def adapt_datetime(x, d): - if isinstance(x, (str, unicode, bytes)): + if isinstance(x, (str, unicode_type, bytes)): x = parse_date(x, assume_utc=False, as_utc=False) return x def adapt_bool(x, d): - if isinstance(x, (str, unicode, bytes)): + if isinstance(x, (str, unicode_type, bytes)): x = x.lower() if x == 'true': x = True @@ -167,7 +168,7 @@ class CustomColumns(object): def adapt_number(x, d): if x is None: return None - if isinstance(x, (str, unicode, bytes)): + if isinstance(x, (str, unicode_type, bytes)): if x.lower() == 'none': return None if d['datatype'] == 'int': diff --git a/src/calibre/library/database.py b/src/calibre/library/database.py index 0a4e1349ef..dcebaae4e8 100644 --- a/src/calibre/library/database.py +++ b/src/calibre/library/database.py @@ -11,6 +11,7 @@ from zlib import compress, decompress from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata import string_to_authors from calibre import isbytestring +from polyglot.builtins import unicode_type class Concatenate(object): @@ -45,7 +46,7 @@ class Connection(sqlite.Connection): def _connect(path): - if isinstance(path, unicode): + if isinstance(path, unicode_type): path = path.encode('utf-8') conn = sqlite.connect(path, factory=Connection, detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES) conn.row_factory = lambda cursor, row : list(row) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index cc22304db5..88a26e28a7 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -48,6 +48,7 @@ from calibre.db.lazy import FormatMetadata, FormatsList from calibre.db.categories import Tag, CATEGORY_SORTS from calibre.utils.localization import (canonicalize_lang, calibre_langcode_to_name) +from polyglot.builtins import unicode_type copyfile = os.link if hasattr(os, 'link') else shutil.copyfile SPOOL_SIZE = 30*1024*1024 @@ -104,7 +105,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): return self._library_id_ def fset(self, val): - self._library_id_ = unicode(val) + self._library_id_ = unicode_type(val) self.conn.executescript(''' DELETE FROM library_id; INSERT INTO library_id (uuid) VALUES ("%s"); @@ -332,10 +333,10 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): prints('found user category case overlap', catmap[uc]) cat = catmap[uc][0] suffix = 1 - while icu_lower((cat + unicode(suffix))) in catmap: + while icu_lower((cat + unicode_type(suffix))) in catmap: suffix += 1 - prints('Renaming user category %s to %s'%(cat, cat+unicode(suffix))) - user_cats[cat + unicode(suffix)] = user_cats[cat] + prints('Renaming user category %s to %s'%(cat, cat+unicode_type(suffix))) + user_cats[cat + unicode_type(suffix)] = user_cats[cat] del user_cats[cat] cats_changed = True if cats_changed: @@ -1091,7 +1092,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): def has_book(self, mi): title = mi.title if title: - if not isinstance(title, unicode): + if not isinstance(title, unicode_type): title = title.decode(preferred_encoding, 'replace') return bool(self.conn.get('SELECT id FROM books where title=?', (title,), all=False)) return False @@ -1754,7 +1755,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): self.id = id def __str__(self): - return unicode(self) + return unicode_type(self) def __unicode__(self): return 'n=%s s=%s c=%d rt=%d rc=%d id=%s'%\ @@ -1768,8 +1769,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): if len(comps) == 0: i = 1 while True: - if unicode(i) not in user_cats: - new_cats[unicode(i)] = user_cats[k] + if unicode_type(i) not in user_cats: + new_cats[unicode_type(i)] = user_cats[k] break i += 1 else: @@ -1995,7 +1996,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): formatter = calibre_langcode_to_name items = [v for v in tcategories[category].values() if v.c > 0] else: - formatter = (lambda x:unicode(x)) + formatter = (lambda x:unicode_type(x)) items = [v for v in tcategories[category].values() if v.c > 0] # sort the list @@ -2466,7 +2467,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): if not a: continue a = a.strip().replace(',', '|') - if not isinstance(a, unicode): + if not isinstance(a, unicode_type): a = a.decode(preferred_encoding, 'replace') aus = self.conn.get('SELECT id, name, sort FROM authors WHERE name=?', (a,)) if aus: @@ -2625,7 +2626,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): def set_timestamp(self, id, dt, notify=True, commit=True): if dt: - if isinstance(dt, (unicode, bytes)): + if isinstance(dt, (unicode_type, bytes)): dt = parse_date(dt, as_utc=True, assume_utc=False) self.conn.execute('UPDATE books SET timestamp=? WHERE id=?', (dt, id)) self.data.set(id, self.FIELD_MAP['timestamp'], dt, row_is_id=True) @@ -2654,7 +2655,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): books_to_refresh = {id} if publisher: case_change = False - if not isinstance(publisher, unicode): + if not isinstance(publisher, unicode_type): publisher = publisher.decode(preferred_encoding, 'replace') pubx = self.conn.get('''SELECT id,name from publishers WHERE name=?''', (publisher,)) @@ -3099,7 +3100,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): tag = tag.strip() if not tag: continue - if not isinstance(tag, unicode): + if not isinstance(tag, unicode_type): tag = tag.decode(preferred_encoding, 'replace') existing_tags = self.all_tags() lt = [t.lower() for t in existing_tags] @@ -3180,7 +3181,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): books_to_refresh = {id} if series: case_change = False - if not isinstance(series, unicode): + if not isinstance(series, unicode_type): series = series.decode(preferred_encoding, 'replace') series = series.strip() series = u' '.join(series.split()) @@ -3552,7 +3553,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): aus = mi.author_sort if mi.author_sort else self.author_sort_from_authors(mi.authors) if isinstance(aus, str): aus = aus.decode(preferred_encoding, 'replace') - title = mi.title if isinstance(mi.title, unicode) else \ + title = mi.title if isinstance(mi.title, unicode_type) else \ mi.title.decode(preferred_encoding, 'replace') obj = self.conn.execute('INSERT INTO books(title, series_index, author_sort) VALUES (?, ?, ?)', (title, series_index, aus)) @@ -3622,7 +3623,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): os.remove(dest) shutil.copyfile(src, dest) x = path_map[x] - if not isinstance(x, unicode): + if not isinstance(x, unicode_type): x = x.decode(filesystem_encoding, 'replace') progress(x) @@ -3658,7 +3659,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): progress.setLabelText(header) QCoreApplication.processEvents() db.conn.row_factory = lambda cursor, row: tuple(row) - db.conn.text_factory = lambda x: unicode(x, 'utf-8', 'replace') + db.conn.text_factory = lambda x: unicode_type(x, 'utf-8', 'replace') books = db.conn.get('SELECT id, title, sort, timestamp, series_index, author_sort, isbn FROM books ORDER BY id ASC') progress.setAutoReset(False) progress.setRange(0, len(books)) diff --git a/src/calibre/library/prefs.py b/src/calibre/library/prefs.py index dd10702854..d5e7398ffa 100644 --- a/src/calibre/library/prefs.py +++ b/src/calibre/library/prefs.py @@ -10,6 +10,7 @@ import json, os from calibre.constants import preferred_encoding from calibre.utils.config import to_json, from_json from calibre import prints +from polyglot.builtins import unicode_type class DBPrefs(dict): @@ -28,7 +29,7 @@ class DBPrefs(dict): dict.__setitem__(self, key, val) def raw_to_object(self, raw): - if not isinstance(raw, unicode): + if not isinstance(raw, unicode_type): raw = raw.decode(preferred_encoding) return json.loads(raw, object_hook=from_json) diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py index f1896a6e52..cfb774c186 100644 --- a/src/calibre/library/save_to_disk.py +++ b/src/calibre/library/save_to_disk.py @@ -19,6 +19,7 @@ from calibre.ebooks.metadata import title_sort from calibre.utils.date import as_local_time from calibre import strftime, prints, sanitize_file_name_unicode from calibre.db.lazy import FormatsList +from polyglot.builtins import unicode_type plugboard_any_device_value = 'any device' plugboard_any_format_value = 'any format' @@ -133,7 +134,7 @@ def preprocess_template(template): template = template.replace('//', '/') template = template.replace('{author}', '{authors}') template = template.replace('{tag}', '{tags}') - if not isinstance(template, unicode): + if not isinstance(template, unicode_type): template = template.decode(preferred_encoding, 'replace') return template @@ -235,7 +236,7 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250, divide_by=2.0) elif cm['datatype'] in ['int', 'float']: if format_args[key] != 0: - format_args[key] = unicode(format_args[key]) + format_args[key] = unicode_type(format_args[key]) else: format_args[key] = '' if safe_format: diff --git a/src/calibre/library/schema_upgrades.py b/src/calibre/library/schema_upgrades.py index dca844273e..a0ff54c302 100644 --- a/src/calibre/library/schema_upgrades.py +++ b/src/calibre/library/schema_upgrades.py @@ -1,7 +1,6 @@ #!/usr/bin/env python2 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -from __future__ import with_statement -from __future__ import print_function +from __future__ import print_function, with_statement __license__ = 'GPL v3' __copyright__ = '2010, Kovid Goyal ' @@ -10,6 +9,7 @@ __docformat__ = 'restructuredtext en' import os from calibre.utils.date import isoformat, DEFAULT_DATE +from polyglot.builtins import unicode_type class SchemaUpgrade(object): @@ -596,7 +596,7 @@ class SchemaUpgrade(object): id_ = str(id_) fname = custom_recipe_filename(id_, title) custom_recipes[id_] = (title, fname) - if isinstance(script, unicode): + if isinstance(script, unicode_type): script = script.encode('utf-8') with open(os.path.join(bdir, fname), 'wb') as f: f.write(script) @@ -611,5 +611,3 @@ class SchemaUpgrade(object): ALTER TABLE authors ADD COLUMN link TEXT NOT NULL DEFAULT ""; ''' self.conn.executescript(script) - - diff --git a/src/calibre/library/sqlite.py b/src/calibre/library/sqlite.py index 6f5ac75d74..5fd140ce90 100644 --- a/src/calibre/library/sqlite.py +++ b/src/calibre/library/sqlite.py @@ -1,5 +1,4 @@ -from __future__ import with_statement -from __future__ import print_function +from __future__ import print_function, with_statement __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __docformat__ = 'restructuredtext en' @@ -23,6 +22,7 @@ from calibre import isbytestring, force_unicode from calibre.constants import iswindows, DEBUG, plugins from calibre.utils.icu import sort_key from calibre import prints +from polyglot.builtins import unicode_type from dateutil.tz import tzoffset @@ -321,7 +321,7 @@ class DatabaseException(Exception): def __init__(self, err, tb): tb = '\n\t'.join(('\tRemote'+tb).splitlines()) try: - msg = unicode(err) +'\n' + tb + msg = unicode_type(err) +'\n' + tb except: msg = repr(err) + '\n' + tb Exception.__init__(self, msg) @@ -342,7 +342,7 @@ def proxy(fn): ok, res = self.proxy.results.get() if not ok: if isinstance(res[0], IntegrityError): - raise IntegrityError(unicode(res[0])) + raise IntegrityError(unicode_type(res[0])) raise DatabaseException(*res) return res return run diff --git a/src/calibre/spell/dictionary.py b/src/calibre/spell/dictionary.py index 15e459c9a8..6845a5cc3d 100644 --- a/src/calibre/spell/dictionary.py +++ b/src/calibre/spell/dictionary.py @@ -18,6 +18,7 @@ from calibre.spell import parse_lang_code from calibre.utils.config import JSONConfig from calibre.utils.icu import capitalize from calibre.utils.localization import get_lang, get_system_locale +from polyglot.builtins import unicode_type Dictionary = namedtuple('Dictionary', 'primary_locale locales dicpath affpath builtin name id') LoadedDictionary = namedtuple('Dictionary', 'primary_locale locales obj builtin name id') @@ -391,7 +392,7 @@ class Dictionaries(object): if d is not None: try: - ans = d.obj.suggest(unicode(word).replace('\u2010', '-')) + ans = d.obj.suggest(unicode_type(word).replace('\u2010', '-')) except ValueError: pass else: diff --git a/src/calibre/srv/ajax.py b/src/calibre/srv/ajax.py index a94ab24fb0..b1838387e4 100644 --- a/src/calibre/srv/ajax.py +++ b/src/calibre/srv/ajax.py @@ -7,7 +7,7 @@ __license__ = 'GPL v3' __copyright__ = '2015, Kovid Goyal ' from functools import partial -from polyglot.builtins import zip +from polyglot.builtins import unicode_type, zip from itertools import cycle from calibre import force_unicode @@ -116,7 +116,7 @@ def book_to_json(ctx, rd, db, book_id, dbtags[category] = ctx.url_for( books_in, encoded_category=encode_name(tag.category if tag.category else key), - encoded_item=encode_name(tag.original_name if tag.id is None else unicode(tag.id)), + encoded_item=encode_name(tag.original_name if tag.id is None else unicode_type(tag.id)), library_id=db.server_library_id ) break @@ -446,7 +446,7 @@ def category(ctx, rd, encoded_name, library_id): 'average_rating': x.avg_rating, 'count': x.count, 'url': ctx.url_for(books_in, encoded_category=encode_name(x.category if x.category else toplevel), - encoded_item=encode_name(x.original_name if x.id is None else unicode(x.id)), + encoded_item=encode_name(x.original_name if x.id is None else unicode_type(x.id)), library_id=db.server_library_id ), 'has_children': x.original_name in children, @@ -550,7 +550,7 @@ def search_result(ctx, rd, db, query, num, offset, sort, sort_order, vl=''): 'vl': vl, } if parse_error is not None: - ans['bad_restriction'] = unicode(parse_error) + ans['bad_restriction'] = unicode_type(parse_error) return ans diff --git a/src/calibre/srv/opds.py b/src/calibre/srv/opds.py index be2fd0a4d3..f37127b21f 100644 --- a/src/calibre/srv/opds.py +++ b/src/calibre/srv/opds.py @@ -27,10 +27,11 @@ from calibre import force_unicode from calibre.srv.errors import HTTPNotFound, HTTPInternalServerError from calibre.srv.routes import endpoint from calibre.srv.utils import get_library_data, http_date, Offsets +from polyglot.builtins import unicode_type def hexlify(x): - if isinstance(x, unicode): + if isinstance(x, unicode_type): x = x.encode('utf-8') return binascii.hexlify(x) @@ -210,9 +211,9 @@ def ACQUISITION_ENTRY(book_id, updated, request_context): fm['is_multiple']['ui_to_list'], joinval=fm['is_multiple']['list_to_ui'])))) elif datatype == 'comments' or (fm['datatype'] == 'composite' and fm['display'].get('contains_html', False)): - extra.append('%s: %s
'%(xml(name), comments_to_html(unicode(val)))) + extra.append('%s: %s
'%(xml(name), comments_to_html(unicode_type(val)))) else: - extra.append('%s: %s
'%(xml(name), xml(unicode(val)))) + extra.append('%s: %s
'%(xml(name), xml(unicode_type(val)))) if mi.comments: comments = comments_to_html(mi.comments) extra.append(comments) diff --git a/src/calibre/srv/render_book.py b/src/calibre/srv/render_book.py index eca906937c..813d8c6947 100644 --- a/src/calibre/srv/render_book.py +++ b/src/calibre/srv/render_book.py @@ -9,7 +9,7 @@ from base64 import standard_b64encode, standard_b64decode from collections import defaultdict, OrderedDict from itertools import count from functools import partial -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from urlparse import urlparse from urllib import quote @@ -325,7 +325,7 @@ class Container(ContainerBase): frag = urlunquote(frag) url = resource_template.format(encode_url(name, frag)) else: - if isinstance(name, unicode): + if isinstance(name, unicode_type): name = name.encode('utf-8') url = 'missing:' + force_unicode(quote(name), 'utf-8') changed.add(base) diff --git a/src/calibre/srv/routes.py b/src/calibre/srv/routes.py index 75f2e434f5..8623c77489 100644 --- a/src/calibre/srv/routes.py +++ b/src/calibre/srv/routes.py @@ -14,6 +14,7 @@ from operator import attrgetter from calibre.srv.errors import HTTPSimpleResponse, HTTPNotFound, RouteError from calibre.srv.utils import http_date from calibre.utils.serialize import msgpack_dumps, json_dumps, MSGPACK_MIME +from polyglot.builtins import unicode_type default_methods = frozenset(('HEAD', 'GET')) @@ -201,9 +202,9 @@ class Route(object): raise RouteError('The variable(s) %s are not part of the route: %s' % (','.join(unknown), self.endpoint.route)) def quoted(x): - if not isinstance(x, unicode) and not isinstance(x, bytes): - x = unicode(x) - if isinstance(x, unicode): + if not isinstance(x, unicode_type) and not isinstance(x, bytes): + x = unicode_type(x) + if isinstance(x, unicode_type): x = x.encode('utf-8') return urlquote(x, '') args = {k:'' for k in self.defaults} diff --git a/src/calibre/srv/utils.py b/src/calibre/srv/utils.py index 859d4f4946..e02f96f559 100644 --- a/src/calibre/srv/utils.py +++ b/src/calibre/srv/utils.py @@ -13,7 +13,7 @@ from urlparse import parse_qs import repr as reprlib from email.utils import formatdate from operator import itemgetter -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from urllib import quote as urlquote from binascii import hexlify, unhexlify @@ -287,7 +287,7 @@ def encode_path(*components): def encode_name(name): 'Encode a name (arbitrary string) as URL safe characters. See decode_name() also.' - if isinstance(name, unicode): + if isinstance(name, unicode_type): name = name.encode('utf-8') return hexlify(name) diff --git a/src/calibre/startup.py b/src/calibre/startup.py index 481d8780ab..78a7cad5be 100644 --- a/src/calibre/startup.py +++ b/src/calibre/startup.py @@ -10,7 +10,7 @@ Perform various initialization tasks. import locale, sys # Default translation is NOOP -from polyglot.builtins import builtins +from polyglot.builtins import builtins, unicode_type builtins.__dict__['_'] = lambda s: s # For strings which belong in the translation tables, but which shouldn't be @@ -58,7 +58,7 @@ if not _run_once: winutil, winutilerror = plugins['winutil'] if not winutil: raise RuntimeError('Failed to load the winutil plugin: %s'%winutilerror) - if len(sys.argv) > 1 and not isinstance(sys.argv[1], unicode): + if len(sys.argv) > 1 and not isinstance(sys.argv[1], unicode_type): sys.argv[1:] = winutil.argv()[1-len(sys.argv):] # @@ -75,7 +75,7 @@ if not _run_once: if isosx: enc = 'utf-8' for i in range(1, len(sys.argv)): - if not isinstance(sys.argv[i], unicode): + if not isinstance(sys.argv[i], unicode_type): sys.argv[i] = sys.argv[i].decode(enc, 'replace') # @@ -202,7 +202,7 @@ if not _run_once: if name == 'Thread': name = self.name if name: - if isinstance(name, unicode): + if isinstance(name, unicode_type): name = name.encode('ascii', 'replace').decode('ascii') plugins['speedup'][0].set_thread_name(name[:15]) except Exception: diff --git a/src/calibre/test_build.py b/src/calibre/test_build.py index f450e91744..4d0761b893 100644 --- a/src/calibre/test_build.py +++ b/src/calibre/test_build.py @@ -2,7 +2,7 @@ # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai from __future__ import (unicode_literals, division, absolute_import, print_function) -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type __license__ = 'GPL v3' __copyright__ = '2011, Kovid Goyal ' @@ -128,7 +128,7 @@ class BuildTest(unittest.TestCase): winutil = plugins['winutil'][0] def au(x, name): - self.assertTrue(isinstance(x, unicode), name + '() did not return a unicode string') + self.assertTrue(isinstance(x, unicode_type), name + '() did not return a unicode string') for x in winutil.argv(): au(x, 'argv') for x in 'username temp_path locale_name'.split(): @@ -139,7 +139,7 @@ class BuildTest(unittest.TestCase): for k, v in d.iteritems(): au(v, k) for k in os.environ.keys(): - au(winutil.getenv(unicode(k)), 'getenv-' + k) + au(winutil.getenv(unicode_type(k)), 'getenv-' + k) os.environ['XXXTEST'] = 'YYY' self.assertEqual(winutil.getenv(u'XXXTEST'), u'YYY') del os.environ['XXXTEST'] @@ -149,7 +149,7 @@ class BuildTest(unittest.TestCase): for fmt in (fmt, fmt.encode('ascii')): x = strftime(fmt, t) au(x, 'strftime') - self.assertEqual(unicode(time.strftime(fmt.replace('%e', '%#d'), t)), x) + self.assertEqual(unicode_type(time.strftime(fmt.replace('%e', '%#d'), t)), x) def test_sqlite(self): import sqlite3 @@ -173,7 +173,7 @@ class BuildTest(unittest.TestCase): # it should just work because the hard-coded paths of the Qt # installation should work. If they do not, then it is a distro # problem. - fmts = set(map(unicode, QImageReader.supportedImageFormats())) + fmts = set(map(unicode_type, QImageReader.supportedImageFormats())) testf = {'jpg', 'png', 'svg', 'ico', 'gif'} self.assertEqual(testf.intersection(fmts), testf, "Qt doesn't seem to be able to load some of its image plugins. Available plugins: %s" % fmts) data = P('images/blank.png', allow_user_override=False, data=True) diff --git a/src/calibre/utils/apsw_shell.py b/src/calibre/utils/apsw_shell.py index ba2fb2bd91..43b2356737 100644 --- a/src/calibre/utils/apsw_shell.py +++ b/src/calibre/utils/apsw_shell.py @@ -13,6 +13,8 @@ import time import codecs import base64 +from polyglot.builtins import unicode_type + if sys.platform=="win32": _win_colour=False try: @@ -722,7 +724,7 @@ Enter SQL statements terminated with a ";" intro=intro.lstrip() if self.interactive and intro: if sys.version_info<(3,0): - intro=unicode(intro) + intro=unicode_type(intro) c=self.colour self.write(self.stdout, c.intro+intro+c.intro_) @@ -1639,7 +1641,7 @@ Enter SQL statements terminated with a ";" # Ensure all values are utf8 not unicode for k,v in dialect.items(): - if isinstance(v, unicode): + if isinstance(v, unicode_type): dialect[k]=v.encode("utf8") for line in csv.reader(thefile, **dialect): # back to unicode again @@ -2419,8 +2421,8 @@ Enter SQL statements terminated with a ";" def write(self, dest, text): """Writes text to dest. dest will typically be one of self.stdout or self.stderr.""" # ensure text is unicode to catch codeset issues here - if type(text)!=unicode: - text=unicode(text) + if type(text)!=unicode_type: + text=unicode_type(text) try: dest.write(text) except UnicodeEncodeError: @@ -2465,7 +2467,7 @@ Enter SQL statements terminated with a ";" line=self.stdin.readline() # includes newline unless last line of file doesn't have one self.input_line_number+=1 if sys.version_info<(3,0): - if type(line)!=unicode: + if type(line)!=unicode_type: enc=getattr(self.stdin, "encoding", self.encoding[0]) if not enc: enc=self.encoding[0] diff --git a/src/calibre/utils/cleantext.py b/src/calibre/utils/cleantext.py index 6c4392427c..3ef9962391 100644 --- a/src/calibre/utils/cleantext.py +++ b/src/calibre/utils/cleantext.py @@ -3,7 +3,7 @@ __copyright__ = '2010, sengian ' __docformat__ = 'restructuredtext en' import re, htmlentitydefs -from polyglot.builtins import map +from polyglot.builtins import codepoint_to_chr, map from calibre.constants import plugins, preferred_encoding try: @@ -32,12 +32,12 @@ def clean_ascii_chars(txt, charlist=None): chars.add(127) for x in (9, 10, 13): chars.remove(x) - _ascii_pat = re.compile(u'|'.join(map(unichr, chars))) + _ascii_pat = re.compile(u'|'.join(map(codepoint_to_chr, chars))) if charlist is None: pat = _ascii_pat else: - pat = re.compile(u'|'.join(map(unichr, charlist))) + pat = re.compile(u'|'.join(map(codepoint_to_chr, charlist))) return pat.sub('', txt) @@ -72,15 +72,15 @@ def unescape(text, rm=False, rchar=u''): # character reference try: if text[:3] == "&#x": - return unichr(int(text[3:-1], 16)) + return codepoint_to_chr(int(text[3:-1], 16)) else: - return unichr(int(text[2:-1])) + return codepoint_to_chr(int(text[2:-1])) except ValueError: pass else: # named entity try: - text = unichr(htmlentitydefs.name2codepoint[text[1:-1]]) + text = codepoint_to_chr(htmlentitydefs.name2codepoint[text[1:-1]]) except KeyError: pass if rm: diff --git a/src/calibre/utils/complete.py b/src/calibre/utils/complete.py index e2ae94e808..7a66bf7a51 100644 --- a/src/calibre/utils/complete.py +++ b/src/calibre/utils/complete.py @@ -14,6 +14,8 @@ completion. import sys, os, shlex, glob, re +from polyglot.builtins import unicode_type + def prints(*args, **kwargs): ''' @@ -28,7 +30,7 @@ def prints(*args, **kwargs): enc = 'utf-8' safe_encode = kwargs.get('safe_encode', False) for i, arg in enumerate(args): - if isinstance(arg, unicode): + if isinstance(arg, unicode_type): try: arg = arg.encode(enc) except UnicodeEncodeError: @@ -39,8 +41,8 @@ def prints(*args, **kwargs): try: arg = str(arg) except ValueError: - arg = unicode(arg) - if isinstance(arg, unicode): + arg = unicode_type(arg) + if isinstance(arg, unicode_type): try: arg = arg.encode(enc) except UnicodeEncodeError: diff --git a/src/calibre/utils/config_base.py b/src/calibre/utils/config_base.py index 9726e50b1c..0a0345df26 100644 --- a/src/calibre/utils/config_base.py +++ b/src/calibre/utils/config_base.py @@ -13,6 +13,7 @@ from copy import deepcopy from calibre.utils.lock import ExclusiveFile from calibre.constants import config_dir, CONFIG_DIR_MODE +from polyglot.builtins import unicode_type plugin_dir = os.path.join(config_dir, 'plugins') @@ -198,7 +199,7 @@ class OptionSet(object): options = {'cPickle':cPickle} if src is not None: try: - if not isinstance(src, unicode): + if not isinstance(src, unicode_type): src = src.decode('utf-8') src = src.replace(u'PyQt%d.QtCore' % 4, u'PyQt5.QtCore') exec(src, options) @@ -306,7 +307,7 @@ class Config(ConfigInterface): src = self.option_set.serialize(opts)+ '\n\n' + footer + '\n' f.seek(0) f.truncate() - if isinstance(src, unicode): + if isinstance(src, unicode_type): src = src.encode('utf-8') f.write(src) diff --git a/src/calibre/utils/date.py b/src/calibre/utils/date.py index 90057cd451..d518da9ee4 100644 --- a/src/calibre/utils/date.py +++ b/src/calibre/utils/date.py @@ -14,6 +14,7 @@ from calibre import strftime from calibre.constants import iswindows, isosx, plugins from calibre.utils.iso8601 import utc_tz, local_tz, UNDEFINED_DATE from calibre.utils.localization import lcdata +from polyglot.builtins import unicode_type _utc_tz = utc_tz _local_tz = local_tz @@ -186,13 +187,13 @@ def fromordinal(day, as_utc=True): def isoformat(date_time, assume_utc=False, as_utc=True, sep='T'): if not hasattr(date_time, 'tzinfo'): - return unicode(date_time.isoformat()) + return unicode_type(date_time.isoformat()) if date_time.tzinfo is None: date_time = date_time.replace(tzinfo=_utc_tz if assume_utc else _local_tz) date_time = date_time.astimezone(_utc_tz if as_utc else _local_tz) # str(sep) because isoformat barfs with unicode sep on python 2.x - return unicode(date_time.isoformat(str(sep))) + return unicode_type(date_time.isoformat(str(sep))) def internal_iso_format_string(): @@ -205,7 +206,7 @@ def w3cdtf(date_time, assume_utc=False): date_time = date_time.replace(tzinfo=_utc_tz if assume_utc else _local_tz) date_time = date_time.astimezone(_utc_tz if as_utc else _local_tz) - return unicode(date_time.strftime('%Y-%m-%dT%H:%M:%SZ')) + return unicode_type(date_time.strftime('%Y-%m-%dT%H:%M:%SZ')) def as_local_time(date_time, assume_utc=True): diff --git a/src/calibre/utils/filenames.py b/src/calibre/utils/filenames.py index 58460d52f7..98dc6ecb73 100644 --- a/src/calibre/utils/filenames.py +++ b/src/calibre/utils/filenames.py @@ -14,6 +14,7 @@ from calibre.constants import ( filesystem_encoding, iswindows, plugins, preferred_encoding, isosx ) from calibre.utils.localization import get_udc +from polyglot.builtins import unicode_type def ascii_text(orig): @@ -21,7 +22,7 @@ def ascii_text(orig): try: ascii = udc.decode(orig) except: - if isinstance(orig, unicode): + if isinstance(orig, unicode_type): orig = orig.encode('ascii', 'replace') ascii = orig.decode(preferred_encoding, 'replace').encode('ascii', 'replace') diff --git a/src/calibre/utils/fonts/free_type.py b/src/calibre/utils/fonts/free_type.py index fc7c27b598..5974fc7be7 100644 --- a/src/calibre/utils/fonts/free_type.py +++ b/src/calibre/utils/fonts/free_type.py @@ -9,7 +9,7 @@ __docformat__ = 'restructuredtext en' import threading from functools import wraps -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from calibre.constants import plugins @@ -52,7 +52,7 @@ class Face(object): ''' Returns True if all the characters in text have glyphs in this font. ''' - if not isinstance(text, unicode): + if not isinstance(text, unicode_type): raise TypeError('%r is not a unicode object'%text) if has_non_printable_chars: from calibre.utils.fonts.utils import get_printable_characters @@ -62,7 +62,7 @@ class Face(object): @same_thread def glyph_ids(self, text): - if not isinstance(text, unicode): + if not isinstance(text, unicode_type): raise TypeError('%r is not a unicode object'%text) for char in text: yield self.face.glyph_id(ord(char)) diff --git a/src/calibre/utils/fonts/scanner.py b/src/calibre/utils/fonts/scanner.py index 33e5c7d0dd..2b1130ae24 100644 --- a/src/calibre/utils/fonts/scanner.py +++ b/src/calibre/utils/fonts/scanner.py @@ -16,6 +16,7 @@ from calibre.constants import (config_dir, iswindows, isosx, plugins, DEBUG, isworker, filesystem_encoding) from calibre.utils.fonts.metadata import FontMetadata, UnsupportedFont from calibre.utils.icu import sort_key +from polyglot.builtins import unicode_type class NoFonts(ValueError): @@ -266,7 +267,7 @@ class FontScanner(Thread): ''' from calibre.utils.fonts.utils import (supports_text, panose_to_css_generic_family, get_printable_characters) - if not isinstance(text, unicode): + if not isinstance(text, unicode_type): raise TypeError(u'%r is not unicode'%text) text = get_printable_characters(text) found = {} diff --git a/src/calibre/utils/fonts/sfnt/subset.py b/src/calibre/utils/fonts/sfnt/subset.py index 8c7b5901a5..b1683af139 100644 --- a/src/calibre/utils/fonts/sfnt/subset.py +++ b/src/calibre/utils/fonts/sfnt/subset.py @@ -15,6 +15,7 @@ from functools import partial from calibre.utils.icu import safe_chr, ord_string from calibre.utils.fonts.sfnt.container import Sfnt from calibre.utils.fonts.sfnt.errors import UnsupportedFont, NoGlyphs +from polyglot.builtins import unicode_type # TrueType outlines {{{ @@ -106,7 +107,7 @@ def pdf_subset(sfnt, glyphs): def safe_ord(x): - return ord_string(unicode(x))[0] + return ord_string(unicode_type(x))[0] def subset(raw, individual_chars, ranges=(), warnings=None): @@ -343,12 +344,12 @@ def all(): print('No glyphs!') continue except UnsupportedFont as e: - unsupported.append((font['full_name'], font['path'], unicode(e))) + unsupported.append((font['full_name'], font['path'], unicode_type(e))) print ('Unsupported!') continue except Exception as e: print ('Failed!') - failed.append((font['full_name'], font['path'], unicode(e))) + failed.append((font['full_name'], font['path'], unicode_type(e))) else: averages.append(sum(new_stats.itervalues())/sum(old_stats.itervalues()) * 100) print ('Reduced to:', '%.1f'%averages[-1] , '%') diff --git a/src/calibre/utils/fonts/utils.py b/src/calibre/utils/fonts/utils.py index 553d8cb7e2..36bdc05f03 100644 --- a/src/calibre/utils/fonts/utils.py +++ b/src/calibre/utils/fonts/utils.py @@ -11,6 +11,8 @@ import struct from io import BytesIO from collections import defaultdict +from polyglot.builtins import unicode_type + class UnsupportedFont(ValueError): pass @@ -396,7 +398,7 @@ def get_bmp_glyph_ids(table, bmp, codes): def get_glyph_ids(raw, text, raw_is_table=False): - if not isinstance(text, unicode): + if not isinstance(text, unicode_type): raise TypeError('%r is not a unicode object'%text) if raw_is_table: table = raw @@ -422,7 +424,7 @@ def get_glyph_ids(raw, text, raw_is_table=False): def supports_text(raw, text, has_only_printable_chars=False): - if not isinstance(text, unicode): + if not isinstance(text, unicode_type): raise TypeError('%r is not a unicode object'%text) if not has_only_printable_chars: text = get_printable_characters(text) diff --git a/src/calibre/utils/formatter.py b/src/calibre/utils/formatter.py index 2a47fc5823..7644470377 100644 --- a/src/calibre/utils/formatter.py +++ b/src/calibre/utils/formatter.py @@ -13,6 +13,7 @@ import re, string, traceback from calibre import prints from calibre.constants import DEBUG from calibre.utils.formatter_functions import formatter_functions +from polyglot.builtins import unicode_type class _Parser(object): @@ -213,7 +214,7 @@ class TemplateFormatter(string.Formatter): except: raise ValueError( _('format: type {0} requires a decimal (float) value, got {1}').format(typ, val)) - return unicode(('{0:'+fmt+'}').format(val)) + return unicode_type(('{0:'+fmt+'}').format(val)) def _explode_format_string(self, fmt): try: @@ -272,7 +273,7 @@ class TemplateFormatter(string.Formatter): # ensure we are dealing with a string. if isinstance(val, (int, float)): if val: - val = unicode(val) + val = unicode_type(val) else: val = '' # Handle conditional text diff --git a/src/calibre/utils/formatter_functions.py b/src/calibre/utils/formatter_functions.py index 22f62ff9d5..953840639a 100644 --- a/src/calibre/utils/formatter_functions.py +++ b/src/calibre/utils/formatter_functions.py @@ -23,6 +23,7 @@ from calibre.utils.titlecase import titlecase from calibre.utils.icu import capitalize, strcmp, sort_key from calibre.utils.date import parse_date, format_date, now, UNDEFINED_DATE from calibre.utils.localization import calibre_langcode_to_name, canonicalize_lang +from polyglot.builtins import unicode_type class FormatterFunctions(object): @@ -131,12 +132,12 @@ class FormatterFunction(object): def eval_(self, formatter, kwargs, mi, locals, *args): ret = self.evaluate(formatter, kwargs, mi, locals, *args) - if isinstance(ret, (str, unicode)): + if isinstance(ret, (str, unicode_type)): return ret if isinstance(ret, list): return ','.join(ret) if isinstance(ret, (int, float, bool)): - return unicode(ret) + return unicode_type(ret) class BuiltinFormatterFunction(FormatterFunction): @@ -246,7 +247,7 @@ class BuiltinAdd(BuiltinFormatterFunction): def evaluate(self, formatter, kwargs, mi, locals, x, y): x = float(x if x and x != 'None' else 0) y = float(y if y and y != 'None' else 0) - return unicode(x + y) + return unicode_type(x + y) class BuiltinSubtract(BuiltinFormatterFunction): @@ -258,7 +259,7 @@ class BuiltinSubtract(BuiltinFormatterFunction): def evaluate(self, formatter, kwargs, mi, locals, x, y): x = float(x if x and x != 'None' else 0) y = float(y if y and y != 'None' else 0) - return unicode(x - y) + return unicode_type(x - y) class BuiltinMultiply(BuiltinFormatterFunction): @@ -270,7 +271,7 @@ class BuiltinMultiply(BuiltinFormatterFunction): def evaluate(self, formatter, kwargs, mi, locals, x, y): x = float(x if x and x != 'None' else 0) y = float(y if y and y != 'None' else 0) - return unicode(x * y) + return unicode_type(x * y) class BuiltinDivide(BuiltinFormatterFunction): @@ -282,7 +283,7 @@ class BuiltinDivide(BuiltinFormatterFunction): def evaluate(self, formatter, kwargs, mi, locals, x, y): x = float(x if x and x != 'None' else 0) y = float(y if y and y != 'None' else 0) - return unicode(x / y) + return unicode_type(x / y) class BuiltinTemplate(BuiltinFormatterFunction): @@ -374,7 +375,7 @@ class BuiltinRawField(BuiltinFormatterFunction): if fm is None: return ', '.join(res) return fm['is_multiple']['list_to_ui'].join(res) - return unicode(res) + return unicode_type(res) class BuiltinRawList(BuiltinFormatterFunction): @@ -726,7 +727,7 @@ class BuiltinCount(BuiltinFormatterFunction): 'uses an ampersand. Examples: {tags:count(,)}, {authors:count(&)}') def evaluate(self, formatter, kwargs, mi, locals, val, sep): - return unicode(len([v for v in val.split(sep) if v])) + return unicode_type(len([v for v in val.split(sep) if v])) class BuiltinListitem(BuiltinFormatterFunction): diff --git a/src/calibre/utils/html2text.py b/src/calibre/utils/html2text.py index 49a7a9559d..6541e26f78 100644 --- a/src/calibre/utils/html2text.py +++ b/src/calibre/utils/html2text.py @@ -14,6 +14,7 @@ __contributors__ = ["Martin 'Joey' Schulze", "Ricardo Reyes", "Kevin Jay North"] # TODO: # Support decoded entities with unifiable. +from polyglot.builtins import codepoint_to_chr import re, sys, urllib, htmlentitydefs, codecs import sgmllib sgmllib.charref = re.compile('&#([xX]?[0-9a-fA-F]+)[^0-9a-fA-F]') @@ -75,7 +76,7 @@ def charref(name): if not UNICODE_SNOB and c in unifiable_n.keys(): return unifiable_n[c] else: - return unichr(c) + return codepoint_to_chr(c) def entityref(c): @@ -87,7 +88,7 @@ def entityref(c): except KeyError: return "&" + c else: - return unichr(name2cp(c)) + return codepoint_to_chr(name2cp(c)) def replaceEntities(s): diff --git a/src/calibre/utils/icu.py b/src/calibre/utils/icu.py index e17d345a68..1e26752fb0 100644 --- a/src/calibre/utils/icu.py +++ b/src/calibre/utils/icu.py @@ -16,6 +16,7 @@ import codecs from calibre.constants import plugins from calibre.utils.config_base import tweaks +from polyglot.builtins import unicode_type _locale = _collator = _primary_collator = _sort_collator = _numeric_collator = _case_sensitive_collator = None @@ -250,7 +251,7 @@ ord_string = _icu.ord_string def character_name(string): try: - return _icu.character_name(unicode(string)) or None + return _icu.character_name(unicode_type(string)) or None except (TypeError, ValueError, KeyError): pass @@ -267,7 +268,7 @@ def normalize(text, mode='NFC'): # that unless you have very good reasons not too. Also, it's speed # decreases on wide python builds, where conversion to/from ICU's string # representation is slower. - return _icu.normalize(_nmodes[mode], unicode(text)) + return _icu.normalize(_nmodes[mode], unicode_type(text)) def contractions(col=None): diff --git a/src/calibre/utils/icu_test.py b/src/calibre/utils/icu_test.py index 8ea028b0aa..f70b40f243 100644 --- a/src/calibre/utils/icu_test.py +++ b/src/calibre/utils/icu_test.py @@ -10,6 +10,7 @@ import unittest, sys from contextlib import contextmanager import calibre.utils.icu as icu +from polyglot.builtins import unicode_type @contextmanager @@ -164,7 +165,7 @@ class TestICU(unittest.TestCase): ' Test the break iterator ' from calibre.spell.break_iterator import split_into_words as split, index_of, split_into_words_and_positions for q in ('one two three', ' one two three', 'one\ntwo three ', ): - self.ae(split(unicode(q)), ['one', 'two', 'three'], 'Failed to split: %r' % q) + self.ae(split(unicode_type(q)), ['one', 'two', 'three'], 'Failed to split: %r' % q) self.ae(split(u'I I\'m'), ['I', "I'm"]) self.ae(split(u'out-of-the-box'), ['out-of-the-box']) self.ae(split(u'-one two-'), ['-one', 'two-']) diff --git a/src/calibre/utils/ipc/launch.py b/src/calibre/utils/ipc/launch.py index 5dfcf4f880..31c742c65b 100644 --- a/src/calibre/utils/ipc/launch.py +++ b/src/calibre/utils/ipc/launch.py @@ -12,6 +12,7 @@ from functools import partial from calibre.constants import iswindows, isosx, isfrozen, filesystem_encoding from calibre.utils.config import prefs from calibre.ptempfile import PersistentTemporaryFile, base_dir +from polyglot.builtins import unicode_type if iswindows: import win32process @@ -92,13 +93,13 @@ class Worker(object): for key in os.environ: try: val = os.environ[key] - if isinstance(val, unicode): + if isinstance(val, unicode_type): # On windows subprocess cannot handle unicode env vars try: val = val.encode(filesystem_encoding) except ValueError: val = val.encode('utf-8') - if isinstance(key, unicode): + if isinstance(key, unicode_type): key = key.encode('ascii') env[key] = val except: @@ -156,9 +157,9 @@ class Worker(object): # Windows cannot handle unicode env vars for k, v in env.iteritems(): try: - if isinstance(k, unicode): + if isinstance(k, unicode_type): k = k.encode('ascii') - if isinstance(v, unicode): + if isinstance(v, unicode_type): try: v = v.encode(filesystem_encoding) except: @@ -231,6 +232,3 @@ class Worker(object): self.log_path = ret return ret - - - diff --git a/src/calibre/utils/ipc/proxy.py b/src/calibre/utils/ipc/proxy.py index b58cda06e7..349267a240 100644 --- a/src/calibre/utils/ipc/proxy.py +++ b/src/calibre/utils/ipc/proxy.py @@ -16,6 +16,7 @@ from functools import partial from calibre import as_unicode, prints from calibre.constants import iswindows, DEBUG from calibre.utils.ipc import eintr_retry_call +from polyglot.builtins import unicode_type def _encode(msg): @@ -160,10 +161,8 @@ class Server(Thread): import traceback # Try to tell the client process what error happened try: - eintr_retry_call(conn.send_bytes, (_encode(('failed', (unicode(e), + eintr_retry_call(conn.send_bytes, (_encode(('failed', (unicode_type(e), as_unicode(traceback.format_exc())))))) except: pass raise - - diff --git a/src/calibre/utils/ipc/simple_worker.py b/src/calibre/utils/ipc/simple_worker.py index 07095637a0..bb721a5279 100644 --- a/src/calibre/utils/ipc/simple_worker.py +++ b/src/calibre/utils/ipc/simple_worker.py @@ -16,6 +16,7 @@ from contextlib import closing from calibre.constants import iswindows from calibre.utils.ipc import eintr_retry_call from calibre.utils.ipc.launch import Worker +from polyglot.builtins import unicode_type class WorkerError(Exception): @@ -251,7 +252,7 @@ def offload_worker(env={}, priority='normal', cwd=None): def compile_code(src): import re, io - if not isinstance(src, unicode): + if not isinstance(src, unicode_type): match = re.search(r'coding[:=]\s*([-\w.]+)', src[:200]) enc = match.group(1) if match else 'utf-8' src = src.decode(enc) diff --git a/src/calibre/utils/linux_trash.py b/src/calibre/utils/linux_trash.py index d8c189c4d1..bf01398f2f 100644 --- a/src/calibre/utils/linux_trash.py +++ b/src/calibre/utils/linux_trash.py @@ -24,6 +24,8 @@ import os.path as op from datetime import datetime from urllib import quote +from polyglot.builtins import unicode_type + FILES_DIR = 'files' INFO_DIR = 'info' INFO_SUFFIX = '.trashinfo' @@ -38,7 +40,7 @@ TOPDIR_FALLBACK = '.Trash-%s'%uid def uniquote(raw): - if isinstance(raw, unicode): + if isinstance(raw, unicode_type): raw = raw.encode('utf-8') return quote(raw).decode('utf-8') diff --git a/src/calibre/utils/localization.py b/src/calibre/utils/localization.py index d60ecdd0a0..9da64132e0 100644 --- a/src/calibre/utils/localization.py +++ b/src/calibre/utils/localization.py @@ -1,7 +1,6 @@ #!/usr/bin/env python2 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -from __future__ import absolute_import -from __future__ import print_function +from __future__ import absolute_import, print_function __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' @@ -10,6 +9,8 @@ __docformat__ = 'restructuredtext en' import os, locale, re, cStringIO from gettext import GNUTranslations, NullTranslations +from polyglot.builtins import unicode_type + _available_translations = None @@ -392,7 +393,7 @@ def calibre_langcode_to_name(lc, localize=True): def canonicalize_lang(raw): if not raw: return None - if not isinstance(raw, unicode): + if not isinstance(raw, unicode_type): raw = raw.decode('utf-8', 'ignore') raw = raw.lower().strip() if not raw: diff --git a/src/calibre/utils/logging.py b/src/calibre/utils/logging.py index 6489b1d2f5..ccf8d21c42 100644 --- a/src/calibre/utils/logging.py +++ b/src/calibre/utils/logging.py @@ -15,6 +15,7 @@ from functools import partial from threading import Lock from calibre import isbytestring, force_unicode, as_unicode, prints +from polyglot.builtins import unicode_type class Stream(object): @@ -106,7 +107,7 @@ class UnicodeHTMLStream(HTMLStream): for arg in args: if isbytestring(arg): arg = force_unicode(arg) - elif not isinstance(arg, unicode): + elif not isinstance(arg, unicode_type): arg = as_unicode(arg) self.data.append(arg+sep) self.plain_text.append(arg+sep) diff --git a/src/calibre/utils/matcher.py b/src/calibre/utils/matcher.py index 12a1d5229f..c417a9b41e 100644 --- a/src/calibre/utils/matcher.py +++ b/src/calibre/utils/matcher.py @@ -15,7 +15,7 @@ from collections import OrderedDict from itertools import islice from itertools import izip -from polyglot.builtins import map +from polyglot.builtins import map, unicode_type from calibre import detect_ncpus as cpu_count, as_unicode from calibre.constants import plugins, filesystem_encoding @@ -97,7 +97,7 @@ class Matcher(object): w = [Worker(requests, results) for i in range(max(1, cpu_count()))] [x.start() for x in w] workers.extend(w) - items = map(lambda x: normalize('NFC', unicode(x)), filter(None, items)) + items = map(lambda x: normalize('NFC', unicode_type(x)), filter(None, items)) self.items = items = tuple(items) tasks = split(items, len(workers)) self.task_maps = [{j: i for j, (i, _) in enumerate(task)} for task in tasks] @@ -108,7 +108,7 @@ class Matcher(object): self.sort_keys = None def __call__(self, query, limit=None): - query = normalize('NFC', unicode(query)) + query = normalize('NFC', unicode_type(query)) with wlock: for i, scorer in enumerate(self.scorers): workers[0].requests.put((i, scorer, query)) @@ -265,7 +265,7 @@ class CScorer(object): self.m = speedup.Matcher( items, primary_collator().capsule, - unicode(level1), unicode(level2), unicode(level3) + unicode_type(level1), unicode_type(level2), unicode_type(level3) ) def __call__(self, query): diff --git a/src/calibre/utils/open_with/osx.py b/src/calibre/utils/open_with/osx.py index 92488feb65..6b02aef6d3 100644 --- a/src/calibre/utils/open_with/osx.py +++ b/src/calibre/utils/open_with/osx.py @@ -11,6 +11,7 @@ from collections import defaultdict from calibre.ptempfile import TemporaryDirectory from calibre.utils.icu import numeric_sort_key +from polyglot.builtins import unicode_type application_locations = ('/Applications', '~/Applications', '~/Desktop') @@ -29,8 +30,8 @@ def generate_public_uti_map(): for table in tables: for tr in table.xpath('descendant::tr')[1:]: td = tr.xpath('descendant::td') - identifier = etree.tostring(td[0], method='text', encoding=unicode).strip() - tags = etree.tostring(td[2], method='text', encoding=unicode).strip() + identifier = etree.tostring(td[0], method='text', encoding=unicode_type).strip() + tags = etree.tostring(td[2], method='text', encoding=unicode_type).strip() identifier = identifier.split()[0].replace('\u200b', '') exts = [x.strip()[1:].lower() for x in tags.split(',') if x.strip().startswith('.')] for ext in exts: diff --git a/src/calibre/utils/podofo/__init__.py b/src/calibre/utils/podofo/__init__.py index 209ad26db4..b362cdef2e 100644 --- a/src/calibre/utils/podofo/__init__.py +++ b/src/calibre/utils/podofo/__init__.py @@ -1,7 +1,6 @@ #!/usr/bin/env python2 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai -from __future__ import with_statement -from __future__ import print_function +from __future__ import print_function, with_statement __license__ = 'GPL v3' __copyright__ = '2009, Kovid Goyal ' @@ -13,6 +12,7 @@ from calibre.constants import plugins, preferred_encoding from calibre.ebooks.metadata import authors_to_string from calibre.ptempfile import TemporaryDirectory from calibre.utils.ipc.simple_worker import fork_job, WorkerError +from polyglot.builtins import unicode_type def get_podofo(): @@ -25,7 +25,7 @@ def get_podofo(): def prep(val): if not val: return u'' - if not isinstance(val, unicode): + if not isinstance(val, unicode_type): val = val.decode(preferred_encoding, 'replace') return val.strip() diff --git a/src/calibre/utils/search_query_parser.py b/src/calibre/utils/search_query_parser.py index df3d3ed323..ea6608f64f 100644 --- a/src/calibre/utils/search_query_parser.py +++ b/src/calibre/utils/search_query_parser.py @@ -22,6 +22,7 @@ import weakref, re from calibre.constants import preferred_encoding from calibre.utils.icu import sort_key from calibre import prints +from polyglot.builtins import codepoint_to_chr, unicode_type ''' @@ -55,7 +56,7 @@ class SavedSearchQueries(object): db.set_pref(self.opt_name, self.queries) def force_unicode(self, x): - if not isinstance(x, unicode): + if not isinstance(x, unicode_type): x = x.decode(preferred_encoding, 'replace') return x @@ -143,15 +144,15 @@ class Parser(object): WORD = 2 QUOTED_WORD = 3 EOF = 4 - REPLACEMENTS = tuple((u'\\' + x, unichr(i + 1)) for i, x in enumerate(u'\\"()')) + REPLACEMENTS = tuple((u'\\' + x, codepoint_to_chr(i + 1)) for i, x in enumerate(u'\\"()')) # Had to translate named constants to numeric values lex_scanner = re.Scanner([ - (unicode(r'[()]'), lambda x,t: (Parser.OPCODE, t)), - (unicode(r'@.+?:[^")\s]+'), lambda x,t: (Parser.WORD, unicode(t))), - (unicode(r'[^"()\s]+'), lambda x,t: (Parser.WORD, unicode(t))), - (unicode(r'".*?((? 1 self.output_dir = os.path.abspath(os.getcwdu()) @@ -1387,7 +1388,7 @@ class BasicNewsRecipe(Recipe): ''' try: from calibre.ebooks.covers import create_cover - title = self.title if isinstance(self.title, unicode) else \ + title = self.title if isinstance(self.title, unicode_type) else \ self.title.decode(preferred_encoding, 'replace') date = strftime(self.timefmt).replace('[', '').replace(']', '') img_data = create_cover(title, [date]) @@ -1433,7 +1434,7 @@ class BasicNewsRecipe(Recipe): article_titles.append(force_unicode(a.title, 'utf-8')) desc = self.description - if not isinstance(desc, unicode): + if not isinstance(desc, unicode_type): desc = desc.decode('utf-8', 'replace') mi.comments = (_('Articles in this issue:' ) + '\n\n' + '\n\n'.join(article_titles)) + '\n\n' + desc @@ -1535,7 +1536,7 @@ class BasicNewsRecipe(Recipe): elem = BeautifulSoup(templ.render(doctype='xhtml').decode('utf-8')).find('div') body.insert(len(body.contents), elem) with open(last, 'wb') as fi: - fi.write(unicode(soup).encode('utf-8')) + fi.write(unicode_type(soup).encode('utf-8')) if len(feeds) == 0: raise Exception('All feeds are empty, aborting.') @@ -1662,7 +1663,7 @@ class BasicNewsRecipe(Recipe): return tag if callable(getattr(tag, 'xpath', None)) and not hasattr(tag, 'contents'): # a lxml tag from lxml.etree import tostring - ans = tostring(tag, method='text', encoding=unicode, with_tail=False) + ans = tostring(tag, method='text', encoding=unicode_type, with_tail=False) else: strings = [] for item in tag.contents: diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py index 0b1eb7f22b..0b08171b6e 100644 --- a/src/calibre/web/feeds/recipes/__init__.py +++ b/src/calibre/web/feeds/recipes/__init__.py @@ -9,6 +9,7 @@ from calibre.web.feeds.news import (BasicNewsRecipe, CustomIndexRecipe, AutomaticNewsRecipe, CalibrePeriodical) from calibre.ebooks.BeautifulSoup import BeautifulSoup from calibre.utils.config import JSONConfig +from polyglot.builtins import unicode_type basic_recipes = (BasicNewsRecipe, AutomaticNewsRecipe, CustomIndexRecipe, CalibrePeriodical) @@ -30,7 +31,7 @@ def compile_recipe(src): :return: Recipe class or None, if no such class was found in src ''' - if not isinstance(src, unicode): + if not isinstance(src, unicode_type): match = re.search(r'coding[:=]\s*([-\w.]+)', src[:200]) enc = match.group(1) if match else 'utf-8' src = src.decode(enc) @@ -53,4 +54,3 @@ def compile_recipe(src): return x return None - diff --git a/src/calibre/web/feeds/recipes/collection.py b/src/calibre/web/feeds/recipes/collection.py index 426fd66ea8..3eea8b4ab1 100644 --- a/src/calibre/web/feeds/recipes/collection.py +++ b/src/calibre/web/feeds/recipes/collection.py @@ -18,6 +18,7 @@ from calibre.constants import numeric_version from calibre.utils.iso8601 import parse_iso8601 from calibre.utils.date import now as nowf, utcnow, local_tz, isoformat, EPOCH, UNDEFINED_DATE from calibre.utils.recycle_bin import delete_file +from polyglot.builtins import unicode_type NS = 'http://calibre-ebook.com/recipe_collection' E = ElementMaker(namespace=NS, nsmap={None:NS}) @@ -143,7 +144,7 @@ def update_custom_recipes(script_ids): fname = custom_recipe_filename(id_, title) else: fname = existing[1] - if isinstance(script, unicode): + if isinstance(script, unicode_type): script = script.encode('utf-8') custom_recipes[id_] = (title, fname) @@ -172,7 +173,7 @@ def add_custom_recipes(script_map): fid = str(id_) fname = custom_recipe_filename(fid, title) - if isinstance(script, unicode): + if isinstance(script, unicode_type): script = script.encode('utf-8') custom_recipes[fid] = (title, fname) @@ -548,8 +549,8 @@ class SchedulerConfig(object): username, password = c[k] except: username = password = '' - self.set_account_info(urn, unicode(username), - unicode(password)) + self.set_account_info(urn, unicode_type(username), + unicode_type(password)) except: continue del c diff --git a/src/calibre/web/feeds/recipes/model.py b/src/calibre/web/feeds/recipes/model.py index 06fa5f5606..d9a34b6b26 100644 --- a/src/calibre/web/feeds/recipes/model.py +++ b/src/calibre/web/feeds/recipes/model.py @@ -19,6 +19,7 @@ from calibre.web.feeds.recipes.collection import \ update_custom_recipes, add_custom_recipe, add_custom_recipes, \ remove_custom_recipe, get_custom_recipe, get_builtin_recipe from calibre.utils.search_query_parser import ParseException +from polyglot.builtins import unicode_type class NewsTreeItem(object): @@ -296,7 +297,7 @@ class RecipeModel(QAbstractItemModel, AdaptSQP): def search(self, query): results = [] try: - query = unicode(query).strip() + query = unicode_type(query).strip() if query: results = self.parse(query) if not results: @@ -413,6 +414,3 @@ class RecipeModel(QAbstractItemModel, AdaptSQP): for recipe in self.scheduler_config.iter_recipes(): ans.append(recipe.get('id')) return ans - - - diff --git a/src/calibre/web/feeds/templates.py b/src/calibre/web/feeds/templates.py index a3fe823333..385746bbd6 100644 --- a/src/calibre/web/feeds/templates.py +++ b/src/calibre/web/feeds/templates.py @@ -12,6 +12,7 @@ from lxml.html.builder import HTML, HEAD, TITLE, STYLE, DIV, BODY, \ TABLE, TD, TR from calibre import strftime, isbytestring +from polyglot.builtins import unicode_type def CLASS(*args, **kwargs): # class is a reserved word in Python @@ -73,7 +74,7 @@ class EmbeddedContent(Template): self.root = HTML(head, BODY(H2(article.title), DIV())) div = self.root.find('body').find('div') - if elements and isinstance(elements[0], unicode): + if elements and isinstance(elements[0], unicode_type): div.text = elements[0] elements = list(elements)[1:] for elem in elements: diff --git a/src/calibre/web/fetch/simple.py b/src/calibre/web/fetch/simple.py index 453220522d..a894691510 100644 --- a/src/calibre/web/fetch/simple.py +++ b/src/calibre/web/fetch/simple.py @@ -24,6 +24,7 @@ from calibre.utils.logging import Log from calibre.utils.img import image_from_data, image_to_data from calibre.utils.imghdr import what from calibre.web.fetch.utils import rescale_image +from polyglot.builtins import unicode_type class AbortArticle(Exception): @@ -90,7 +91,7 @@ def save_soup(soup, target): if path and os.path.isfile(path) and os.path.exists(path) and os.path.isabs(path): tag[key] = unicode_path(relpath(path, selfdir).replace(os.sep, '/')) - html = unicode(soup) + html = unicode_type(soup) with open(target, 'wb') as f: f.write(html.encode('utf-8')) @@ -120,7 +121,7 @@ class RecursiveFetcher(object): def __init__(self, options, log, image_map={}, css_map={}, job_info=None): bd = options.dir - if not isinstance(bd, unicode): + if not isinstance(bd, unicode_type): bd = bd.decode(filesystem_encoding) self.base_dir = os.path.abspath(os.path.expanduser(bd)) @@ -254,7 +255,7 @@ class RecursiveFetcher(object): delta = time.time() - self.last_fetch_at if delta < self.delay: time.sleep(self.delay - delta) - if isinstance(url, unicode): + if isinstance(url, unicode_type): url = url.encode('utf-8') # Not sure is this is really needed as I think mechanize # handles quoting automatically, but leaving it @@ -401,7 +402,7 @@ class RecursiveFetcher(object): continue c += 1 fname = ascii_filename('img'+str(c)) - if isinstance(fname, unicode): + if isinstance(fname, unicode_type): fname = fname.encode('ascii', 'replace') data = self.preprocess_image_ext(data, iurl) if self.preprocess_image_ext is not None else data if data is None: @@ -529,7 +530,7 @@ class RecursiveFetcher(object): self.process_stylesheets(soup, newbaseurl) _fname = basename(iurl) - if not isinstance(_fname, unicode): + if not isinstance(_fname, unicode_type): _fname.decode('latin1', 'replace') _fname = _fname.encode('ascii', 'replace').replace('%', '').replace(os.sep, '') _fname = ascii_filename(_fname) diff --git a/src/polyglot/builtins.py b/src/polyglot/builtins.py index 2872b24009..61a4bb3ccf 100644 --- a/src/polyglot/builtins.py +++ b/src/polyglot/builtins.py @@ -26,6 +26,9 @@ if is_py3: map = builtins.__dict__['map'] filter = builtins.__dict__['filter'] + codepoint_to_chr = chr + unicode_type = str + def iteritems(d): return iter(d.items()) @@ -46,6 +49,9 @@ else: from future_builtins import zip, map, filter # noqa import __builtin__ as builtins + codepoint_to_chr = unichr + unicode_type = unicode + def iteritems(d): return d.iteritems() diff --git a/src/templite/__init__.py b/src/templite/__init__.py index 30c2c8ad82..8e64cc4b82 100644 --- a/src/templite/__init__.py +++ b/src/templite/__init__.py @@ -27,6 +27,8 @@ import sys, re +from polyglot.builtins import unicode_type + class Templite(object): auto_emit = re.compile('(^[\'\"])|(^[a-zA-Z0-9_\[\]\'\"]+$)') @@ -84,4 +86,4 @@ class Templite(object): def write(self, *args): for a in args: - self.__output.append(unicode(a)) + self.__output.append(unicode_type(a))