Blob Blame History Raw
From 2c909f199e721e27c7639acc575a917215a7c3da Mon Sep 17 00:00:00 2001
From: Eli Schwartz <eschwartz@archlinux.org>
Date: Thu, 18 Jul 2019 12:29:39 -0400
Subject: [PATCH 10/71]  py3: more work towards universal __future__s

---
 src/calibre/ebooks/oeb/transforms/flatcss.py  |  42 +--
 src/calibre/ebooks/oeb/transforms/jacket.py   |   7 +-
 src/calibre/ebooks/oeb/transforms/metadata.py |   2 +-
 src/calibre/ebooks/oeb/transforms/split.py    |  12 +-
 .../ebooks/oeb/transforms/structure.py        |  12 +-
 .../ebooks/oeb/transforms/trimmanifest.py     |   2 +-
 src/calibre/ebooks/pml/__init__.py            |   1 +
 src/calibre/ebooks/pml/pmlconverter.py        |  37 +--
 src/calibre/ebooks/pml/pmlml.py               |  13 +-
 src/calibre/ebooks/rb/__init__.py             |   5 +-
 src/calibre/ebooks/rb/writer.py               |   1 +
 src/calibre/ebooks/readability/cleaners.py    |   2 +
 src/calibre/ebooks/readability/debug.py       |   2 +
 src/calibre/ebooks/readability/htmls.py       |  18 +-
 src/calibre/ebooks/readability/readability.py |  18 +-
 src/calibre/ebooks/rtf/input.py               |   5 +-
 src/calibre/ebooks/rtf/preprocess.py          |   3 +-
 src/calibre/ebooks/rtf/rtfml.py               |  22 +-
 src/calibre/ebooks/rtf2xml/ParseRtf.py        |   6 +-
 src/calibre/ebooks/rtf2xml/check_encoding.py  |   6 +-
 src/calibre/ebooks/rtf2xml/footnote.py        |   8 +-
 src/calibre/ebooks/rtf2xml/hex_2_utf8.py      |   6 +-
 src/calibre/ebooks/rtf2xml/list_table.py      |  15 +-
 src/calibre/ebooks/rtf2xml/make_lists.py      |   5 +-
 src/calibre/ebooks/rtf2xml/old_rtf.py         |   7 +-
 src/calibre/ebooks/rtf2xml/paragraph_def.py   |   7 +-
 src/calibre/ebooks/rtf2xml/pict.py            |   6 +-
 src/calibre/ebooks/rtf2xml/process_tokens.py  |   8 +-
 src/calibre/ebooks/rtf2xml/sections.py        |  16 +-
 src/calibre/ebooks/rtf2xml/table.py           |  11 +-
 src/calibre/ebooks/snb/__init__.py            |   3 +-
 src/calibre/ebooks/snb/snbml.py               |  41 +--
 src/calibre/ebooks/unihandecode/__init__.py   |   7 +-
 .../ebooks/unihandecode/jacodepoints.py       |   3 +-
 src/calibre/ebooks/unihandecode/jadecoder.py  |   3 +-
 .../ebooks/unihandecode/krcodepoints.py       |   3 +-
 src/calibre/ebooks/unihandecode/krdecoder.py  |   2 +-
 .../ebooks/unihandecode/pykakasi/__init__.py  |   3 +-
 .../ebooks/unihandecode/pykakasi/h2a.py       | 239 +++++++++---------
 .../ebooks/unihandecode/pykakasi/j2h.py       |   3 +-
 .../ebooks/unihandecode/pykakasi/jisyo.py     |   2 +
 .../ebooks/unihandecode/pykakasi/k2a.py       |   1 +
 .../ebooks/unihandecode/pykakasi/kakasi.py    |   2 +-
 .../ebooks/unihandecode/unicodepoints.py      |   1 +
 src/calibre/ebooks/unihandecode/unidecoder.py |   1 +
 .../ebooks/unihandecode/vncodepoints.py       |   3 +-
 src/calibre/ebooks/unihandecode/vndecoder.py  |   2 +-
 .../ebooks/unihandecode/zhcodepoints.py       |   3 +-
 src/calibre/gui2/book_details.py              |  27 +-
 src/calibre/gui2/cover_flow.py                |   9 +-
 src/calibre/gui2/custom_column_widgets.py     |   3 +-
 src/calibre/gui2/email.py                     |   2 +-
 src/calibre/gui2/init.py                      |   5 +-
 src/calibre/gui2/jobs.py                      |  14 +-
 src/calibre/gui2/layout.py                    |   3 +-
 src/calibre/gui2/linux_file_dialogs.py        |   6 +-
 src/calibre/gui2/shortcuts.py                 |   4 +-
 src/calibre/gui2/ui.py                        |   6 +-
 src/calibre/gui2/update.py                    |  16 +-
 59 files changed, 393 insertions(+), 329 deletions(-)

diff --git a/src/calibre/ebooks/oeb/transforms/flatcss.py b/src/calibre/ebooks/oeb/transforms/flatcss.py
index 4b777dbc04..c02dfe9e34 100644
--- a/src/calibre/ebooks/oeb/transforms/flatcss.py
+++ b/src/calibre/ebooks/oeb/transforms/flatcss.py
@@ -1,7 +1,7 @@
 '''
 CSS flattening transform.
 '''
-from __future__ import with_statement
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
@@ -122,9 +122,9 @@ class EmbedFontsCSSRules(object):
         if not self.body_font_family:
             return None
         if not self.href:
-            iid, href = oeb.manifest.generate(u'page_styles', u'page_styles.css')
+            iid, href = oeb.manifest.generate('page_styles', 'page_styles.css')
             rules = [css_text(x) for x in self.rules]
-            rules = u'\n\n'.join(rules)
+            rules = '\n\n'.join(rules)
             sheet = css_parser.parseString(rules, validate=False)
             self.href = oeb.manifest.add(iid, href, guess_type(href)[0],
                     data=sheet).href
@@ -228,13 +228,13 @@ class CSSFlattener(object):
         try:
             faces = font_scanner.fonts_for_family(family)
         except NoFonts:
-            msg = (u'No embeddable fonts found for family: %r'%family)
+            msg = ('No embeddable fonts found for family: %r'%family)
             if failure_critical:
                 raise ValueError(msg)
             self.oeb.log.warn(msg)
             return body_font_family, efi
         if not faces:
-            msg = (u'No embeddable fonts found for family: %r'%family)
+            msg = ('No embeddable fonts found for family: %r'%family)
             if failure_critical:
                 raise ValueError(msg)
             self.oeb.log.warn(msg)
@@ -243,26 +243,26 @@ class CSSFlattener(object):
         for i, font in enumerate(faces):
             ext = 'otf' if font['is_otf'] else 'ttf'
             fid, href = self.oeb.manifest.generate(id=u'font',
-                href=u'fonts/%s.%s'%(ascii_filename(font['full_name']).replace(u' ', u'-'), ext))
+                href='fonts/%s.%s'%(ascii_filename(font['full_name']).replace(' ', '-'), ext))
             item = self.oeb.manifest.add(fid, href,
                     guess_type('dummy.'+ext)[0],
                     data=font_scanner.get_font_data(font))
             item.unload_data_from_memory()
 
             cfont = {
-                    u'font-family':u'"%s"'%font['font-family'],
-                    u'panose-1': u' '.join(map(unicode_type, font['panose'])),
-                    u'src': u'url(%s)'%item.href,
+                    'font-family': '"%s"'%font['font-family'],
+                    'panose-1': ' '.join(map(unicode_type, font['panose'])),
+                    'src': 'url(%s)'%item.href,
             }
 
             if i == 0:
                 generic_family = panose_to_css_generic_family(font['panose'])
-                body_font_family = u"'%s',%s"%(font['font-family'], generic_family)
-                self.oeb.log(u'Embedding font: %s'%font['font-family'])
-            for k in (u'font-weight', u'font-style', u'font-stretch'):
-                if font[k] != u'normal':
+                body_font_family = "'%s',%s"%(font['font-family'], generic_family)
+                self.oeb.log('Embedding font: %s'%font['font-family'])
+            for k in ('font-weight', 'font-style', 'font-stretch'):
+                if font[k] != 'normal':
                     cfont[k] = font[k]
-            rule = '@font-face { %s }'%('; '.join(u'%s:%s'%(k, v) for k, v in
+            rule = '@font-face { %s }'%('; '.join('%s:%s'%(k, v) for k, v in
                 iteritems(cfont)))
             rule = css_parser.parseString(rule)
             efi.append(rule)
@@ -295,7 +295,7 @@ class CSSFlattener(object):
             if self.context.change_justification != 'original':
                 bs.append('text-align: '+ self.context.change_justification)
             if self.body_font_family:
-                bs.append(u'font-family: '+self.body_font_family)
+                bs.append('font-family: '+self.body_font_family)
             body.set('style', '; '.join(bs))
             stylizer = Stylizer(html, item.href, self.oeb, self.context, profile,
                     user_css=self.context.extra_css,
@@ -458,7 +458,7 @@ class CSSFlattener(object):
             dyn_rescale = node.attrib.pop('data-calibre-rescale', None)
             if dyn_rescale is not None:
                 try:
-                    dyn_rescale = float(dyn_rescale) / 100.0
+                    dyn_rescale = float(dyn_rescale) / 100
                 except Exception:
                     dyn_rescale = 1
                 fsize = self.fmap[_sbase]
@@ -476,7 +476,7 @@ class CSSFlattener(object):
         try:
             minlh = self.context.minimum_line_height / 100.
             if not is_drop_cap and style['line-height'] < minlh * fsize:
-                cssdict['line-height'] = str(minlh)
+                cssdict['line-height'] = unicode_type(minlh)
         except:
             self.oeb.logger.exception('Failed to set minimum line-height')
 
@@ -528,7 +528,7 @@ class CSSFlattener(object):
 
             if cssdict:
                 items = sorted(iteritems(cssdict))
-                css = u';\n'.join(u'%s: %s' % (key, val) for key, val in items)
+                css = ';\n'.join(u'%s: %s' % (key, val) for key, val in items)
                 classes = node.get('class', '').strip() or 'calibre'
                 classes_list = classes.split()
                 # lower() because otherwise if the document uses the same class
@@ -538,7 +538,7 @@ class CSSFlattener(object):
                 if css in styles:
                     match = styles[css]
                 else:
-                    match = klass + str(names[klass] or '')
+                    match = klass + unicode_type(names[klass] or '')
                     styles[css] = match
                     names[klass] += 1
                 node.attrib['class'] = match
@@ -546,7 +546,7 @@ class CSSFlattener(object):
 
             for psel, cssdict in iteritems(pseudo_classes):
                 items = sorted(iteritems(cssdict))
-                css = u';\n'.join(u'%s: %s' % (key, val) for key, val in items)
+                css = ';\n'.join('%s: %s' % (key, val) for key, val in items)
                 pstyles = pseudo_styles[psel]
                 if css in pstyles:
                     match = pstyles[css]
@@ -558,7 +558,7 @@ class CSSFlattener(object):
                     # then the class attribute for a.x tags will contain both
                     # that class and the class for a.x:hover, which is wrong.
                     klass = 'pcalibre'
-                    match = klass + str(names[klass] or '')
+                    match = klass + unicode_type(names[klass] or '')
                     pstyles[css] = match
                     names[klass] += 1
                 keep_classes.add(match)
diff --git a/src/calibre/ebooks/oeb/transforms/jacket.py b/src/calibre/ebooks/oeb/transforms/jacket.py
index 68ae89b8ba..35ead6a29a 100644
--- a/src/calibre/ebooks/oeb/transforms/jacket.py
+++ b/src/calibre/ebooks/oeb/transforms/jacket.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 absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
@@ -188,7 +187,7 @@ class Series(unicode_type):
             combined = roman = escape(series or u'')
         s = unicode_type.__new__(self, combined)
         s.roman = roman
-        s.name = escape(series or u'')
+        s.name = escape(series or '')
         s.number = escape(fmt_sidx(series_index or 1.0, use_roman=False))
         s.roman_number = escape(fmt_sidx(series_index or 1.0, use_roman=True))
         return s
@@ -260,7 +259,7 @@ def render_jacket(mi, output_profile,
             pubdate = ''
         else:
             dt = as_local_time(mi.pubdate)
-            pubdate = strftime(u'%Y', dt.timetuple())
+            pubdate = strftime('%Y', dt.timetuple())
     except:
         pubdate = ''
 
diff --git a/src/calibre/ebooks/oeb/transforms/metadata.py b/src/calibre/ebooks/oeb/transforms/metadata.py
index 7f5342d6f4..ed829dc92d 100644
--- a/src/calibre/ebooks/oeb/transforms/metadata.py
+++ b/src/calibre/ebooks/oeb/transforms/metadata.py
@@ -1,6 +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 absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
diff --git a/src/calibre/ebooks/oeb/transforms/split.py b/src/calibre/ebooks/oeb/transforms/split.py
index 93fd1226c5..a54121e48c 100644
--- a/src/calibre/ebooks/oeb/transforms/split.py
+++ b/src/calibre/ebooks/oeb/transforms/split.py
@@ -1,4 +1,4 @@
-from __future__ import with_statement
+from __future__ import absolute_import, division, print_function, unicode_literals
 __license__   = 'GPL v3'
 __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
 __docformat__ = 'restructuredtext en'
@@ -20,7 +20,7 @@ from calibre.ebooks.epub import rules
 from calibre.ebooks.oeb.base import (OEB_STYLES, XPNSMAP as NAMESPACES,
         urldefrag, rewrite_links, XHTML, urlnormalize)
 from calibre.ebooks.oeb.polish.split import do_split
-from polyglot.builtins import iteritems, range, map
+from polyglot.builtins import iteritems, range, map, unicode_type
 from polyglot.urllib import unquote
 from css_selectors import Select, SelectorError
 
@@ -123,7 +123,7 @@ class Split(object):
 
         for i, elem in enumerate(item.data.iter('*')):
             try:
-                elem.set('pb_order', str(i))
+                elem.set('pb_order', unicode_type(i))
             except TypeError:  # Cant set attributes on comment nodes etc.
                 continue
 
@@ -202,7 +202,7 @@ class FlowSplitter(object):
         self.csp_counter    = 0
 
         base, ext = os.path.splitext(self.base)
-        self.base = base.replace('%', '%%')+u'_split_%.3d'+ext
+        self.base = base.replace('%', '%%')+'_split_%.3d'+ext
 
         self.trees = [self.item.data.getroottree()]
         self.splitting_on_page_breaks = True
@@ -295,7 +295,7 @@ class FlowSplitter(object):
         body = self.get_body(root)
         if body is None:
             return False
-        txt = re.sub(ur'\s+|\xa0', '',
+        txt = re.sub(r'\s+|\xa0', '',
                 etree.tostring(body, method='text', encoding='unicode'))
         if len(txt) > 1:
             return False
@@ -338,7 +338,7 @@ class FlowSplitter(object):
                 for frag in frags:
                     pre2 = copy.copy(pre)
                     pre2.text = frag
-                    pre2.tail = u''
+                    pre2.tail = ''
                     new_pres.append(pre2)
                 new_pres[-1].tail = pre.tail
                 p = pre.getparent()
diff --git a/src/calibre/ebooks/oeb/transforms/structure.py b/src/calibre/ebooks/oeb/transforms/structure.py
index 31c95c8aa1..cd5211c156 100644
--- a/src/calibre/ebooks/oeb/transforms/structure.py
+++ b/src/calibre/ebooks/oeb/transforms/structure.py
@@ -1,6 +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 absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
@@ -26,7 +26,7 @@ def XPath(x):
 
 
 def isspace(x):
-    return not x or x.replace(u'\xa0', u'').isspace()
+    return not x or x.replace('\xa0', '').isspace()
 
 
 def at_start(elem):
@@ -124,11 +124,11 @@ class DetectStructure(object):
                 elem = matches[0]
                 eid = elem.get('id', None)
                 if not eid:
-                    eid = u'start_reading_at_'+unicode_type(uuid.uuid4()).replace(u'-', u'')
+                    eid = 'start_reading_at_'+unicode_type(uuid.uuid4()).replace('-', '')
                     elem.set('id', eid)
-                if u'text' in self.oeb.guide:
-                    self.oeb.guide.remove(u'text')
-                self.oeb.guide.add(u'text', u'Start', item.href+u'#'+eid)
+                if 'text' in self.oeb.guide:
+                    self.oeb.guide.remove('text')
+                self.oeb.guide.add('text', 'Start', item.href+'#'+eid)
                 self.log('Setting start reading at position to %s in %s'%(
                     self.opts.start_reading_at, item.href))
                 return
diff --git a/src/calibre/ebooks/oeb/transforms/trimmanifest.py b/src/calibre/ebooks/oeb/transforms/trimmanifest.py
index c9d9b04b6e..d67f0e471c 100644
--- a/src/calibre/ebooks/oeb/transforms/trimmanifest.py
+++ b/src/calibre/ebooks/oeb/transforms/trimmanifest.py
@@ -1,7 +1,7 @@
 '''
 OPF manifest trimming transform.
 '''
-from __future__ import with_statement
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
diff --git a/src/calibre/ebooks/pml/__init__.py b/src/calibre/ebooks/pml/__init__.py
index c01caf569d..2260f2fe7c 100644
--- a/src/calibre/ebooks/pml/__init__.py
+++ b/src/calibre/ebooks/pml/__init__.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2009, John Schember <john@nachtimwald.com>'
diff --git a/src/calibre/ebooks/pml/pmlconverter.py b/src/calibre/ebooks/pml/pmlconverter.py
index da748469c2..4bef9a306b 100644
--- a/src/calibre/ebooks/pml/pmlconverter.py
+++ b/src/calibre/ebooks/pml/pmlconverter.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 '''
 Convert pml markup to and from html
@@ -229,7 +230,7 @@ class PML_HTMLizer(object):
         return html
 
     def start_line(self):
-        start = u''
+        start = ''
 
         state = deepcopy(self.state)
         div = []
@@ -258,10 +259,10 @@ class PML_HTMLizer(object):
             else:
                 start += self.STATES_TAGS[key][0]
 
-        return u'<p>%s' % start
+        return '<p>%s' % start
 
     def end_line(self):
-        end = u''
+        end = ''
 
         div = []
         span = []
@@ -281,10 +282,10 @@ class PML_HTMLizer(object):
             else:
                 end += self.STATES_TAGS[key][1]
 
-        return u'%s</p>' % end
+        return '%s</p>' % end
 
     def process_code(self, code, stream, pre=''):
-        text = u''
+        text = ''
 
         code = self.CODE_STATES.get(code, None)
         if not code:
@@ -309,7 +310,7 @@ class PML_HTMLizer(object):
         return text
 
     def process_code_simple(self, code, stream):
-        text = u''
+        text = ''
 
         if self.state[code][0]:
             if code in self.STATES_CLOSE_VALUE_REQ:
@@ -330,7 +331,7 @@ class PML_HTMLizer(object):
         return text
 
     def process_code_div(self, code, stream):
-        text = u''
+        text = ''
 
         # Close code.
         if self.state[code][0]:
@@ -384,7 +385,7 @@ class PML_HTMLizer(object):
         return text
 
     def process_code_span(self, code, stream):
-        text = u''
+        text = ''
 
         # Close code.
         if self.state[code][0]:
@@ -422,7 +423,7 @@ class PML_HTMLizer(object):
         return text
 
     def process_code_block(self, code, stream, pre=''):
-        text = u''
+        text = ''
 
         # Close all spans
         for c in self.SPAN_STATES:
@@ -467,7 +468,7 @@ class PML_HTMLizer(object):
         return text
 
     def code_value(self, stream):
-        value = u''
+        value = ''
         # state 0 is before =
         # state 1 is before the first "
         # state 2 is before the second "
@@ -506,7 +507,7 @@ class PML_HTMLizer(object):
             # Unable to complete the sequence to reterieve the value. Reset
             # the stream to the location it started.
             stream.seek(loc)
-            value = u''
+            value = ''
 
         return value.strip()
 
@@ -565,7 +566,7 @@ class PML_HTMLizer(object):
 
             c = line.read(1)
             while c != '':
-                text = u''
+                text = ''
 
                 if c == '\\':
                     c = line.read(1)
@@ -673,10 +674,10 @@ class PML_HTMLizer(object):
                     indent_state['T'] = False
                     adv_indent_val = ''
 
-                output.append(u''.join(parsed))
+                output.append(''.join(parsed))
             line.close()
 
-        output = self.cleanup_html(u'\n'.join(output))
+        output = self.cleanup_html('\n'.join(output))
 
         return output
 
@@ -700,18 +701,18 @@ class PML_HTMLizer(object):
         t_l3 = None
 
         for level, (href, id, text) in self.toc:
-            if level == u'0':
+            if level == '0':
                 t_l0 = n_toc.add_item(href, id, text)
                 t_l1 = None
                 t_l2 = None
                 t_l3 = None
-            elif level == u'1':
+            elif level == '1':
                 if t_l0 is None:
                     t_l0 = n_toc
                 t_l1 = t_l0.add_item(href, id, text)
                 t_l2 = None
                 t_l3 = None
-            elif level == u'2':
+            elif level == '2':
                 if t_l1 is None:
                     if t_l0 is None:
                         t_l1 = n_toc
@@ -719,7 +720,7 @@ class PML_HTMLizer(object):
                         t_l1 = t_l0
                 t_l2 = t_l1.add_item(href, id, text)
                 t_l3 = None
-            elif level == u'3':
+            elif level == '3':
                 if t_l2 is None:
                     if t_l1 is None:
                         if t_l0 is None:
diff --git a/src/calibre/ebooks/pml/pmlml.py b/src/calibre/ebooks/pml/pmlml.py
index e99ec66226..7685036733 100644
--- a/src/calibre/ebooks/pml/pmlml.py
+++ b/src/calibre/ebooks/pml/pmlml.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2009, John Schember <john@nachtimwald.com>'
@@ -103,7 +104,7 @@ class PMLMLizer(object):
     def pmlmlize_spine(self):
         self.image_hrefs = {}
         self.link_hrefs = {}
-        output = [u'']
+        output = ['']
         output.append(self.get_cover_page())
         output.append(self.get_text())
         output = ''.join(output)
@@ -114,7 +115,7 @@ class PMLMLizer(object):
         from calibre.ebooks.oeb.stylizer import Stylizer
         from calibre.ebooks.oeb.base import XHTML
 
-        output = u''
+        output = ''
         if 'cover' in self.oeb_book.guide:
             output += '\\m="cover.png"\n'
             self.image_hrefs[self.oeb_book.guide['cover'].href] = 'cover.png'
@@ -132,7 +133,7 @@ class PMLMLizer(object):
         from calibre.ebooks.oeb.stylizer import Stylizer
         from calibre.ebooks.oeb.base import XHTML
 
-        text = [u'']
+        text = ['']
         for item in self.oeb_book.spine:
             self.log.debug('Converting %s to PML markup...' % item.href)
             content = etree.tostring(item.data, encoding='unicode')
@@ -155,7 +156,7 @@ class PMLMLizer(object):
 
     def get_anchor(self, page, aid):
         aid = self.get_anchor_id(page.href, aid)
-        return ur'\Q="%s"' % aid
+        return r'\Q="%s"' % aid
 
     def remove_newlines(self, text):
         text = text.replace('\r\n', ' ')
@@ -192,8 +193,8 @@ class PMLMLizer(object):
         text = re.sub(unicode_type(r'(?msu)(?P<t>\\(x|X[0-4]))(?P<a>.*?)(?P<c>\\C[0-4]\s*=\s*"[^"]*")(?P<b>.*?)(?P=t)'), r'\g<t>\g<a>\g<b>\g<t>', text)
 
         # Replace bad characters.
-        text = text.replace(u'\xc2', '')
-        text = text.replace(u'\xa0', ' ')
+        text = text.replace('\xc2', '')
+        text = text.replace('\xa0', ' ')
 
         # Turn all characters that cannot be represented by themself into their
         # PML code equivelent
diff --git a/src/calibre/ebooks/rb/__init__.py b/src/calibre/ebooks/rb/__init__.py
index f45b966dad..f942dc3eb2 100644
--- a/src/calibre/ebooks/rb/__init__.py
+++ b/src/calibre/ebooks/rb/__init__.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2009, John Schember <john@nachtimwald.com>'
@@ -6,6 +7,8 @@ __docformat__ = 'restructuredtext en'
 
 import os
 
+from polyglot.builtins import unicode_type
+
 HEADER = b'\xb0\x0c\xb0\x0c\x02\x00NUVO\x00\x00\x00\x00'
 
 
@@ -21,7 +24,7 @@ def unique_name(name, used_names):
         ext = os.path.splitext(name)[1][:3]
         base_name = name[:22]
         for i in range(0, 9999):
-            name = '%s-%s.%s' % (str(i).rjust('0', 4)[:4], base_name, ext)
+            name = '%s-%s.%s' % (unicode_type(i).rjust('0', 4)[:4], base_name, ext)
             if name not in used_names:
                 break
         return name
diff --git a/src/calibre/ebooks/rb/writer.py b/src/calibre/ebooks/rb/writer.py
index 9f4818725f..af671295bc 100644
--- a/src/calibre/ebooks/rb/writer.py
+++ b/src/calibre/ebooks/rb/writer.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2009, John Schember <john@nachtimwald.com>'
diff --git a/src/calibre/ebooks/readability/cleaners.py b/src/calibre/ebooks/readability/cleaners.py
index d30216c4d8..ee160f594b 100644
--- a/src/calibre/ebooks/readability/cleaners.py
+++ b/src/calibre/ebooks/readability/cleaners.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 # strip out a set of nuisance html attributes that can mess up rendering in RSS feeds
 import re
 from lxml.html.clean import Cleaner
diff --git a/src/calibre/ebooks/readability/debug.py b/src/calibre/ebooks/readability/debug.py
index 103bb5f9f0..c8acf510cf 100644
--- a/src/calibre/ebooks/readability/debug.py
+++ b/src/calibre/ebooks/readability/debug.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 def save_to_file(text, filename):
     f = open(filename, 'wt')
     f.write('<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />')
diff --git a/src/calibre/ebooks/readability/htmls.py b/src/calibre/ebooks/readability/htmls.py
index 692f26c2ca..56aa159508 100644
--- a/src/calibre/ebooks/readability/htmls.py
+++ b/src/calibre/ebooks/readability/htmls.py
@@ -1,3 +1,5 @@
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 import re
 
 from lxml.html import tostring
@@ -20,14 +22,14 @@ def js_re(src, pattern, flags, repl):
 
 def normalize_entities(cur_title):
     entities = {
-        u'\u2014':'-',
-        u'\u2013':'-',
-        u'&mdash;': '-',
-        u'&ndash;': '-',
-        u'\u00A0': ' ',
-        u'\u00AB': '"',
-        u'\u00BB': '"',
-        u'&quot;': '"',
+        '\u2014':'-',
+        '\u2013':'-',
+        '&mdash;': '-',
+        '&ndash;': '-',
+        '\u00A0': ' ',
+        '\u00AB': '"',
+        '\u00BB': '"',
+        '&quot;': '"',
     }
     for c, r in iteritems(entities):
         if c in cur_title:
diff --git a/src/calibre/ebooks/readability/readability.py b/src/calibre/ebooks/readability/readability.py
index bef8caf307..e8cb581b10 100644
--- a/src/calibre/ebooks/readability/readability.py
+++ b/src/calibre/ebooks/readability/readability.py
@@ -156,7 +156,7 @@ class Document:
                     return cleaned_article
         except Exception as e:
             self.log.exception('error getting summary: ')
-            reraise(Unparseable, Unparseable(str(e)), sys.exc_info()[2])
+            reraise(Unparseable, Unparseable(unicode_type(e)), sys.exc_info()[2])
 
     def get_article(self, candidates, best_candidate):
         # Now that we have the top candidate, look through its siblings for content that might also be related.
@@ -216,7 +216,7 @@ class Document:
     def score_paragraphs(self, ):
         MIN_LEN = self.options.get('min_text_length', self.TEXT_LENGTH_THRESHOLD)
         candidates = {}
-        # self.debug(str([describe(node) for node in self.tags(self.html, "div")]))
+        # self.debug(unicode_type([describe(node) for node in self.tags(self.html, "div")]))
 
         ordered = []
         for elem in self.tags(self.html, "p", "pre", "td"):
@@ -316,7 +316,7 @@ class Document:
             if not REGEXES['divToPElementsRe'].search(unicode_type(''.join(map(tounicode, list(elem))))):
                 # self.debug("Altering %s to p" % (describe(elem)))
                 elem.tag = "p"
-                # print "Fixed element "+describe(elem)
+                # print("Fixed element "+describe(elem))
 
         for elem in self.tags(self.html, 'div'):
             if elem.text and elem.text.strip():
@@ -324,7 +324,7 @@ class Document:
                 p.text = elem.text
                 elem.text = None
                 elem.insert(0, p)
-                # print "Appended "+tounicode(p)+" to "+describe(elem)
+                # print("Appended "+tounicode(p)+" to "+describe(elem))
 
             for pos, child in reversed(list(enumerate(elem))):
                 if child.tail and child.tail.strip():
@@ -332,9 +332,9 @@ class Document:
                     p.text = child.tail
                     child.tail = None
                     elem.insert(pos + 1, p)
-                    # print "Inserted "+tounicode(p)+" to "+describe(elem)
+                    # print("Inserted "+tounicode(p)+" to "+describe(elem))
                 if child.tag == 'br':
-                    # print 'Dropped <br> at '+describe(elem)
+                    # print('Dropped <br> at '+describe(elem))
                     child.drop_tree()
 
     def tags(self, node, *tag_names):
@@ -363,7 +363,7 @@ class Document:
             weight = self.class_weight(el)
             if el in candidates:
                 content_score = candidates[el]['content_score']
-                # print '!',el, '-> %6.3f' % content_score
+                # print('!',el, '-> %6.3f' % content_score)
             else:
                 content_score = 0
             tag = el.tag
@@ -457,7 +457,7 @@ class Document:
                             siblings.append(sib_content_length)
                             if j == x:
                                 break
-                    # self.debug(str(siblings))
+                    # self.debug(unicode_type(siblings))
                     if siblings and sum(siblings) > 1000 :
                         to_remove = False
                         self.debug("Allowing %s" % describe(el))
@@ -467,7 +467,7 @@ class Document:
                 if to_remove:
                     self.debug("Cleaned %6.3f %s with weight %s cause it has %s." %
                         (content_score, describe(el), weight, reason))
-                    # print tounicode(el)
+                    # print(tounicode(el))
                     # self.debug("pname %s pweight %.3f" %(pname, pweight))
                     el.drop_tree()
 
diff --git a/src/calibre/ebooks/rtf/input.py b/src/calibre/ebooks/rtf/input.py
index 8ff793b5d4..075eaaa36b 100644
--- a/src/calibre/ebooks/rtf/input.py
+++ b/src/calibre/ebooks/rtf/input.py
@@ -1,4 +1,5 @@
-from __future__ import with_statement
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 __license__   = 'GPL v3'
 __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
 
@@ -36,5 +37,3 @@ class InlineClass(etree.XSLTExtension):
             classes.append('col%d'%self.colors.index(fc))
 
         output_parent.text = ' '.join(classes)
-
-
diff --git a/src/calibre/ebooks/rtf/preprocess.py b/src/calibre/ebooks/rtf/preprocess.py
index aae0a1502d..04d3c1124b 100644
--- a/src/calibre/ebooks/rtf/preprocess.py
+++ b/src/calibre/ebooks/rtf/preprocess.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 absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2010, Gerendi Sandor Attila'
diff --git a/src/calibre/ebooks/rtf/rtfml.py b/src/calibre/ebooks/rtf/rtfml.py
index 7f6cc91c50..5944c4f228 100644
--- a/src/calibre/ebooks/rtf/rtfml.py
+++ b/src/calibre/ebooks/rtf/rtfml.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2009, John Schember <john@nachtimwald.com>'
@@ -83,11 +84,12 @@ def txt2rtf(text):
     for x in text:
         val = ord(x)
         if val == 160:
-            buf.write(ur'\~')
+            buf.write(r'\~')
         elif val <= 127:
             buf.write(unicode_type(x))
         else:
-            c = unicode_type(r'\u{0:d}?'.format(val))
+            # python2 and ur'\u' does not work
+            c = unicode_type('\\u{0:d}?'.format(val))
             buf.write(c)
     return buf.getvalue()
 
@@ -120,7 +122,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('<!--.*?-->', '', etree.tostring(item.data, encoding='unicode'), flags=re.DOTALL)
             content = self.remove_newlines(content)
             content = self.remove_tabs(content)
             content = etree.fromstring(content)
@@ -149,7 +151,7 @@ class RTFMLizer(object):
         return text
 
     def header(self):
-        header = u'{\\rtf1{\\info{\\title %s}{\\author %s}}\\ansi\\ansicpg1252\\deff0\\deflang1033\n' % (
+        header = '{\\rtf1{\\info{\\title %s}{\\author %s}}\\ansi\\ansicpg1252\\deff0\\deflang1033\n' % (
             self.oeb_book.metadata.title[0].value, authors_to_string([x.value for x in self.oeb_book.metadata.creator]))
         return header + (
             '{\\fonttbl{\\f0\\froman\\fprq2\\fcharset128 Times New Roman;}{\\f1\\froman\\fprq2\\fcharset128 Times New Roman;}{\\f2\\fswiss\\fprq2\\fcharset128 Arial;}{\\f3\\fnil\\fprq2\\fcharset128 Arial;}{\\f4\\fnil\\fprq2\\fcharset128 MS Mincho;}{\\f5\\fnil\\fprq2\\fcharset128 Tahoma;}{\\f6\\fnil\\fprq0\\fcharset128 Tahoma;}}\n'  # noqa
@@ -215,7 +217,7 @@ class RTFMLizer(object):
         text = re.sub(r'(\{\\line \}\s*){3,}', r'{\\line }{\\line }', text)
 
         # Remove non-breaking spaces
-        text = text.replace(u'\xa0', ' ')
+        text = text.replace('\xa0', ' ')
         text = text.replace('\n\r', '\n')
 
         return text
@@ -230,16 +232,16 @@ class RTFMLizer(object):
             if p is not None and isinstance(p.tag, string_or_bytes) and namespace(p.tag) == XHTML_NS \
                     and elem.tail:
                 return elem.tail
-            return u''
+            return ''
 
-        text = u''
+        text = ''
         style = stylizer.style(elem)
 
         if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
            or style['visibility'] == 'hidden':
             if hasattr(elem, 'tail') and elem.tail:
                 return elem.tail
-            return u''
+            return ''
 
         tag = barename(elem.tag)
         tag_count = 0
@@ -292,9 +294,9 @@ class RTFMLizer(object):
             end_tag =  tag_stack.pop()
             if end_tag != 'block':
                 if tag in BLOCK_TAGS:
-                    text += ur'\par\pard\plain\hyphpar}'
+                    text += r'\par\pard\plain\hyphpar}'
                 else:
-                    text += u'}'
+                    text += '}'
 
         if hasattr(elem, 'tail') and elem.tail:
             if 'block' in tag_stack:
diff --git a/src/calibre/ebooks/rtf2xml/ParseRtf.py b/src/calibre/ebooks/rtf2xml/ParseRtf.py
index 01a26ba85c..164e706a03 100644
--- a/src/calibre/ebooks/rtf2xml/ParseRtf.py
+++ b/src/calibre/ebooks/rtf2xml/ParseRtf.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals, absolute_import, print_function, division
+from __future__ import absolute_import, division, print_function, unicode_literals
 #########################################################################
 #                                                                       #
 #                                                                       #
@@ -26,6 +26,8 @@ from calibre.ebooks.rtf2xml import headings_to_sections, \
     body_styles, preamble_rest, group_styles, \
     inline
 from calibre.ebooks.rtf2xml.old_rtf import OldRtf
+from polyglot.builtins import unicode_type
+
 from . import open_for_read, open_for_write
 
 """
@@ -248,7 +250,7 @@ class ParseRtf:
             enc = encode_obj.get_codepage()
             # TODO: to check if cp is a good idea or if I should use a dict to convert
             enc = 'cp' + enc
-            msg = '%s\nException in token processing' % str(msg)
+            msg = '%s\nException in token processing' % unicode_type(msg)
             if check_encoding_obj.check_encoding(self.__file, enc):
                 file_name = self.__file if isinstance(self.__file, bytes) \
                                     else self.__file.encode('utf-8')
diff --git a/src/calibre/ebooks/rtf2xml/check_encoding.py b/src/calibre/ebooks/rtf2xml/check_encoding.py
index 37ac305e1f..4f8a04ceda 100644
--- a/src/calibre/ebooks/rtf2xml/check_encoding.py
+++ b/src/calibre/ebooks/rtf2xml/check_encoding.py
@@ -1,7 +1,9 @@
 #!/usr/bin/env python2
-from __future__ import unicode_literals, absolute_import, print_function, division
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 import sys
 
+from polyglot.builtins import unicode_type
 
 class CheckEncoding:
 
@@ -15,7 +17,7 @@ class CheckEncoding:
             try:
                 char.decode(encoding)
             except ValueError as msg:
-                sys.stderr.write('line: %s char: %s\n%s\n' %  (line_num, char_position, str(msg)))
+                sys.stderr.write('line: %s char: %s\n%s\n' %  (line_num, char_position, unicode_type(msg)))
 
     def check_encoding(self, path, encoding='us-ascii', verbose=True):
         line_num = 0
diff --git a/src/calibre/ebooks/rtf2xml/footnote.py b/src/calibre/ebooks/rtf2xml/footnote.py
index 007febb775..36e7624134 100644
--- a/src/calibre/ebooks/rtf2xml/footnote.py
+++ b/src/calibre/ebooks/rtf2xml/footnote.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals, absolute_import, print_function, division
+from __future__ import absolute_import, division, print_function, unicode_literals
 #########################################################################
 #                                                                       #
 #                                                                       #
@@ -15,6 +15,8 @@ import os
 
 from calibre.ebooks.rtf2xml import copy
 from calibre.ptempfile import better_mktemp
+from polyglot.builtins import unicode_type
+
 from . import open_for_read, open_for_write
 
 
@@ -56,7 +58,7 @@ class Footnote:
         if self.__first_line:
             self.__first_line_func(line)
         if self.__token_info == 'cw<ci<footnot-mk':
-            num = str(self.__footnote_count)
+            num = unicode_type(self.__footnote_count)
             self.__write_to_foot_obj.write(line)
             self.__write_to_foot_obj.write(
                 'tx<nu<__________<%s\n' % num
@@ -93,7 +95,7 @@ class Footnote:
             self.__found_footnote(line)
         self.__write_obj.write(line)
         if self.__token_info == 'cw<ci<footnot-mk':
-            num = str(self.__footnote_count + 1)
+            num = unicode_type(self.__footnote_count + 1)
             self.__write_obj.write(
                 'tx<nu<__________<%s\n' % num
             )
diff --git a/src/calibre/ebooks/rtf2xml/hex_2_utf8.py b/src/calibre/ebooks/rtf2xml/hex_2_utf8.py
index 3dbd47acba..71d0f25496 100644
--- a/src/calibre/ebooks/rtf2xml/hex_2_utf8.py
+++ b/src/calibre/ebooks/rtf2xml/hex_2_utf8.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals, absolute_import, print_function, division
+from __future__ import absolute_import, division, print_function, unicode_literals
 #########################################################################
 #                                                                       #
 #                                                                       #
@@ -16,6 +16,8 @@ import sys, os, io
 from calibre.ebooks.rtf2xml import get_char_map, copy
 from calibre.ebooks.rtf2xml.char_set import char_set
 from calibre.ptempfile import better_mktemp
+from polyglot.builtins import unicode_type
+
 from . import open_for_read, open_for_write
 
 
@@ -481,7 +483,7 @@ class Hex2Utf8:
             the_string = ''
             for letter in text:
                 hex_num = hex(ord(letter))
-                hex_num = str(hex_num)
+                hex_num = unicode_type(hex_num)
                 hex_num = hex_num.upper()
                 hex_num = hex_num[2:]
                 hex_num = '\'%s' % hex_num
diff --git a/src/calibre/ebooks/rtf2xml/list_table.py b/src/calibre/ebooks/rtf2xml/list_table.py
index d85b7232b4..8688430cf1 100644
--- a/src/calibre/ebooks/rtf2xml/list_table.py
+++ b/src/calibre/ebooks/rtf2xml/list_table.py
@@ -1,5 +1,4 @@
-from __future__ import unicode_literals, absolute_import, print_function, division
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function, unicode_literals
 #########################################################################
 #                                                                       #
 #                                                                       #
@@ -13,6 +12,8 @@ from __future__ import print_function
 #                                                                       #
 #########################################################################
 
+from polyglot.builtins import unicode_type
+
 
 class ListTable:
     """
@@ -234,7 +235,7 @@ class ListTable:
             """
             num = line[18:]
             num = int(num, 16)
-            level = str(round((num - 1)/2, 0))
+            level = unicode_type(round((num - 1)/2, 0))
             level = level[:-2]
             level = 'level%s-show-level' % level
             self.__all_lists[-1][-1][0][level] = 'true'
@@ -291,11 +292,11 @@ class ListTable:
         num = line[18:]
         the_num = int(num, 16)
         if not self.__found_level_text_length:
-            self.__all_lists[-1][-1][0]['list-text-length'] = str(the_num)
+            self.__all_lists[-1][-1][0]['list-text-length'] = unicode_type(the_num)
             self.__found_level_text_length = 1
         else:
             the_num += 1
-            the_string = str(the_num)
+            the_string = unicode_type(the_num)
             level_marker = 'level%s-suffix' % the_string
             show_marker = 'show-level%s' % the_string
             self.__level_text_position = level_marker
@@ -383,7 +384,7 @@ class ListTable:
         for list in self.__all_lists:
             id += 1
             self.__list_table_final += 'mi<tg<open-att__<list-in-table'
-            # self.__list_table_final += '<list-id>%s' % (str(id))
+            # self.__list_table_final += '<list-id>%s' % (unicode_type(id))
             the_dict = list[0]
             the_keys = the_dict.keys()
             for the_key in the_keys:
@@ -398,7 +399,7 @@ class ListTable:
             for level in levels:
                 level_num += 1
                 self.__list_table_final += 'mi<tg<empty-att_<level-in-table'
-                self.__list_table_final += '<level>%s' % (str(level_num))
+                self.__list_table_final += '<level>%s' % (unicode_type(level_num))
                 the_dict2 = level[0]
                 the_keys2 = the_dict2.keys()
                 is_bullet = 0
diff --git a/src/calibre/ebooks/rtf2xml/make_lists.py b/src/calibre/ebooks/rtf2xml/make_lists.py
index 4cea5b1b13..7cfd07beae 100644
--- a/src/calibre/ebooks/rtf2xml/make_lists.py
+++ b/src/calibre/ebooks/rtf2xml/make_lists.py
@@ -12,8 +12,11 @@ from __future__ import unicode_literals, absolute_import, print_function, divisi
 #                                                                       #
 #########################################################################
 import sys, os, re
+
 from calibre.ebooks.rtf2xml import copy
 from calibre.ptempfile import better_mktemp
+from polyglot.builtins import unicode_type
+
 from . import open_for_read, open_for_write
 
 
@@ -287,7 +290,7 @@ class MakeLists:
             'mi<mk<list_start\n'
                 )
         # bogus levels are sometimes written for empty paragraphs
-        if str(self.__level) not in self.__allow_levels:
+        if unicode_type(self.__level) not in self.__allow_levels:
             lev_num = '0'
         else:
             lev_num = self.__level
diff --git a/src/calibre/ebooks/rtf2xml/old_rtf.py b/src/calibre/ebooks/rtf2xml/old_rtf.py
index aec7604661..65137b55dc 100644
--- a/src/calibre/ebooks/rtf2xml/old_rtf.py
+++ b/src/calibre/ebooks/rtf2xml/old_rtf.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals, absolute_import, print_function, division
+from __future__ import absolute_import, division, print_function, unicode_literals
 #########################################################################
 #                                                                       #
 #                                                                       #
@@ -12,6 +12,9 @@ from __future__ import unicode_literals, absolute_import, print_function, divisi
 #                                                                       #
 #########################################################################
 import sys
+
+from polyglot.builtins import unicode_type
+
 from . import open_for_read
 
 
@@ -136,7 +139,7 @@ class OldRtf:
                     if self.__run_level > 3:
                         sys.stderr.write(
                             'Old rtf construction %s (bracket %s, line %s)\n' % (
-                                self.__inline_info, str(self.__ob_group), line_num)
+                                self.__inline_info, unicode_type(self.__ob_group), line_num)
                         )
                     return True
                 self.__previous_token = line[6:16]
diff --git a/src/calibre/ebooks/rtf2xml/paragraph_def.py b/src/calibre/ebooks/rtf2xml/paragraph_def.py
index 45c2f136ec..f5aab5df05 100644
--- a/src/calibre/ebooks/rtf2xml/paragraph_def.py
+++ b/src/calibre/ebooks/rtf2xml/paragraph_def.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals, absolute_import, print_function, division
+from __future__ import absolute_import, division, print_function, unicode_literals
 #########################################################################
 #                                                                       #
 #                                                                       #
@@ -12,8 +12,11 @@ from __future__ import unicode_literals, absolute_import, print_function, divisi
 #                                                                       #
 #########################################################################
 import sys, os
+
 from calibre.ebooks.rtf2xml import copy, border_parse
 from calibre.ptempfile import better_mktemp
+from polyglot.builtins import unicode_type
+
 from . import open_for_read, open_for_write
 
 
@@ -621,7 +624,7 @@ if another paragraph_def is found, the state changes to collect_tokens.
             num = len(self.__style_num_strings)
             new_style = 1
         num = '%04d' % num
-        self.__att_val_dict['style-num'] = 's' + str(num)
+        self.__att_val_dict['style-num'] = 's' + unicode_type(num)
         if new_style:
             self.__write_body_styles()
 
diff --git a/src/calibre/ebooks/rtf2xml/pict.py b/src/calibre/ebooks/rtf2xml/pict.py
index 62fa905db5..f3b1f74f18 100644
--- a/src/calibre/ebooks/rtf2xml/pict.py
+++ b/src/calibre/ebooks/rtf2xml/pict.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals, absolute_import, print_function, division
+from __future__ import absolute_import, division, print_function, unicode_literals
 #########################################################################
 #                                                                       #
 #                                                                       #
@@ -15,6 +15,8 @@ import sys, os
 
 from calibre.ebooks.rtf2xml import copy
 from calibre.ptempfile import better_mktemp
+from polyglot.builtins import unicode_type
+
 from . import open_for_read, open_for_write
 
 
@@ -76,7 +78,7 @@ class Pict:
             try:
                 os.mkdir(self.__dir_name)
             except OSError as msg:
-                msg = "%sCouldn't make directory '%s':\n" % (str(msg), self.__dir_name)
+                msg = "%sCouldn't make directory '%s':\n" % (unicode_type(msg), self.__dir_name)
                 raise self.__bug_handler
         else:
             if self.__run_level > 1:
diff --git a/src/calibre/ebooks/rtf2xml/process_tokens.py b/src/calibre/ebooks/rtf2xml/process_tokens.py
index c7a720f152..e64fba4d8c 100644
--- a/src/calibre/ebooks/rtf2xml/process_tokens.py
+++ b/src/calibre/ebooks/rtf2xml/process_tokens.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals, absolute_import, print_function, division
+from __future__ import absolute_import, division, print_function, unicode_literals
 #########################################################################
 #                                                                       #
 #                                                                       #
@@ -15,6 +15,8 @@ import os, re
 
 from calibre.ebooks.rtf2xml import copy, check_brackets
 from calibre.ptempfile import better_mktemp
+from polyglot.builtins import unicode_type
+
 from . import open_for_read, open_for_write
 
 
@@ -693,7 +695,7 @@ class ProcessTokens:
         if num[-1] == ';':
             num = num[:-1]
             third_field = 'en'
-        num = str('%X' % int(num))
+        num = unicode_type('%X' % int(num))
         if len(num) != 2:
             num = "0" + num
         return 'cw<%s<%s<%s<%s\n' % (pre, token, third_field, num)
@@ -730,7 +732,7 @@ class ProcessTokens:
             return 0
         num = '%0.2f' % round(numerator/denominator, 2)
         return num
-        string_num = str(num)
+        string_num = unicode_type(num)
         if string_num[-2:] == ".0":
             string_num = string_num[:-2]
         return string_num
diff --git a/src/calibre/ebooks/rtf2xml/sections.py b/src/calibre/ebooks/rtf2xml/sections.py
index 3fbd7b3187..fdc0ed4eb6 100644
--- a/src/calibre/ebooks/rtf2xml/sections.py
+++ b/src/calibre/ebooks/rtf2xml/sections.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals, absolute_import, print_function, division
+from __future__ import absolute_import, division, print_function, unicode_literals
 #########################################################################
 #                                                                       #
 #                                                                       #
@@ -15,6 +15,8 @@ import sys, os
 
 from calibre.ebooks.rtf2xml import copy
 from calibre.ptempfile import better_mktemp
+from polyglot.builtins import unicode_type
+
 from . import open_for_read, open_for_write
 
 
@@ -274,8 +276,8 @@ class Sections:
             my_string += 'mi<tg<close_____<section\n'
         else:
             self.__found_first_sec = 1
-        my_string += 'mi<tg<open-att__<section<num>%s' % str(self.__section_num)
-        my_string += '<num-in-level>%s' % str(self.__section_num)
+        my_string += 'mi<tg<open-att__<section<num>%s' % unicode_type(self.__section_num)
+        my_string += '<num-in-level>%s' % unicode_type(self.__section_num)
         my_string += '<type>rtf-native'
         my_string += '<level>0'
         keys = self.__section_values.keys()
@@ -357,7 +359,7 @@ class Sections:
                     '<num-in-level>%s'
                     '<type>rtf-native'
                     '<level>0\n'
-                    % (str(self.__section_num), str(self.__section_num))
+                    % (unicode_type(self.__section_num), unicode_type(self.__section_num))
                     )
             self.__found_first_sec = 1
         elif self.__token_info == 'tx<nu<__________':
@@ -368,7 +370,7 @@ class Sections:
                     '<num-in-level>%s'
                     '<type>rtf-native'
                     '<level>0\n'
-                    % (str(self.__section_num), str(self.__section_num))
+                    % (unicode_type(self.__section_num), unicode_type(self.__section_num))
                     )
             self.__write_obj.write(
                 'cw<pf<par-def___<true\n'
@@ -461,7 +463,7 @@ class Sections:
         self.__field_num = self.__field_num[1:]
         self.__write_obj.write(
         'mi<tg<close_____<section\n'
-        'mi<tg<open-att__<section<num>%s' % str(num)
+        'mi<tg<open-att__<section<num>%s' % unicode_type(num)
         )
         if self.__list_of_sec_values:
             keys =  self.__list_of_sec_values[0].keys()
@@ -471,7 +473,7 @@ class Sections:
             self.__list_of_sec_values = self.__list_of_sec_values[1:]
         self.__write_obj.write('<level>0')
         self.__write_obj.write('<type>rtf-native')
-        self.__write_obj.write('<num-in-level>%s' % str(self.__section_num))
+        self.__write_obj.write('<num-in-level>%s' % unicode_type(self.__section_num))
         self.__write_obj.write('\n')
         # Look here
 
diff --git a/src/calibre/ebooks/rtf2xml/table.py b/src/calibre/ebooks/rtf2xml/table.py
index 4424a4978a..139dea4971 100644
--- a/src/calibre/ebooks/rtf2xml/table.py
+++ b/src/calibre/ebooks/rtf2xml/table.py
@@ -1,4 +1,4 @@
-from __future__ import unicode_literals, absolute_import, print_function, division
+from __future__ import absolute_import, division, print_function, unicode_literals
 #########################################################################
 #                                                                       #
 #                                                                       #
@@ -12,8 +12,11 @@ from __future__ import unicode_literals, absolute_import, print_function, divisi
 #                                                                       #
 #########################################################################
 import sys, os
+
 from calibre.ebooks.rtf2xml import copy, border_parse
 from calibre.ptempfile import better_mktemp
+from polyglot.builtins import unicode_type
+
 from . import open_for_read, open_for_write
 
 """
@@ -397,13 +400,13 @@ class Table:
             left_position = float(left_position)
         width = new_cell_position - self.__last_cell_position - left_position
         # width = round(width, 2)
-        width = str('%.2f' % width)
+        width = unicode_type('%.2f' % width)
         self.__last_cell_position = new_cell_position
         widths_exists = self.__row_dict.get('widths')
         if widths_exists:
-            self.__row_dict['widths'] += ', %s' % str(width)
+            self.__row_dict['widths'] += ', %s' % unicode_type(width)
         else:
-            self.__row_dict['widths'] = str(width)
+            self.__row_dict['widths'] = unicode_type(width)
         self.__cell_list[-1]['width'] = width
         self.__cell_list.append({})
         self.__cell_widths.append(width)
diff --git a/src/calibre/ebooks/snb/__init__.py b/src/calibre/ebooks/snb/__init__.py
index 3d97812b9b..25d2014767 100644
--- a/src/calibre/ebooks/snb/__init__.py
+++ b/src/calibre/ebooks/snb/__init__.py
@@ -1,4 +1,6 @@
 #!/usr/bin/env  python2
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 __license__   = 'GPL v3'
 __copyright__ = '2010, Li Fanxi <lifanxi@freemindworld.com>'
 __docformat__ = 'restructuredtext en'
@@ -6,4 +8,3 @@ __docformat__ = 'restructuredtext en'
 '''
 Used for snb output
 '''
-
diff --git a/src/calibre/ebooks/snb/snbml.py b/src/calibre/ebooks/snb/snbml.py
index 659959e6f0..c93d3d3701 100644
--- a/src/calibre/ebooks/snb/snbml.py
+++ b/src/calibre/ebooks/snb/snbml.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2010, Li Fanxi <lifanxi@freemindworld.com>'
@@ -93,19 +94,19 @@ class SNBMLizer(object):
             snbcHead = etree.SubElement(snbcTree, "head")
             etree.SubElement(snbcHead, "title").text = subtitle
             if self.opts and self.opts.snb_hide_chapter_name:
-                etree.SubElement(snbcHead, "hidetitle").text = u"true"
+                etree.SubElement(snbcHead, "hidetitle").text = "true"
             etree.SubElement(snbcTree, "body")
             trees[subitem] = snbcTree
-        output.append(u'%s%s\n\n' % (CALIBRE_SNB_BM_TAG, ""))
+        output.append('%s%s\n\n' % (CALIBRE_SNB_BM_TAG, ""))
         output += self.dump_text(self.subitems, etree.fromstring(content), stylizer)[0]
-        output = self.cleanup_text(u''.join(output))
+        output = self.cleanup_text(''.join(output))
 
         subitem = ''
         bodyTree = trees[subitem].find(".//body")
         for line in output.splitlines():
             pos = line.find(CALIBRE_SNB_PRE_TAG)
             if pos == -1:
-                line = line.strip(u' \t\n\r\u3000')
+                line = line.strip(' \t\n\r\u3000')
             else:
                 etree.SubElement(bodyTree, "text").text = \
                     etree.CDATA(line[pos+len(CALIBRE_SNB_PRE_TAG):])
@@ -124,14 +125,14 @@ class SNBMLizer(object):
                     bodyTree = trees[subitem].find(".//body")
                 else:
                     if self.opts and not self.opts.snb_dont_indent_first_line:
-                        prefix = u'\u3000\u3000'
+                        prefix = '\u3000\u3000'
                     else:
-                        prefix = u''
+                        prefix = ''
                     etree.SubElement(bodyTree, "text").text = \
                         etree.CDATA(unicode_type(prefix + line))
                 if self.opts and self.opts.snb_insert_empty_line:
                     etree.SubElement(bodyTree, "text").text = \
-                        etree.CDATA(u'')
+                        etree.CDATA('')
 
         return trees
 
@@ -146,9 +147,9 @@ class SNBMLizer(object):
     def cleanup_text(self, text):
         self.log.debug('\tClean up text...')
         # Replace bad characters.
-        text = text.replace(u'\xc2', '')
-        text = text.replace(u'\xa0', ' ')
-        text = text.replace(u'\xa9', '(C)')
+        text = text.replace('\xc2', '')
+        text = text.replace('\xa0', ' ')
+        text = text.replace('\xa9', '(C)')
 
         # Replace tabs, vertical tags and form feeds with single space.
         text = text.replace('\t+', ' ')
@@ -226,7 +227,7 @@ class SNBMLizer(object):
         if elem.attrib.get('id') is not None and elem.attrib['id'] in [href for href, title in subitems]:
             if self.curSubItem is not None and self.curSubItem != elem.attrib['id']:
                 self.curSubItem = elem.attrib['id']
-                text.append(u'\n\n%s%s\n\n' % (CALIBRE_SNB_BM_TAG, self.curSubItem))
+                text.append('\n\n%s%s\n\n' % (CALIBRE_SNB_BM_TAG, self.curSubItem))
 
         if style['display'] in ('none', 'oeb-page-head', 'oeb-page-foot') \
            or style['visibility'] == 'hidden':
@@ -240,18 +241,18 @@ class SNBMLizer(object):
         # Are we in a paragraph block?
         if tag in BLOCK_TAGS or style['display'] in BLOCK_STYLES:
             in_block = True
-            if not end.endswith(u'\n\n') and hasattr(elem, 'text') and elem.text:
-                text.append(u'\n\n')
+            if not end.endswith('\n\n') and hasattr(elem, 'text') and elem.text:
+                text.append('\n\n')
 
         if tag in SPACE_TAGS:
             if not end.endswith('u ') and hasattr(elem, 'text') and elem.text:
-                text.append(u' ')
+                text.append(' ')
 
         if tag == 'img':
-            text.append(u'\n\n%s%s\n\n' % (CALIBRE_SNB_IMG_TAG, ProcessFileName(elem.attrib['src'])))
+            text.append('\n\n%s%s\n\n' % (CALIBRE_SNB_IMG_TAG, ProcessFileName(elem.attrib['src'])))
 
         if tag == 'br':
-            text.append(u'\n\n')
+            text.append('\n\n')
 
         if tag == 'li':
             li = '- '
@@ -260,24 +261,24 @@ class SNBMLizer(object):
         # Process tags that contain text.
         if hasattr(elem, 'text') and elem.text:
             if pre:
-                text.append((u'\n\n%s' % CALIBRE_SNB_PRE_TAG).join((li + elem.text).splitlines()))
+                text.append(('\n\n%s' % CALIBRE_SNB_PRE_TAG).join((li + elem.text).splitlines()))
             else:
                 text.append(li + elem.text)
             li = ''
 
         for item in elem:
-            en = u''
+            en = ''
             if len(text) >= 2:
                 en = text[-1][-2:]
             t = self.dump_text(subitems, item, stylizer, en, pre, li)[0]
             text += t
 
         if in_block:
-            text.append(u'\n\n')
+            text.append('\n\n')
 
         if hasattr(elem, 'tail') and elem.tail:
             if pre:
-                text.append((u'\n\n%s' % CALIBRE_SNB_PRE_TAG).join(elem.tail.splitlines()))
+                text.append(('\n\n%s' % CALIBRE_SNB_PRE_TAG).join(elem.tail.splitlines()))
             else:
                 text.append(li + elem.tail)
             li = ''
diff --git a/src/calibre/ebooks/unihandecode/__init__.py b/src/calibre/ebooks/unihandecode/__init__.py
index 153d8221fe..91238eddaa 100644
--- a/src/calibre/ebooks/unihandecode/__init__.py
+++ b/src/calibre/ebooks/unihandecode/__init__.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
@@ -27,13 +28,13 @@ class Unihandecoder(object):
     def __init__(self, lang="zh", encoding='utf-8'):
         self.preferred_encoding = encoding
         lang = lang.lower()
-        if lang[:2] == u'ja':
+        if lang[:2] == 'ja':
             from calibre.ebooks.unihandecode.jadecoder import Jadecoder
             self.decoder = Jadecoder()
-        elif lang[:2] == u'kr' or lang == u'korean':
+        elif lang[:2] == 'kr' or lang == 'korean':
             from calibre.ebooks.unihandecode.krdecoder import Krdecoder
             self.decoder = Krdecoder()
-        elif lang[:2] == u'vn' or lang == u'vietnum':
+        elif lang[:2] == 'vn' or lang == 'vietnum':
             from calibre.ebooks.unihandecode.vndecoder import Vndecoder
             self.decoder = Vndecoder()
         else:  # zh and others
diff --git a/src/calibre/ebooks/unihandecode/jacodepoints.py b/src/calibre/ebooks/unihandecode/jacodepoints.py
index 5d8e3db279..89d83d94b6 100644
--- a/src/calibre/ebooks/unihandecode/jacodepoints.py
+++ b/src/calibre/ebooks/unihandecode/jacodepoints.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2010 Hiroshi Miura <miurahr@linux.com>'
@@ -9,7 +10,7 @@ Unicode code point dictionary.
 Based on Unicode.org Unihan database.
 '''
 
-CODEPOINTS = { 
+CODEPOINTS = {
     'x34':[
         'Qiu ','Tian ','','','Kua ','Wu ','Yin ','','','','','','Si ','','','',
         '','','','','','','Ye ','','','','','','Chou ','','','',
diff --git a/src/calibre/ebooks/unihandecode/jadecoder.py b/src/calibre/ebooks/unihandecode/jadecoder.py
index b49c1144c0..d6318c270d 100644
--- a/src/calibre/ebooks/unihandecode/jadecoder.py
+++ b/src/calibre/ebooks/unihandecode/jadecoder.py
@@ -1,4 +1,6 @@
 # coding:utf-8
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 __license__ = 'GPL 3'
 __copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
 __docformat__ = 'restructuredtext en'
@@ -39,4 +41,3 @@ class Jadecoder(Unidecoder):
             return re.sub('[^\x00-\x7f]', lambda x: self.replace_point(x.group()),result)
         except:
             return re.sub('[^\x00-\x7f]', lambda x: self.replace_point(x.group()),text)
-
diff --git a/src/calibre/ebooks/unihandecode/krcodepoints.py b/src/calibre/ebooks/unihandecode/krcodepoints.py
index cdb711afdd..bca8e3f4b4 100644
--- a/src/calibre/ebooks/unihandecode/krcodepoints.py
+++ b/src/calibre/ebooks/unihandecode/krcodepoints.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2010 Hiroshi Miura <miurahr@linux.com>'
@@ -9,7 +10,7 @@ Unicode code point dictionary.
 Based on Unicode.org Unihan database.
 '''
 
-CODEPOINTS = { 
+CODEPOINTS = {
     'x34':[
         'Qiu ','Tian ','','','Kua ','Wu ','Yin ','','','','','','Si ','','','',
         '','','','','','','Ye ','','','','','','Chou ','','','',
diff --git a/src/calibre/ebooks/unihandecode/krdecoder.py b/src/calibre/ebooks/unihandecode/krdecoder.py
index af5b3b39e8..914f6f41c6 100644
--- a/src/calibre/ebooks/unihandecode/krdecoder.py
+++ b/src/calibre/ebooks/unihandecode/krdecoder.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
@@ -22,4 +23,3 @@ class Krdecoder(Unidecoder):
     def __init__(self):
         self.codepoints = CODEPOINTS
         self.codepoints.update(HANCODES)
-
diff --git a/src/calibre/ebooks/unihandecode/pykakasi/__init__.py b/src/calibre/ebooks/unihandecode/pykakasi/__init__.py
index c92e541a82..4995491752 100644
--- a/src/calibre/ebooks/unihandecode/pykakasi/__init__.py
+++ b/src/calibre/ebooks/unihandecode/pykakasi/__init__.py
@@ -1,5 +1,6 @@
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 from calibre.ebooks.unihandecode.pykakasi.kakasi import kakasi
 kakasi
 
 __all__ = ["pykakasi"]
-
diff --git a/src/calibre/ebooks/unihandecode/pykakasi/h2a.py b/src/calibre/ebooks/unihandecode/pykakasi/h2a.py
index 409a110093..ebbf06fdf3 100644
--- a/src/calibre/ebooks/unihandecode/pykakasi/h2a.py
+++ b/src/calibre/ebooks/unihandecode/pykakasi/h2a.py
@@ -20,6 +20,7 @@
 # * GNU General Public License for more details.
 # *
 # */
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 from polyglot.builtins import range
 
@@ -27,137 +28,137 @@ from polyglot.builtins import range
 class H2a (object):
 
     H2a_table = {
-        u"\u3041":"a", u"\u3042":"a",
-        u"\u3043":"i", u"\u3044":"i",
-        u"\u3045":"u", u"\u3046":"u",
-        u"\u3046\u309b":"vu", u"\u3046\u309b\u3041":"va",
-        u"\u3046\u309b\u3043":"vi", u"\u3046\u309b\u3047":"ve",
-        u"\u3046\u309b\u3049":"vo",
-        u"\u3047":"e", u"\u3048":"e",
-        u"\u3049":"o", u"\u304a":"o",
+        "\u3041":"a", "\u3042":"a",
+        "\u3043":"i", "\u3044":"i",
+        "\u3045":"u", "\u3046":"u",
+        "\u3046\u309b":"vu", "\u3046\u309b\u3041":"va",
+        "\u3046\u309b\u3043":"vi", "\u3046\u309b\u3047":"ve",
+        "\u3046\u309b\u3049":"vo",
+        "\u3047":"e", "\u3048":"e",
+        "\u3049":"o", "\u304a":"o",
 
-        u"\u304b":"ka", u"\u304c":"ga",
-        u"\u304d":"ki", u"\u304d\u3041":"kya",
-        u"\u304d\u3045":"kyu", u"\u304d\u3049":"kyo",
-        u"\u304e":"gi", u"\u3050\u3083":"gya",
-        u"\u304e\u3045":"gyu", u"\u304e\u3087":"gyo",
-        u"\u304f":"ku", u"\u3050":"gu",
-        u"\u3051":"ke", u"\u3052":"ge",
-        u"\u3053":"ko", u"\u3054":"go",
+        "\u304b":"ka", "\u304c":"ga",
+        "\u304d":"ki", "\u304d\u3041":"kya",
+        "\u304d\u3045":"kyu", "\u304d\u3049":"kyo",
+        "\u304e":"gi", "\u3050\u3083":"gya",
+        "\u304e\u3045":"gyu", "\u304e\u3087":"gyo",
+        "\u304f":"ku", "\u3050":"gu",
+        "\u3051":"ke", "\u3052":"ge",
+        "\u3053":"ko", "\u3054":"go",
 
-        u"\u3055":"sa", u"\u3056":"za",
-        u"\u3057":"shi", u"\u3057\u3083":"sha",
-        u"\u3057\u3085":"shu", u"\u3057\u3087":"sho",
-        u"\u3058":"ji", u"\u3058\u3083":"ja",
-        u"\u3058\u3085":"ju", u"\u3058\u3087":"jo",
-        u"\u3059":"su", u"\u305a":"zu",
-        u"\u305b":"se", u"\u305c":"ze",
-        u"\u305d":"so", u"\u305e":"zo",
+        "\u3055":"sa", "\u3056":"za",
+        "\u3057":"shi", "\u3057\u3083":"sha",
+        "\u3057\u3085":"shu", "\u3057\u3087":"sho",
+        "\u3058":"ji", "\u3058\u3083":"ja",
+        "\u3058\u3085":"ju", "\u3058\u3087":"jo",
+        "\u3059":"su", "\u305a":"zu",
+        "\u305b":"se", "\u305c":"ze",
+        "\u305d":"so", "\u305e":"zo",
 
-        u"\u305f":"ta", u"\u3060":"da",
-        u"\u3061":"chi", u"\u3061\u3047":"che", u"\u3061\u3083":"cha",
-        u"\u3061\u3085":"chu", u"\u3061\u3087":"cho",
-        u"\u3062":"ji", u"\u3062\u3083":"ja",
-        u"\u3062\u3085":"ju", u"\u3062\u3087":"jo",
+        "\u305f":"ta", "\u3060":"da",
+        "\u3061":"chi", "\u3061\u3047":"che", "\u3061\u3083":"cha",
+        "\u3061\u3085":"chu", "\u3061\u3087":"cho",
+        "\u3062":"ji", "\u3062\u3083":"ja",
+        "\u3062\u3085":"ju", "\u3062\u3087":"jo",
 
-        u"\u3063":"tsu",
-        u"\u3063\u3046\u309b":"vvu",
-        u"\u3063\u3046\u309b\u3041":"vva",
-        u"\u3063\u3046\u309b\u3043":"vvi",
-        u"\u3063\u3046\u309b\u3047":"vve",
-        u"\u3063\u3046\u309b\u3049":"vvo",
-        u"\u3063\u304b":"kka", u"\u3063\u304c":"gga",
-        u"\u3063\u304d":"kki", u"\u3063\u304d\u3083":"kkya",
-        u"\u3063\u304d\u3085":"kkyu", u"\u3063\u304d\u3087":"kkyo",
-        u"\u3063\u304e":"ggi", u"\u3063\u304e\u3083":"ggya",
-        u"\u3063\u304e\u3085":"ggyu", u"\u3063\u304e\u3087":"ggyo",
-        u"\u3063\u304f":"kku", u"\u3063\u3050":"ggu",
-        u"\u3063\u3051":"kke", u"\u3063\u3052":"gge",
-        u"\u3063\u3053":"kko", u"\u3063\u3054":"ggo",
-        u"\u3063\u3055":"ssa", u"\u3063\u3056":"zza",
-        u"\u3063\u3057":"sshi", u"\u3063\u3057\u3083":"ssha",
-        u"\u3063\u3057\u3085":"sshu", u"\u3063\u3057\u3087":"ssho",
-        u"\u3063\u3058":"jji", u"\u3063\u3058\u3083":"jja",
-        u"\u3063\u3058\u3085":"jju", u"\u3063\u3058\u3087":"jjo",
-        u"\u3063\u3059":"ssu", u"\u3063\u305a":"zzu",
-        u"\u3063\u305b":"sse", u"\u3063\u305e":"zze",
-        u"\u3063\u305d":"sso", u"\u3063\u305c":"zzo",
-        u"\u3063\u305f":"tta", u"\u3063\u3060":"dda",
-        u"\u3063\u3061":"tchi", u"\u3063\u3061\u3083":"tcha",
-        u"\u3063\u3061\u3085":"tchu", u"\u3063\u3061\u3087":"tcho",
-        u"\u3063\u3062":"jji", u"\u3063\u3062\u3083":"jjya",
-        u"\u3063\u3062\u3085":"jjyu", u"\u3063\u3062\u3087":"jjyo",
-        u"\u3063\u3064":"ttsu", u"\u3063\u3065":"zzu",
-        u"\u3063\u3066":"tte", u"\u3063\u3067":"dde",
-        u"\u3063\u3068":"tto", u"\u3063\u3069":"ddo",
-        u"\u3063\u306f":"hha", u"\u3063\u3070":"bba",
-        u"\u3063\u3071":"ppa",
-        u"\u3063\u3072":"hhi", u"\u3063\u3072\u3083":"hhya",
-        u"\u3063\u3072\u3085":"hhyu", u"\u3063\u3072\u3087":"hhyo",
-        u"\u3063\u3073":"bbi", u"\u3063\u3073\u3083":"bbya",
-        u"\u3063\u3073\u3085":"bbyu", u"\u3063\u3073\u3087":"bbyo",
-        u"\u3063\u3074":"ppi", u"\u3063\u3074\u3083":"ppya",
-        u"\u3063\u3074\u3085":"ppyu", u"\u3063\u3074\u3087":"ppyo",
-        u"\u3063\u3075":"ffu", u"\u3063\u3075\u3041":"ffa",
-        u"\u3063\u3075\u3043":"ffi", u"\u3063\u3075\u3047":"ffe",
-        u"\u3063\u3075\u3049":"ffo",
-        u"\u3063\u3076":"bbu", u"\u3063\u3077":"ppu",
-        u"\u3063\u3078":"hhe", u"\u3063\u3079":"bbe",
-        u"\u3063\u307a":"ppe",
-        u"\u3063\u307b":"hho", u"\u3063\u307c":"bbo",
-        u"\u3063\u307d":"ppo",
-        u"\u3063\u3084":"yya", u"\u3063\u3086":"yyu",
-        u"\u3063\u3088":"yyo",
-        u"\u3063\u3089":"rra", u"\u3063\u308a":"rri",
-        u"\u3063\u308a\u3083":"rrya", u"\u3063\u308a\u3085":"rryu",
-        u"\u3063\u308a\u3087":"rryo",
-        u"\u3063\u308b":"rru", u"\u3063\u308c":"rre",
-        u"\u3063\u308d":"rro",
+        "\u3063":"tsu",
+        "\u3063\u3046\u309b":"vvu",
+        "\u3063\u3046\u309b\u3041":"vva",
+        "\u3063\u3046\u309b\u3043":"vvi",
+        "\u3063\u3046\u309b\u3047":"vve",
+        "\u3063\u3046\u309b\u3049":"vvo",
+        "\u3063\u304b":"kka", "\u3063\u304c":"gga",
+        "\u3063\u304d":"kki", "\u3063\u304d\u3083":"kkya",
+        "\u3063\u304d\u3085":"kkyu", "\u3063\u304d\u3087":"kkyo",
+        "\u3063\u304e":"ggi", "\u3063\u304e\u3083":"ggya",
+        "\u3063\u304e\u3085":"ggyu", "\u3063\u304e\u3087":"ggyo",
+        "\u3063\u304f":"kku", "\u3063\u3050":"ggu",
+        "\u3063\u3051":"kke", "\u3063\u3052":"gge",
+        "\u3063\u3053":"kko", "\u3063\u3054":"ggo",
+        "\u3063\u3055":"ssa", "\u3063\u3056":"zza",
+        "\u3063\u3057":"sshi", "\u3063\u3057\u3083":"ssha",
+        "\u3063\u3057\u3085":"sshu", "\u3063\u3057\u3087":"ssho",
+        "\u3063\u3058":"jji", "\u3063\u3058\u3083":"jja",
+        "\u3063\u3058\u3085":"jju", "\u3063\u3058\u3087":"jjo",
+        "\u3063\u3059":"ssu", "\u3063\u305a":"zzu",
+        "\u3063\u305b":"sse", "\u3063\u305e":"zze",
+        "\u3063\u305d":"sso", "\u3063\u305c":"zzo",
+        "\u3063\u305f":"tta", "\u3063\u3060":"dda",
+        "\u3063\u3061":"tchi", "\u3063\u3061\u3083":"tcha",
+        "\u3063\u3061\u3085":"tchu", "\u3063\u3061\u3087":"tcho",
+        "\u3063\u3062":"jji", "\u3063\u3062\u3083":"jjya",
+        "\u3063\u3062\u3085":"jjyu", "\u3063\u3062\u3087":"jjyo",
+        "\u3063\u3064":"ttsu", "\u3063\u3065":"zzu",
+        "\u3063\u3066":"tte", "\u3063\u3067":"dde",
+        "\u3063\u3068":"tto", "\u3063\u3069":"ddo",
+        "\u3063\u306f":"hha", "\u3063\u3070":"bba",
+        "\u3063\u3071":"ppa",
+        "\u3063\u3072":"hhi", "\u3063\u3072\u3083":"hhya",
+        "\u3063\u3072\u3085":"hhyu", "\u3063\u3072\u3087":"hhyo",
+        "\u3063\u3073":"bbi", "\u3063\u3073\u3083":"bbya",
+        "\u3063\u3073\u3085":"bbyu", "\u3063\u3073\u3087":"bbyo",
+        "\u3063\u3074":"ppi", "\u3063\u3074\u3083":"ppya",
+        "\u3063\u3074\u3085":"ppyu", "\u3063\u3074\u3087":"ppyo",
+        "\u3063\u3075":"ffu", "\u3063\u3075\u3041":"ffa",
+        "\u3063\u3075\u3043":"ffi", "\u3063\u3075\u3047":"ffe",
+        "\u3063\u3075\u3049":"ffo",
+        "\u3063\u3076":"bbu", "\u3063\u3077":"ppu",
+        "\u3063\u3078":"hhe", "\u3063\u3079":"bbe",
+        "\u3063\u307a":"ppe",
+        "\u3063\u307b":"hho", "\u3063\u307c":"bbo",
+        "\u3063\u307d":"ppo",
+        "\u3063\u3084":"yya", "\u3063\u3086":"yyu",
+        "\u3063\u3088":"yyo",
+        "\u3063\u3089":"rra", "\u3063\u308a":"rri",
+        "\u3063\u308a\u3083":"rrya", "\u3063\u308a\u3085":"rryu",
+        "\u3063\u308a\u3087":"rryo",
+        "\u3063\u308b":"rru", "\u3063\u308c":"rre",
+        "\u3063\u308d":"rro",
 
-        u"\u3064":"tsu", u"\u3065":"zu",
-        u"\u3066":"te", u"\u3067":"de", u"\u3067\u3043":"di",
-        u"\u3068":"to", u"\u3069":"do",
+        "\u3064":"tsu", "\u3065":"zu",
+        "\u3066":"te", "\u3067":"de", "\u3067\u3043":"di",
+        "\u3068":"to", "\u3069":"do",
 
-        u"\u306a":"na",
-        u"\u306b":"ni", u"\u306b\u3083":"nya",
-        u"\u306b\u3085":"nyu", u"\u306b\u3087":"nyo",
-        u"\u306c":"nu", u"\u306d":"ne", u"\u306e":"no",
+        "\u306a":"na",
+        "\u306b":"ni", "\u306b\u3083":"nya",
+        "\u306b\u3085":"nyu", "\u306b\u3087":"nyo",
+        "\u306c":"nu", "\u306d":"ne", "\u306e":"no",
 
-        u"\u306f":"ha", u"\u3070":"ba", u"\u3071":"pa",
-        u"\u3072":"hi", u"\u3072\u3083":"hya",
-        u"\u3072\u3085":"hyu", u"\u3072\u3087":"hyo",
-        u"\u3073":"bi", u"\u3073\u3083":"bya",
-        u"\u3073\u3085":"byu", u"\u3073\u3087":"byo",
-        u"\u3074":"pi", u"\u3074\u3083":"pya",
-        u"\u3074\u3085":"pyu", u"\u3074\u3087":"pyo",
-        u"\u3075":"fu", u"\u3075\u3041":"fa",
-        u"\u3075\u3043":"fi", u"\u3075\u3047":"fe",
-        u"\u3075\u3049":"fo",
-        u"\u3076":"bu", u"\u3077":"pu",
-        u"\u3078":"he", u"\u3079":"be", u"\u307a":"pe",
-        u"\u307b":"ho", u"\u307c":"bo", u"\u307d":"po",
+        "\u306f":"ha", "\u3070":"ba", "\u3071":"pa",
+        "\u3072":"hi", "\u3072\u3083":"hya",
+        "\u3072\u3085":"hyu", "\u3072\u3087":"hyo",
+        "\u3073":"bi", "\u3073\u3083":"bya",
+        "\u3073\u3085":"byu", "\u3073\u3087":"byo",
+        "\u3074":"pi", "\u3074\u3083":"pya",
+        "\u3074\u3085":"pyu", "\u3074\u3087":"pyo",
+        "\u3075":"fu", "\u3075\u3041":"fa",
+        "\u3075\u3043":"fi", "\u3075\u3047":"fe",
+        "\u3075\u3049":"fo",
+        "\u3076":"bu", "\u3077":"pu",
+        "\u3078":"he", "\u3079":"be", "\u307a":"pe",
+        "\u307b":"ho", "\u307c":"bo", "\u307d":"po",
 
-        u"\u307e":"ma",
-        u"\u307f":"mi", u"\u307f\u3083":"mya",
-        u"\u307f\u3085":"myu", u"\u307f\u3087":"myo",
-        u"\u3080":"mu", u"\u3081":"me", u"\u3082":"mo",
+        "\u307e":"ma",
+        "\u307f":"mi", "\u307f\u3083":"mya",
+        "\u307f\u3085":"myu", "\u307f\u3087":"myo",
+        "\u3080":"mu", "\u3081":"me", "\u3082":"mo",
 
-        u"\u3083":"ya", u"\u3084":"ya",
-        u"\u3085":"yu", u"\u3086":"yu",
-        u"\u3087":"yo", u"\u3088":"yo",
+        "\u3083":"ya", "\u3084":"ya",
+        "\u3085":"yu", "\u3086":"yu",
+        "\u3087":"yo", "\u3088":"yo",
 
-        u"\u3089":"ra",
-        u"\u308a":"ri", u"\u308a\u3083":"rya",
-        u"\u308a\u3085":"ryu", u"\u308a\u3087":"ryo",
-        u"\u308b":"ru", u"\u308c":"re", u"\u308d":"ro",
+        "\u3089":"ra",
+        "\u308a":"ri", "\u308a\u3083":"rya",
+        "\u308a\u3085":"ryu", "\u308a\u3087":"ryo",
+        "\u308b":"ru", "\u308c":"re", "\u308d":"ro",
 
-        u"\u308e":"wa", u"\u308f":"wa",
-        u"\u3090":"i", u"\u3091":"e",
-        u"\u3092":"wo", u"\u3093":"n",
+        "\u308e":"wa", "\u308f":"wa",
+        "\u3090":"i", "\u3091":"e",
+        "\u3092":"wo", "\u3093":"n",
 
-        u"\u3093\u3042":"n'a", u"\u3093\u3044":"n'i",
-        u"\u3093\u3046":"n'u", u"\u3093\u3048":"n'e",
-        u"\u3093\u304a":"n'o",
+        "\u3093\u3042":"n'a", "\u3093\u3044":"n'i",
+        "\u3093\u3046":"n'u", "\u3093\u3048":"n'e",
+        "\u3093\u304a":"n'o",
     }
 
 # this class is Borg
diff --git a/src/calibre/ebooks/unihandecode/pykakasi/j2h.py b/src/calibre/ebooks/unihandecode/pykakasi/j2h.py
index 79cd2c29ac..3a9d836df2 100644
--- a/src/calibre/ebooks/unihandecode/pykakasi/j2h.py
+++ b/src/calibre/ebooks/unihandecode/pykakasi/j2h.py
@@ -20,6 +20,7 @@
 # * GNU General Public License for more details.
 # *
 # */
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 import re
 
@@ -48,7 +49,7 @@ class J2H (object):
         return (0x3400 <= ord(c) and ord(c) < 0xfa2e)
 
     def isCletter(self, l, c):
-        if (ord(u"ぁ") <= ord(c) and ord(c) <= 0x309f) and (l in self.cl_table[ord(c) - ord(u"ぁ")-1]):
+        if (ord("ぁ") <= ord(c) and ord(c) <= 0x309f) and (l in self.cl_table[ord(c) - ord("ぁ")-1]):
             return True
         return False
 
diff --git a/src/calibre/ebooks/unihandecode/pykakasi/jisyo.py b/src/calibre/ebooks/unihandecode/pykakasi/jisyo.py
index 6ff55ad90d..2c1c95f32a 100644
--- a/src/calibre/ebooks/unihandecode/pykakasi/jisyo.py
+++ b/src/calibre/ebooks/unihandecode/pykakasi/jisyo.py
@@ -2,6 +2,8 @@
 #  jisyo.py
 #
 # Copyright 2011 Hiroshi Miura <miurahr@linux.com>
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 from zlib import decompress
 
 from polyglot.builtins import unicode_type
diff --git a/src/calibre/ebooks/unihandecode/pykakasi/k2a.py b/src/calibre/ebooks/unihandecode/pykakasi/k2a.py
index 7650199128..fb5b5da1ac 100644
--- a/src/calibre/ebooks/unihandecode/pykakasi/k2a.py
+++ b/src/calibre/ebooks/unihandecode/pykakasi/k2a.py
@@ -20,6 +20,7 @@
 # * GNU General Public License for more details.
 # *
 # */
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 from calibre.ebooks.unihandecode.pykakasi.jisyo import jisyo
 from polyglot.builtins import range
diff --git a/src/calibre/ebooks/unihandecode/pykakasi/kakasi.py b/src/calibre/ebooks/unihandecode/pykakasi/kakasi.py
index 39b84b545a..47a8c026f8 100644
--- a/src/calibre/ebooks/unihandecode/pykakasi/kakasi.py
+++ b/src/calibre/ebooks/unihandecode/pykakasi/kakasi.py
@@ -20,6 +20,7 @@
 # * GNU General Public License for more details.
 # *
 # */
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 from calibre.ebooks.unihandecode.pykakasi.j2h import J2H
 from calibre.ebooks.unihandecode.pykakasi.h2a import H2a
@@ -94,4 +95,3 @@ class kakasi(object):
                 i += 1
 
         return otext
-
diff --git a/src/calibre/ebooks/unihandecode/unicodepoints.py b/src/calibre/ebooks/unihandecode/unicodepoints.py
index d9130123fb..13eeed2e03 100644
--- a/src/calibre/ebooks/unihandecode/unicodepoints.py
+++ b/src/calibre/ebooks/unihandecode/unicodepoints.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2009, John Schember <john@nachtimwald.com>'
diff --git a/src/calibre/ebooks/unihandecode/unidecoder.py b/src/calibre/ebooks/unihandecode/unidecoder.py
index 748fcb64f1..e66a11da2f 100644
--- a/src/calibre/ebooks/unihandecode/unidecoder.py
+++ b/src/calibre/ebooks/unihandecode/unidecoder.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
diff --git a/src/calibre/ebooks/unihandecode/vncodepoints.py b/src/calibre/ebooks/unihandecode/vncodepoints.py
index 7e10fde1c8..2a74bb157b 100644
--- a/src/calibre/ebooks/unihandecode/vncodepoints.py
+++ b/src/calibre/ebooks/unihandecode/vncodepoints.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2010 Hiroshi Miura <miurahr@linux.com>'
@@ -9,7 +10,7 @@ Unicode code point dictionary.
 Based on Unicode.org Unihan database.
 '''
 
-CODEPOINTS = { 
+CODEPOINTS = {
     'x34':[
         'Qiu ','Tian ','','','Kua ','Wu ','Yin ','','','','','','Si ','','','',
         '','','','','','','Ye ','','','','','','Chou ','','','',
diff --git a/src/calibre/ebooks/unihandecode/vndecoder.py b/src/calibre/ebooks/unihandecode/vndecoder.py
index 76d926d7b7..60ee7fbdf9 100644
--- a/src/calibre/ebooks/unihandecode/vndecoder.py
+++ b/src/calibre/ebooks/unihandecode/vndecoder.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2010, Hiroshi Miura <miurahr@linux.com>'
@@ -21,4 +22,3 @@ class Vndecoder(Unidecoder):
     def __init__(self):
         self.codepoints = CODEPOINTS
         self.codepoints.update(HANCODES)
-
diff --git a/src/calibre/ebooks/unihandecode/zhcodepoints.py b/src/calibre/ebooks/unihandecode/zhcodepoints.py
index 1715ecb46e..57e4de3326 100644
--- a/src/calibre/ebooks/unihandecode/zhcodepoints.py
+++ b/src/calibre/ebooks/unihandecode/zhcodepoints.py
@@ -1,4 +1,5 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__ = 'GPL 3'
 __copyright__ = '2010 Hiroshi Miura <miurahr@linux.com>'
@@ -9,7 +10,7 @@ Unicode code point dictionary.
 Based on Unicode.org Unihan database.
 '''
 
-CODEPOINTS = { 
+CODEPOINTS = {
     'x34':[
         'Qiu ','Tian ','','','Kua ','Wu ','Yin ','','','','','','Si ','','','',
         '','','','','','','Ye ','','','','','','Chou ','','','',
diff --git a/src/calibre/gui2/book_details.py b/src/calibre/gui2/book_details.py
index 031cbac7b4..357ea55c65 100644
--- a/src/calibre/gui2/book_details.py
+++ b/src/calibre/gui2/book_details.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python2
 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
 # License: GPLv3 Copyright: 2010, Kovid Goyal <kovid at kovidgoyal.net>
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 import os
 import re
@@ -59,7 +60,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_type(r'/\*.*?\*/'), u'', val, flags=re.DOTALL)
+        _css = re.sub(unicode_type(r'/\*.*?\*/'), '', val, flags=re.DOTALL)
     return _css
 
 
@@ -127,7 +128,7 @@ def render_html(mi, css, vertical, widget, all_fields=False, render_data_func=No
 
     c = color_to_string(QApplication.palette().color(QPalette.Normal,
                     QPalette.WindowText))
-    templ = u'''\
+    templ = '''\
     <html>
         <head>
         <style type="text/css">
@@ -147,20 +148,20 @@ def render_html(mi, css, vertical, widget, all_fields=False, render_data_func=No
         </body>
     <html>
     '''%(f, fam, c, css)
-    comments = u''
+    comments = ''
     if comment_fields:
         comments = '\n'.join(u'<div>%s</div>' % x for x in comment_fields)
-    right_pane = u'<div id="comments" class="comments">%s</div>'%comments
+    right_pane = '<div id="comments" class="comments">%s</div>'%comments
 
     if vertical:
         ans = templ%(table+right_pane)
     else:
         if gprefs['book_details_narrow_comments_layout'] == 'columns':
-            ans = templ%(u'<table><tr><td valign="top" '
+            ans = templ%('<table><tr><td valign="top" '
                 'style="padding-right:2em; width:40%%">%s</td><td valign="top">%s</td></tr></table>'
                     % (table, right_pane))
         else:
-            ans = templ%(u'<div style="float: left; margin-right: 1em; margin-bottom: 1em; max-width: 40%">{}</div><div>{}</div>'.format(
+            ans = templ%('<div style="float: left; margin-right: 1em; margin-bottom: 1em; max-width: 40%">{}</div><div>{}</div>'.format(
                     table, right_pane))
     return ans
 
@@ -266,7 +267,7 @@ def details_context_menu_event(view, ev, book_info):  # {{{
         else:
             el = r.linkElement()
             data = el.attribute('data-item')
-            author = el.toPlainText() if unicode_type(el.attribute('calibre-data')) == u'authors' else None
+            author = el.toPlainText() if unicode_type(el.attribute('calibre-data')) == 'authors' else None
             if url and not url.startswith('search:'):
                 for a, t in [('copy', _('&Copy link')),
                 ]:
@@ -382,12 +383,12 @@ class CoverView(QWidget):  # {{{
         extrax = canvas_size.width() - width
         if extrax < 0:
             extrax = 0
-        x = int(extrax/2.)
+        x = int(extrax//2)
         height = self.current_pixmap_size.height()
         extray = canvas_size.height() - height
         if extray < 0:
             extray = 0
-        y = int(extray/2.)
+        y = int(extray//2)
         target = QRect(x, y, width, height)
         p = QPainter(self)
         p.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform)
@@ -403,7 +404,7 @@ class CoverView(QWidget):  # {{{
             f = p.font()
             f.setBold(True)
             p.setFont(f)
-            sz = u'\u00a0%d x %d\u00a0'%(self.pixmap.width(), self.pixmap.height())
+            sz = '\u00a0%d x %d\u00a0'%(self.pixmap.width(), self.pixmap.height())
             flags = Qt.AlignBottom|Qt.AlignRight|Qt.TextSingleLine
             szrect = p.boundingRect(sztgt, flags, sz)
             p.fillRect(szrect.adjusted(0, 0, 0, 4), QColor(0, 0, 0, 200))
@@ -710,7 +711,7 @@ class DetailsLayout(QLayout):  # {{{
     def cover_height(self, r):
         if not self._children[0].widget().isVisible():
             return 0
-        mh = min(int(r.height()/2.), int(4/3. * r.width())+1)
+        mh = min(int(r.height()//2), int(4/3 * r.width())+1)
         try:
             ph = self._children[0].widget().pixmap.height()
         except:
@@ -722,7 +723,7 @@ class DetailsLayout(QLayout):  # {{{
     def cover_width(self, r):
         if not self._children[0].widget().isVisible():
             return 0
-        mw = 1 + int(3/4. * r.height())
+        mw = 1 + int(3/4 * r.height())
         try:
             pw = self._children[0].widget().pixmap.width()
         except:
@@ -894,7 +895,7 @@ class BookDetails(QWidget):  # {{{
             self.last_data = {}
         self.book_info.show_data(data)
         self.cover_view.show_data(data)
-        self.current_path = getattr(data, u'path', u'')
+        self.current_path = getattr(data, 'path', '')
         self.update_layout()
 
     def update_layout(self):
diff --git a/src/calibre/gui2/cover_flow.py b/src/calibre/gui2/cover_flow.py
index fcfe465780..17aafcbaf5 100644
--- a/src/calibre/gui2/cover_flow.py
+++ b/src/calibre/gui2/cover_flow.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env  python2
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 __license__   = 'GPL v3'
 __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
 __docformat__ = 'restructuredtext en'
@@ -244,7 +245,7 @@ class CBDialog(QDialog):
         geom = gprefs.get('cover_browser_dialog_geometry', bytearray(''))
         geom = QByteArray(geom)
         if not self.restoreGeometry(geom):
-            h, w = available_height()-60, int(available_width()/1.5)
+            h, w = available_height()-60, available_width()//1.5
             self.resize(w, h)
         self.action_fs_toggle = a = QAction(self)
         self.addAction(a)
@@ -458,7 +459,7 @@ def test():
     app = QApplication([])
     w = QMainWindow()
     cf = CoverFlow()
-    cf.resize(int(available_width()/1.5), available_height()-60)
+    cf.resize(available_width()//1.5, available_height()-60)
     w.resize(cf.size()+QSize(30, 20))
     model = DummyImageList()
     cf.setImages(model)
@@ -479,7 +480,7 @@ if __name__ == '__main__':
     app = QApplication([])
     w = QMainWindow()
     cf = CoverFlow()
-    cf.resize(int(available_width()/1.5), available_height()-60)
+    cf.resize(available_width()//1.5, available_height()-60)
     w.resize(cf.size()+QSize(30, 20))
     path = sys.argv[1]
     model = FileSystemImages(sys.argv[1])
diff --git a/src/calibre/gui2/custom_column_widgets.py b/src/calibre/gui2/custom_column_widgets.py
index 1740271ce0..2a4f87c49b 100644
--- a/src/calibre/gui2/custom_column_widgets.py
+++ b/src/calibre/gui2/custom_column_widgets.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python2
 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
@@ -350,7 +351,7 @@ class Comments(Base):
         self._box = QGroupBox(parent)
         self._box.setTitle('&'+self.col_metadata['name'])
         self._layout = QVBoxLayout()
-        self._tb = CommentsEditor(self._box, toolbar_prefs_name=u'metadata-comments-editor-widget-hidden-toolbars')
+        self._tb = CommentsEditor(self._box, toolbar_prefs_name='metadata-comments-editor-widget-hidden-toolbars')
         self._tb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
         # self._tb.setTabChangesFocus(True)
         self._layout.addWidget(self._tb)
diff --git a/src/calibre/gui2/email.py b/src/calibre/gui2/email.py
index 5040eb133c..8b07edaa3e 100644
--- a/src/calibre/gui2/email.py
+++ b/src/calibre/gui2/email.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python2
 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
-from __future__ import print_function
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
diff --git a/src/calibre/gui2/init.py b/src/calibre/gui2/init.py
index 769781fbcd..9f3fa08602 100644
--- a/src/calibre/gui2/init.py
+++ b/src/calibre/gui2/init.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python2
 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
@@ -314,7 +315,7 @@ class StatusBar(QStatusBar):  # {{{
         if self.library_total != self.total:
             base = _('{0}, {1} total').format(base, self.library_total)
 
-        self.defmsg.setText(u'\xa0%s\xa0\xa0\xa0\xa0[%s]' % (msg, base))
+        self.defmsg.setText('\xa0%s\xa0\xa0\xa0\xa0[%s]' % (msg, base))
         self.clearMessage()
 
     def device_disconnected(self):
@@ -622,7 +623,7 @@ class LayoutMixin(object):  # {{{
                     button = self.search_bar_button
             self.layout_buttons.append(button)
             button.setVisible(False)
-            if isosx and stylename != u'Calibre':
+            if isosx and stylename != 'Calibre':
                 button.setStyleSheet('''
                         QToolButton { background: none; border:none; padding: 0px; }
                         QToolButton:checked { background: rgba(0, 0, 0, 25%); }
diff --git a/src/calibre/gui2/jobs.py b/src/calibre/gui2/jobs.py
index 8f835be45b..5431794ed9 100644
--- a/src/calibre/gui2/jobs.py
+++ b/src/calibre/gui2/jobs.py
@@ -1,4 +1,6 @@
 #!/usr/bin/env  python2
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 __license__   = 'GPL v3'
 __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
 __docformat__ = 'restructuredtext en'
@@ -73,7 +75,7 @@ class JobManager(QAbstractTableModel, AdaptSQP):  # {{{
 
         self.jobs          = []
         self.add_job       = Dispatcher(self._add_job)
-        self.server        = Server(limit=int(config['worker_limit']/2.0),
+        self.server        = Server(limit=config['worker_limit']//2,
                                 enforce_cpu_limit=config['enforce_cpu_limit'])
         self.threaded_server = ThreadedJobServer()
         self.changed_queue = Queue()
@@ -149,7 +151,7 @@ class JobManager(QAbstractTableModel, AdaptSQP):  # {{{
                         return None
                     return human_readable_interval(rtime)
                 if col == 4 and job.start_time is not None:
-                    return (strftime(u'%H:%M -- %d %b', time.localtime(job.start_time)))
+                    return (strftime('%H:%M -- %d %b', time.localtime(job.start_time)))
             if role == Qt.DecorationRole and col == 0:
                 state = job.run_state
                 if state == job.WAITING:
@@ -325,7 +327,7 @@ class JobManager(QAbstractTableModel, AdaptSQP):  # {{{
         jobs = [j for j in jobs if j.duration is None]
         unkillable = [j for j in jobs if not getattr(j, 'killable', True)]
         if unkillable:
-            names = u'\n'.join(as_unicode(j.description) for j in unkillable)
+            names = '\n'.join(as_unicode(j.description) for j in unkillable)
             error_dialog(view, _('Cannot kill job'),
                     _('Some of the jobs cannot be stopped. Click Show details'
                         ' to see the list of unstoppable jobs.'), det_msg=names,
@@ -513,7 +515,7 @@ class JobsButton(QWidget):  # {{{
         self._jobs.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
         self.setCursor(Qt.PointingHandCursor)
         b = _('Click to see list of jobs')
-        self.setToolTip(b + u' [%s]'%self.shortcut)
+        self.setToolTip(b + ' [%s]'%self.shortcut)
         self.action_toggle = QAction(b, parent)
         parent.addAction(self.action_toggle)
         self.action_toggle.triggered.connect(self.toggle)
@@ -576,7 +578,7 @@ class JobsButton(QWidget):  # {{{
         jobs = self._jobs
         src = unicode_type(jobs.text())
         num = self.jobs()
-        text = src.replace(str(num), str(nnum))
+        text = src.replace(unicode_type(num), unicode_type(nnum))
         jobs.setText(text)
         self.start()
         self.tray_tooltip_updated.emit(self.tray_tooltip(nnum))
@@ -585,7 +587,7 @@ class JobsButton(QWidget):  # {{{
         jobs = self._jobs
         src = unicode_type(jobs.text())
         num = self.jobs()
-        text = src.replace(str(num), str(nnum))
+        text = src.replace(unicode_type(num), unicode_type(nnum))
         jobs.setText(text)
         if nnum == 0:
             self.no_more_jobs()
diff --git a/src/calibre/gui2/layout.py b/src/calibre/gui2/layout.py
index f4a27c85af..ddd14b023b 100644
--- a/src/calibre/gui2/layout.py
+++ b/src/calibre/gui2/layout.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python2
 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
@@ -150,7 +151,7 @@ class LocationManager(QObject):  # {{{
         for i, loc in enumerate(('main', 'carda', 'cardb')):
             t = self.tooltips[loc]
             if self.free[i] > -1:
-                t += u'\n\n%s '%human_readable(self.free[i]) + _('available')
+                t += '\n\n%s '%human_readable(self.free[i]) + _('available')
             ac = getattr(self, 'location_'+loc)
             ac.setToolTip(t)
             ac.setWhatsThis(t)
diff --git a/src/calibre/gui2/linux_file_dialogs.py b/src/calibre/gui2/linux_file_dialogs.py
index b324265ff8..78d76b90af 100644
--- a/src/calibre/gui2/linux_file_dialogs.py
+++ b/src/calibre/gui2/linux_file_dialogs.py
@@ -136,7 +136,7 @@ def kde_cmd(window, title, *rest):
         ans += ['--desktopfile', 'calibre-gui']
     winid = get_winid(window)
     if winid is not None:
-        ans += ['--attach', str(int(winid))]
+        ans += ['--attach', unicode_type(int(winid))]
     return ans + list(rest)
 
 
@@ -174,7 +174,7 @@ def kdialog_choose_files(
     filters=[],
     all_files=True,
     select_only_single_file=False,
-    default_dir=u'~'):
+    default_dir='~'):
     initial_dir = get_initial_dir(name, title, default_dir, False)
     args = []
     if not select_only_single_file:
@@ -251,7 +251,7 @@ def zenity_choose_files(
     filters=[],
     all_files=True,
     select_only_single_file=False,
-    default_dir=u'~'):
+    default_dir='~'):
     initial_dir = get_initial_dir(name, title, default_dir, False)
     args = ['--filename=' + os.path.join(initial_dir, '.fgdfg.gdfhjdhf*&^839')]
     args += zenity_filters(filters, all_files)
diff --git a/src/calibre/gui2/shortcuts.py b/src/calibre/gui2/shortcuts.py
index 77944aada5..3e78dd7fd0 100644
--- a/src/calibre/gui2/shortcuts.py
+++ b/src/calibre/gui2/shortcuts.py
@@ -1,6 +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 absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
@@ -203,7 +203,7 @@ class Delegate(QStyledItemDelegate):
 
 class Shortcuts(QAbstractListModel):
 
-    TEMPLATE = u'''
+    TEMPLATE = '''
     <p><b>{0}</b><br>
     {2}: <code>{1}</code></p>
     '''
diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py
index 10bd4106c3..f9cb245a6d 100644
--- a/src/calibre/gui2/ui.py
+++ b/src/calibre/gui2/ui.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python2
 # vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
-from __future__ import print_function, with_statement
+from __future__ import absolute_import, division, print_function, unicode_literals
 
 __license__   = 'GPL v3'
 __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
@@ -535,7 +535,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin,  # {{{
 
     def create_spare_pool(self, *args):
         if self._spare_pool is None:
-            num = min(detect_ncpus(), int(config['worker_limit']/2.0))
+            num = min(detect_ncpus(), config['worker_limit']//2)
             self._spare_pool = Pool(max_workers=num, name='GUIPool')
 
     def spare_pool(self):
@@ -765,7 +765,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin,  # {{{
             font.setBold(True)
             font.setItalic(True)
         self.virtual_library.setFont(font)
-        title = u'{0} - || {1}{2} ||'.format(
+        title = '{0} - || {1}{2} ||'.format(
                 __appname__, self.iactions['Choose Library'].library_name(), restrictions)
         self.setWindowTitle(title)
 
diff --git a/src/calibre/gui2/update.py b/src/calibre/gui2/update.py
index 53fe4135a1..1c3aa90ebf 100644
--- a/src/calibre/gui2/update.py
+++ b/src/calibre/gui2/update.py
@@ -1,8 +1,9 @@
+from __future__ import absolute_import, division, print_function, unicode_literals
+
 __license__   = 'GPL v3'
 __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
 
 import re, ssl, json
-from polyglot.builtins import map, unicode_type
 from threading import Thread, Event
 
 from PyQt5.Qt import (QObject, pyqtSignal, Qt, QUrl, QDialog, QGridLayout,
@@ -18,6 +19,7 @@ from calibre.gui2 import config, dynamic, open_url
 from calibre.gui2.dialogs.plugin_updater import get_plugin_updates_available
 from calibre.utils.serialize import msgpack_dumps, msgpack_loads
 from polyglot.binary import as_hex_unicode, from_hex_bytes
+from polyglot.builtins import map, unicode_type
 
 URL = 'https://code.calibre-ebook.com/latest'
 # URL = 'http://localhost:8000/latest'
@@ -56,7 +58,7 @@ def get_newest_version():
     try:
         version = version.decode('utf-8').strip()
     except UnicodeDecodeError:
-        version = u''
+        version = ''
     ans = NO_CALIBRE_UPDATE
     m = re.match(unicode_type(r'(\d+)\.(\d+).(\d+)$'), version)
     if m is not None:
@@ -211,21 +213,21 @@ class UpdateMixin(object):
         has_plugin_updates = number_of_plugin_updates > 0
         self.plugin_update_found(number_of_plugin_updates)
         version_url = as_hex_unicode(msgpack_dumps((calibre_version, number_of_plugin_updates)))
-        calibre_version = u'.'.join(map(unicode_type, calibre_version))
+        calibre_version = '.'.join(map(unicode_type, calibre_version))
 
         if not has_calibre_update and not has_plugin_updates:
             self.status_bar.update_label.setVisible(False)
             return
         if has_calibre_update:
-            plt = u''
+            plt = ''
             if has_plugin_updates:
                 plt = ngettext(' (one plugin update)', ' ({} plugin updates)', number_of_plugin_updates).format(number_of_plugin_updates)
-            msg = (u'<span style="color:green; font-weight: bold">%s: '
-                    u'<a href="update:%s">%s%s</a></span>') % (
+            msg = ('<span style="color:green; font-weight: bold">%s: '
+                    '<a href="update:%s">%s%s</a></span>') % (
                         _('Update found'), version_url, calibre_version, plt)
         else:
             plt = ngettext('updated plugin', 'updated plugins', number_of_plugin_updates)
-            msg = (u'<a href="update:%s">%d %s</a>')%(version_url, number_of_plugin_updates, plt)
+            msg = ('<a href="update:%s">%d %s</a>')%(version_url, number_of_plugin_updates, plt)
         self.status_bar.update_label.setText(msg)
         self.status_bar.update_label.setVisible(True)