1
0
mirror of https://github.com/gryf/ebook-converter.git synced 2026-04-23 14:41:30 +02:00

Removed iteritems and itervalues, which are redundant

This commit is contained in:
2020-04-21 18:20:08 +02:00
parent 9e076e0af4
commit 3234e4de27
82 changed files with 382 additions and 457 deletions
+10 -12
View File
@@ -9,8 +9,6 @@ from ebook_converter.css_selectors.errors import ExpressionError
from ebook_converter.css_selectors.parser import parse, ascii_lower, Element, FunctionalPseudoElement from ebook_converter.css_selectors.parser import parse, ascii_lower, Element, FunctionalPseudoElement
from ebook_converter.css_selectors.ordered_set import OrderedSet from ebook_converter.css_selectors.ordered_set import OrderedSet
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
@@ -149,7 +147,7 @@ class Select(object):
self.invalidate_caches() self.invalidate_caches()
self.default_lang = default_lang self.default_lang = default_lang
if trace: if trace:
self.dispatch_map = {k:trace_wrapper(v) for k, v in iteritems(self.dispatch_map)} self.dispatch_map = {k:trace_wrapper(v) for k, v in self.dispatch_map.items()}
if ignore_inappropriate_pseudo_classes: if ignore_inappropriate_pseudo_classes:
self.ignore_inappropriate_pseudo_classes = INAPPROPRIATE_PSEUDO_CLASSES self.ignore_inappropriate_pseudo_classes = INAPPROPRIATE_PSEUDO_CLASSES
else: else:
@@ -237,7 +235,7 @@ class Select(object):
def map_attrib_name(x): def map_attrib_name(x):
return ascii_lower(x.rpartition('}')[2]) return ascii_lower(x.rpartition('}')[2])
for tag in self.itertag(): for tag in self.itertag():
for attr, val in iteritems(tag.attrib): for attr, val in tag.attrib.items():
am[map_attrib_name(attr)][val].add(tag) am[map_attrib_name(attr)][val].add(tag)
return self._attrib_map return self._attrib_map
@@ -250,7 +248,7 @@ class Select(object):
def map_attrib_name(x): def map_attrib_name(x):
return ascii_lower(x.rpartition('}')[2]) return ascii_lower(x.rpartition('}')[2])
for tag in self.itertag(): for tag in self.itertag():
for attr, val in iteritems(tag.attrib): for attr, val in tag.attrib.items():
for v in val.split(): for v in val.split():
am[map_attrib_name(attr)][v].add(tag) am[map_attrib_name(attr)][v].add(tag)
return self._attrib_space_map return self._attrib_space_map
@@ -269,7 +267,7 @@ class Select(object):
lang = normalize_language_tag(lang) lang = normalize_language_tag(lang)
for dtag in self.itertag(tag): for dtag in self.itertag(tag):
lmap[dtag] = lang lmap[dtag] = lang
for tag, langs in iteritems(lmap): for tag, langs in lmap.items():
for lang in langs: for lang in langs:
lm[lang].add(tag) lm[lang].add(tag)
return self._lang_map return self._lang_map
@@ -426,7 +424,7 @@ def select_attrib(cache, selector):
def select_exists(cache, attrib, value=None): def select_exists(cache, attrib, value=None):
for elem_set in itervalues(cache.attrib_map[attrib]): for elem_set in cache.attrib_map[attrib].values():
for elem in elem_set: for elem in elem_set:
yield elem yield elem
@@ -444,7 +442,7 @@ def select_includes(cache, attrib, value):
def select_dashmatch(cache, attrib, value): def select_dashmatch(cache, attrib, value):
if value: if value:
for val, elem_set in iteritems(cache.attrib_map[attrib]): for val, elem_set in cache.attrib_map[attrib].items():
if val == value or val.startswith(value + '-'): if val == value or val.startswith(value + '-'):
for elem in elem_set: for elem in elem_set:
yield elem yield elem
@@ -452,7 +450,7 @@ def select_dashmatch(cache, attrib, value):
def select_prefixmatch(cache, attrib, value): def select_prefixmatch(cache, attrib, value):
if value: if value:
for val, elem_set in iteritems(cache.attrib_map[attrib]): for val, elem_set in cache.attrib_map[attrib].items():
if val.startswith(value): if val.startswith(value):
for elem in elem_set: for elem in elem_set:
yield elem yield elem
@@ -460,7 +458,7 @@ def select_prefixmatch(cache, attrib, value):
def select_suffixmatch(cache, attrib, value): def select_suffixmatch(cache, attrib, value):
if value: if value:
for val, elem_set in iteritems(cache.attrib_map[attrib]): for val, elem_set in cache.attrib_map[attrib].items():
if val.endswith(value): if val.endswith(value):
for elem in elem_set: for elem in elem_set:
yield elem yield elem
@@ -468,7 +466,7 @@ def select_suffixmatch(cache, attrib, value):
def select_substringmatch(cache, attrib, value): def select_substringmatch(cache, attrib, value):
if value: if value:
for val, elem_set in iteritems(cache.attrib_map[attrib]): for val, elem_set in cache.attrib_map[attrib].items():
if value in val: if value in val:
for elem in elem_set: for elem in elem_set:
yield elem yield elem
@@ -505,7 +503,7 @@ def select_lang(cache, function):
if lang: if lang:
lang = ascii_lower(lang) lang = ascii_lower(lang)
lp = lang + '-' lp = lang + '-'
for tlang, elem_set in iteritems(cache.lang_map): for tlang, elem_set in cache.lang_map.items():
if tlang == lang or (tlang is not None and tlang.startswith(lp)): if tlang == lang or (tlang is not None and tlang.startswith(lp)):
for elem in elem_set: for elem in elem_set:
yield elem yield elem
+2 -3
View File
@@ -18,7 +18,6 @@ from ebook_converter.utils.config import (make_config_dir, Config, ConfigProxy,
plugin_dir, OptionParser) plugin_dir, OptionParser)
# from ebook_converter.ebooks.metadata.sources.base import Source # from ebook_converter.ebooks.metadata.sources.base import Source
from ebook_converter.constants import DEBUG, numeric_version from ebook_converter.constants import DEBUG, numeric_version
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -347,7 +346,7 @@ def reread_metadata_plugins():
return (1 if plugin.plugin_path is None else 0), plugin.name return (1 if plugin.plugin_path is None else 0), plugin.name
for group in (_metadata_readers, _metadata_writers): for group in (_metadata_readers, _metadata_writers):
for plugins in itervalues(group): for plugins in group.values():
if len(plugins) > 1: if len(plugins) > 1:
plugins.sort(key=key) plugins.sort(key=key)
@@ -640,7 +639,7 @@ def patch_metadata_plugins(possibly_updated_plugins):
# Metadata source plugins dont use initialize() but that # Metadata source plugins dont use initialize() but that
# might change in the future, so be safe. # might change in the future, so be safe.
patches[i].initialize() patches[i].initialize()
for i, pup in iteritems(patches): for i, pup in patches.items():
_initialized_plugins[i] = pup _initialized_plugins[i] = pup
# }}} # }}}
+2 -2
View File
@@ -11,7 +11,7 @@ from ebook_converter import as_unicode
from ebook_converter.constants import ispy3 from ebook_converter.constants import ispy3
from ebook_converter.customize import (Plugin, numeric_version, platform, from ebook_converter.customize import (Plugin, numeric_version, platform,
InvalidPlugin, PluginNotFound) InvalidPlugin, PluginNotFound)
from ebook_converter.polyglot.builtins import itervalues, reload from ebook_converter.polyglot.builtins import reload
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -199,7 +199,7 @@ class PluginLoader(object):
else: else:
m = importlib.import_module(plugin_module) m = importlib.import_module(plugin_module)
plugin_classes = [] plugin_classes = []
for obj in itervalues(m.__dict__): for obj in m.__dict__.values():
if isinstance(obj, type) and issubclass(obj, Plugin) and \ if isinstance(obj, type) and issubclass(obj, Plugin) and \
obj.name != 'Trivial Plugin': obj.name != 'Trivial Plugin':
plugin_classes.append(obj) plugin_classes.append(obj)
+1 -2
View File
@@ -11,7 +11,6 @@ from ebook_converter.customize.conversion import OptionRecommendation
from ebook_converter import patheq from ebook_converter import patheq
from ebook_converter.ebooks.conversion import ConversionUserFeedBack from ebook_converter.ebooks.conversion import ConversionUserFeedBack
from ebook_converter.utils.localization import localize_user_manual_link from ebook_converter.utils.localization import localize_user_manual_link
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL 3' __license__ = 'GPL 3'
@@ -254,7 +253,7 @@ def add_pipeline_options(parser, plumber):
)) ))
for group, (desc, options) in iteritems(groups): for group, (desc, options) in groups.items():
if group: if group:
group = OptionGroup(parser, group, desc) group = OptionGroup(parser, group, desc)
parser.add_option_group(group) parser.add_option_group(group)
@@ -6,7 +6,6 @@ import pkg_resources
from ebook_converter.customize.conversion import InputFormatPlugin, OptionRecommendation from ebook_converter.customize.conversion import InputFormatPlugin, OptionRecommendation
from ebook_converter import guess_type from ebook_converter import guess_type
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -105,7 +104,7 @@ class FB2Input(InputFormatPlugin):
notes = {a.get('href')[1:]: a for a in result.xpath('//a[@link_note and @href]') if a.get('href').startswith('#')} notes = {a.get('href')[1:]: a for a in result.xpath('//a[@link_note and @href]') if a.get('href').startswith('#')}
cites = {a.get('link_cite'): a for a in result.xpath('//a[@link_cite]') if not a.get('href', '')} cites = {a.get('link_cite'): a for a in result.xpath('//a[@link_cite]') if not a.get('href', '')}
all_ids = {x for x in result.xpath('//*/@id')} all_ids = {x for x in result.xpath('//*/@id')}
for cite, a in iteritems(cites): for cite, a in cites.items():
note = notes.get(cite, None) note = notes.get(cite, None)
if note: if note:
c = 1 c = 1
@@ -6,7 +6,6 @@ import glob, os
from ebook_converter.customize.conversion import (OutputFormatPlugin, from ebook_converter.customize.conversion import (OutputFormatPlugin,
OptionRecommendation) OptionRecommendation)
from ebook_converter.ptempfile import TemporaryDirectory from ebook_converter.ptempfile import TemporaryDirectory
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL 3' __license__ = 'GPL 3'
@@ -234,7 +233,7 @@ class PDFOutput(OutputFormatPlugin):
self.process_fonts() self.process_fonts()
if self.opts.pdf_use_document_margins and self.stored_page_margins: if self.opts.pdf_use_document_margins and self.stored_page_margins:
for href, margins in iteritems(self.stored_page_margins): for href, margins in self.stored_page_margins.items():
item = oeb_book.manifest.hrefs.get(href) item = oeb_book.manifest.hrefs.get(href)
if item is not None: if item is not None:
root = item.data root = item.data
@@ -2,7 +2,7 @@ import os, glob, re, textwrap
import pkg_resources import pkg_resources
from ebook_converter.customize.conversion import InputFormatPlugin, OptionRecommendation from ebook_converter.customize.conversion import InputFormatPlugin, OptionRecommendation
from ebook_converter.polyglot.builtins import iteritems, as_bytes from ebook_converter.polyglot.builtins import as_bytes
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
@@ -147,7 +147,7 @@ class RTFInput(InputFormatPlugin):
def convert_images(self, imap): def convert_images(self, imap):
self.default_img = None self.default_img = None
for count, val in iteritems(imap): for count, val in imap.items():
try: try:
imap[count] = self.convert_image(val) imap[count] = self.convert_image(val)
except: except:
@@ -212,7 +212,7 @@ class RTFInput(InputFormatPlugin):
css += '\n'+'\n'.join(font_size_classes) css += '\n'+'\n'.join(font_size_classes)
css += '\n' +'\n'.join(color_classes) css += '\n' +'\n'.join(color_classes)
for cls, val in iteritems(border_styles): for cls, val in border_styles.items():
css += '\n\n.%s {\n%s\n}'%(cls, val) css += '\n\n.%s {\n%s\n}'%(cls, val)
with open(u'styles.css', 'ab') as f: with open(u'styles.css', 'ab') as f:
+5 -6
View File
@@ -2,7 +2,6 @@ import re, random, unicodedata, numbers
from collections import namedtuple from collections import namedtuple
from contextlib import contextmanager from contextlib import contextmanager
from math import ceil, sqrt, cos, sin, atan2 from math import ceil, sqrt, cos, sin, atan2
from ebook_converter.polyglot.builtins import iteritems, itervalues
from itertools import chain from itertools import chain
from PyQt5.Qt import ( from PyQt5.Qt import (
@@ -277,7 +276,7 @@ def preserve_fields(obj, fields):
try: try:
yield yield
finally: finally:
for f, val in iteritems(mem): for f, val in mem.items():
if val is null: if val is null:
delattr(obj, f) delattr(obj, f)
else: else:
@@ -319,10 +318,10 @@ def load_color_themes(prefs):
t = default_color_themes.copy() t = default_color_themes.copy()
t.update(prefs.color_themes) t.update(prefs.color_themes)
disabled = frozenset(prefs.disabled_color_themes) disabled = frozenset(prefs.disabled_color_themes)
ans = [theme_to_colors(v) for k, v in iteritems(t) if k not in disabled] ans = [theme_to_colors(v) for k, v in t.items() if k not in disabled]
if not ans: if not ans:
# Ignore disabled and return only the builtin color themes # Ignore disabled and return only the builtin color themes
ans = [theme_to_colors(v) for k, v in iteritems(default_color_themes)] ans = [theme_to_colors(v) for k, v in default_color_themes.items()]
return ans return ans
@@ -559,14 +558,14 @@ class Blocks(Style):
def all_styles(): def all_styles():
return set( return set(
x.NAME for x in itervalues(globals()) if x.NAME for x in globals().values() if
isinstance(x, type) and issubclass(x, Style) and x is not Style isinstance(x, type) and issubclass(x, Style) and x is not Style
) )
def load_styles(prefs, respect_disabled=True): def load_styles(prefs, respect_disabled=True):
disabled = frozenset(prefs.disabled_styles) if respect_disabled else () disabled = frozenset(prefs.disabled_styles) if respect_disabled else ()
ans = tuple(x for x in itervalues(globals()) if ans = tuple(x for x in globals().values() if
isinstance(x, type) and issubclass(x, Style) and x is not Style and x.NAME not in disabled) isinstance(x, type) and issubclass(x, Style) and x is not Style and x.NAME not in disabled)
if not ans and disabled: if not ans and disabled:
# If all styles have been disabled, ignore the disabling and return all # If all styles have been disabled, ignore the disabling and return all
+3 -4
View File
@@ -1,6 +1,5 @@
import numbers import numbers
from collections import OrderedDict from collections import OrderedDict
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -133,11 +132,11 @@ def read_border(parent, dest, XPath, get, border_edges=border_edges, name='pBdr'
for border in XPath('./w:' + name)(parent): for border in XPath('./w:' + name)(parent):
for edge in border_edges: for edge in border_edges:
for prop, val in iteritems(read_single_border(border, edge, XPath, get)): for prop, val in read_single_border(border, edge, XPath, get).items():
if val is not None: if val is not None:
vals[prop % edge] = val vals[prop % edge] = val
for key, val in iteritems(vals): for key, val in vals.items():
setattr(dest, key, val) setattr(dest, key, val)
@@ -472,4 +471,4 @@ class ParagraphStyle(object):
return False return False
read_funcs = {k[5:]:v for k, v in iteritems(globals()) if k.startswith('read_')} read_funcs = {k[5:]:v for k, v in globals().items() if k.startswith('read_')}
+1 -2
View File
@@ -1,5 +1,4 @@
import os import os
from ebook_converter.polyglot.builtins import itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -143,7 +142,7 @@ def cleanup_markup(log, root, styles, dest_dir, detect_cover, XPath):
current_run = [span] current_run = [span]
# Process dir attributes # Process dir attributes
class_map = dict(itervalues(styles.classes)) class_map = dict(styles.classes.values())
parents = ('p', 'div') + tuple('h%d' % i for i in range(1, 7)) parents = ('p', 'div') + tuple('h%d' % i for i in range(1, 7))
for parent in root.xpath('//*[(%s)]' % ' or '.join('name()="%s"' % t for t in parents)): for parent in root.xpath('//*[(%s)]' % ' or '.join('name()="%s"' % t for t in parents)):
# Ensure that children of rtl parents that are not rtl have an # Ensure that children of rtl parents that are not rtl have an
+2 -2
View File
@@ -1,7 +1,7 @@
import re import re
from ebook_converter.ebooks.docx.index import process_index, polish_index_markup from ebook_converter.ebooks.docx.index import process_index, polish_index_markup
from ebook_converter.polyglot.builtins import iteritems, native_string_type from ebook_converter.polyglot.builtins import native_string_type
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -234,7 +234,7 @@ class Fields(object):
def polish_markup(self, object_map): def polish_markup(self, object_map):
if not self.index_fields: if not self.index_fields:
return return
rmap = {v:k for k, v in iteritems(object_map)} rmap = {v:k for k, v in object_map.items()}
for idx, blocks in self.index_fields: for idx, blocks in self.index_fields:
polish_index_markup(idx, [rmap[b] for b in blocks]) polish_index_markup(idx, [rmap[b] for b in blocks])
+1 -2
View File
@@ -6,7 +6,6 @@ from ebook_converter.utils.filenames import ascii_filename
from ebook_converter.utils.fonts.scanner import font_scanner, NoFonts from ebook_converter.utils.fonts.scanner import font_scanner, NoFonts
from ebook_converter.utils.fonts.utils import panose_to_css_generic_family, is_truetype_font from ebook_converter.utils.fonts.utils import panose_to_css_generic_family, is_truetype_font
from ebook_converter.utils.icu import ord_string from ebook_converter.utils.icu import ord_string
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -168,7 +167,7 @@ class Fonts(object):
d['font-weight'] = 'bold' d['font-weight'] = 'bold'
if 'Italic' in variant: if 'Italic' in variant:
d['font-style'] = 'italic' d['font-style'] = 'italic'
d = ['%s: %s' % (k, v) for k, v in iteritems(d)] d = ['%s: %s' % (k, v) for k, v in d.items()]
d = ';\n\t'.join(d) d = ';\n\t'.join(d)
defs.append('@font-face {\n\t%s\n}\n' % d) defs.append('@font-face {\n\t%s\n}\n' % d)
return '\n'.join(defs) return '\n'.join(defs)
+1 -2
View File
@@ -1,5 +1,4 @@
from collections import OrderedDict from collections import OrderedDict
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -54,7 +53,7 @@ class Footnotes(object):
return None, None return None, None
def __iter__(self): def __iter__(self):
for anchor, (counter, note) in iteritems(self.notes): for anchor, (counter, note) in self.notes.items():
yield anchor, counter, note yield anchor, counter, note
@property @property
+5 -6
View File
@@ -7,7 +7,6 @@ from ebook_converter.ebooks.docx.names import barename
from ebook_converter.utils.filenames import ascii_filename from ebook_converter.utils.filenames import ascii_filename
from ebook_converter.utils.img import resize_to_fit, image_to_data from ebook_converter.utils.img import resize_to_fit, image_to_data
from ebook_converter.utils.imghdr import what from ebook_converter.utils.imghdr import what
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -63,7 +62,7 @@ def get_image_properties(parent, XPath, get):
def get_image_margins(elem): def get_image_margins(elem):
ans = {} ans = {}
for w, css in iteritems({'L':'left', 'T':'top', 'R':'right', 'B':'bottom'}): for w, css in {'L':'left', 'T':'top', 'R':'right', 'B':'bottom'}.items():
val = elem.get('dist%s' % w, None) val = elem.get('dist%s' % w, None)
if val is not None: if val is not None:
try: try:
@@ -154,7 +153,7 @@ class Images(object):
return raw, base return raw, base
def unique_name(self, base): def unique_name(self, base):
exists = frozenset(itervalues(self.used)) exists = frozenset(self.used.values())
c = 1 c = 1
name = base name = base
while name in exists: while name in exists:
@@ -239,7 +238,7 @@ class Images(object):
ans = self.pic_to_img(pic, alt, inline, title) ans = self.pic_to_img(pic, alt, inline, title)
if ans is not None: if ans is not None:
if style: if style:
ans.set('style', '; '.join('%s: %s' % (k, v) for k, v in iteritems(style))) ans.set('style', '; '.join('%s: %s' % (k, v) for k, v in style.items()))
yield ans yield ans
# Now process the floats # Now process the floats
@@ -250,7 +249,7 @@ class Images(object):
ans = self.pic_to_img(pic, alt, anchor, title) ans = self.pic_to_img(pic, alt, anchor, title)
if ans is not None: if ans is not None:
if style: if style:
ans.set('style', '; '.join('%s: %s' % (k, v) for k, v in iteritems(style))) ans.set('style', '; '.join('%s: %s' % (k, v) for k, v in style.items()))
yield ans yield ans
def pict_to_html(self, pict, page): def pict_to_html(self, pict, page):
@@ -272,7 +271,7 @@ class Images(object):
style['margin-left'] = '0' if align == 'left' else 'auto' style['margin-left'] = '0' if align == 'left' else 'auto'
style['margin-right'] = 'auto' if align == 'left' else '0' style['margin-right'] = 'auto' if align == 'left' else '0'
if style: if style:
hr.set('style', '; '.join(('%s:%s' % (k, v) for k, v in iteritems(style)))) hr.set('style', '; '.join(('%s:%s' % (k, v) for k, v in style.items())))
yield hr yield hr
for imagedata in XPath('descendant::v:imagedata[@r:id]')(pict): for imagedata in XPath('descendant::v:imagedata[@r:id]')(pict):
+1 -2
View File
@@ -3,7 +3,6 @@ from operator import itemgetter
from lxml import etree from lxml import etree
from ebook_converter.utils.icu import partition_by_first_letter, sort_key from ebook_converter.utils.icu import partition_by_first_letter, sort_key
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -99,7 +98,7 @@ def process_index(field, index, xe_fields, log, XPath, expand):
if heading_text is not None: if heading_text is not None:
groups = partition_by_first_letter(xe_fields, key=itemgetter('text')) groups = partition_by_first_letter(xe_fields, key=itemgetter('text'))
items = [] items = []
for key, fields in iteritems(groups): for key, fields in groups.items():
items.append(key), items.extend(fields) items.append(key), items.extend(fields)
if styles: if styles:
heading_style = styles[0] heading_style = styles[0]
+3 -4
View File
@@ -3,7 +3,6 @@ import re
from lxml.etree import XPath as X from lxml.etree import XPath as X
from ebook_converter.utils.filenames import ascii_text from ebook_converter.utils.filenames import ascii_text
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -29,7 +28,7 @@ TRANSITIONAL_NAMES = {
STRICT_NAMES = { STRICT_NAMES = {
k:v.replace('http://schemas.openxmlformats.org/officeDocument/2006', 'http://purl.oclc.org/ooxml/officeDocument') k:v.replace('http://schemas.openxmlformats.org/officeDocument/2006', 'http://purl.oclc.org/ooxml/officeDocument')
for k, v in iteritems(TRANSITIONAL_NAMES) for k, v in TRANSITIONAL_NAMES.items()
} }
TRANSITIONAL_NAMESPACES = { TRANSITIONAL_NAMESPACES = {
@@ -69,7 +68,7 @@ STRICT_NAMESPACES = {
'http://schemas.openxmlformats.org/officeDocument/2006', 'http://purl.oclc.org/ooxml/officeDocument').replace( 'http://schemas.openxmlformats.org/officeDocument/2006', 'http://purl.oclc.org/ooxml/officeDocument').replace(
'http://schemas.openxmlformats.org/wordprocessingml/2006', 'http://purl.oclc.org/ooxml/wordprocessingml').replace( 'http://schemas.openxmlformats.org/wordprocessingml/2006', 'http://purl.oclc.org/ooxml/wordprocessingml').replace(
'http://schemas.openxmlformats.org/drawingml/2006', 'http://purl.oclc.org/ooxml/drawingml') 'http://schemas.openxmlformats.org/drawingml/2006', 'http://purl.oclc.org/ooxml/drawingml')
for k, v in iteritems(TRANSITIONAL_NAMESPACES) for k, v in TRANSITIONAL_NAMESPACES.items()
} }
# }}} # }}}
@@ -135,7 +134,7 @@ class DOCXNamespace(object):
return self.XPath('|'.join('descendant::%s' % a for a in args))(elem) return self.XPath('|'.join('descendant::%s' % a for a in args))(elem)
def makeelement(self, root, tag, append=True, **attrs): def makeelement(self, root, tag, append=True, **attrs):
ans = root.makeelement(self.expand(tag), **{self.expand(k, sep='_'):v for k, v in iteritems(attrs)}) ans = root.makeelement(self.expand(tag), **{self.expand(k, sep='_'):v for k, v in attrs.items()})
if append: if append:
root.append(ans) root.append(ans)
return ans return ans
+7 -8
View File
@@ -7,7 +7,6 @@ from lxml.html.builder import OL, UL, SPAN
from ebook_converter.ebooks.docx.block_styles import ParagraphStyle from ebook_converter.ebooks.docx.block_styles import ParagraphStyle
from ebook_converter.ebooks.docx.char_styles import RunStyle, inherit from ebook_converter.ebooks.docx.char_styles import RunStyle, inherit
from ebook_converter.ebooks.metadata import roman from ebook_converter.ebooks.metadata import roman
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -166,7 +165,7 @@ class NumberingDefinition(object):
def copy(self): def copy(self):
ans = NumberingDefinition(self.namespace, an_id=self.abstract_numbering_definition_id) ans = NumberingDefinition(self.namespace, an_id=self.abstract_numbering_definition_id)
for l, lvl in iteritems(self.levels): for l, lvl in self.levels.items():
ans.levels[l] = lvl.copy() ans.levels[l] = lvl.copy()
return ans return ans
@@ -222,7 +221,7 @@ class Numbering(object):
if alvl is None: if alvl is None:
alvl = Level(self.namespace) alvl = Level(self.namespace)
alvl.read_from_xml(lvl, override=True) alvl.read_from_xml(lvl, override=True)
for ilvl, so in iteritems(start_overrides): for ilvl, so in start_overrides.items():
try: try:
nd.levels[ilvl].start = start_override nd.levels[ilvl].start = start_override
except KeyError: except KeyError:
@@ -242,22 +241,22 @@ class Numbering(object):
self.instances[num_id] = create_instance(n, d) self.instances[num_id] = create_instance(n, d)
numbering_links = styles.numbering_style_links numbering_links = styles.numbering_style_links
for an_id, style_link in iteritems(lazy_load): for an_id, style_link in lazy_load.items():
num_id = numbering_links[style_link] num_id = numbering_links[style_link]
self.definitions[an_id] = self.instances[num_id].copy() self.definitions[an_id] = self.instances[num_id].copy()
for num_id, (an_id, n) in iteritems(next_pass): for num_id, (an_id, n) in next_pass.items():
d = self.definitions.get(an_id, None) d = self.definitions.get(an_id, None)
if d is not None: if d is not None:
self.instances[num_id] = create_instance(n, d) self.instances[num_id] = create_instance(n, d)
for num_id, d in iteritems(self.instances): for num_id, d in self.instances.items():
self.starts[num_id] = {lvl:d.levels[lvl].start for lvl in d.levels} self.starts[num_id] = {lvl:d.levels[lvl].start for lvl in d.levels}
def get_pstyle(self, num_id, style_id): def get_pstyle(self, num_id, style_id):
d = self.instances.get(num_id, None) d = self.instances.get(num_id, None)
if d is not None: if d is not None:
for ilvl, lvl in iteritems(d.levels): for ilvl, lvl in d.levels.items():
if lvl.para_link == style_id: if lvl.para_link == style_id:
return ilvl return ilvl
@@ -269,7 +268,7 @@ class Numbering(object):
def update_counter(self, counter, levelnum, levels): def update_counter(self, counter, levelnum, levels):
counter[levelnum] += 1 counter[levelnum] += 1
for ilvl, lvl in iteritems(levels): for ilvl, lvl in levels.items():
restart = lvl.restart restart = lvl.restart
if (restart is None and ilvl == levelnum + 1) or restart == levelnum + 1: if (restart is None and ilvl == levelnum + 1) or restart == levelnum + 1:
counter[ilvl] = lvl.start counter[ilvl] = lvl.start
+8 -9
View File
@@ -4,7 +4,6 @@ from collections import OrderedDict, Counter
from ebook_converter.ebooks.docx.block_styles import ParagraphStyle, inherit, twips from ebook_converter.ebooks.docx.block_styles import ParagraphStyle, inherit, twips
from ebook_converter.ebooks.docx.char_styles import RunStyle from ebook_converter.ebooks.docx.char_styles import RunStyle
from ebook_converter.ebooks.docx.tables import TableStyle from ebook_converter.ebooks.docx.tables import TableStyle
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -121,7 +120,7 @@ class Styles(object):
self.default_paragraph_style = self.default_character_style = None self.default_paragraph_style = self.default_character_style = None
def __iter__(self): def __iter__(self):
for s in itervalues(self.id_map): for s in self.id_map.values():
yield s yield s
def __getitem__(self, key): def __getitem__(self, key):
@@ -340,7 +339,7 @@ class Styles(object):
setattr(s, prop, inherit) setattr(s, prop, inherit)
setattr(block_style, prop, next(iter(vals))) setattr(block_style, prop, next(iter(vals)))
for p, runs in iteritems(layers): for p, runs in layers.items():
has_links = '1' in {r.get('is-link', None) for r in runs} has_links = '1' in {r.get('is-link', None) for r in runs}
char_styles = [self.resolve_run(r) for r in runs] char_styles = [self.resolve_run(r) for r in runs]
block_style = self.resolve_paragraph(p) block_style = self.resolve_paragraph(p)
@@ -420,7 +419,7 @@ class Styles(object):
ps.pageBreakBefore = True ps.pageBreakBefore = True
def register(self, css, prefix): def register(self, css, prefix):
h = hash(frozenset(iteritems(css))) h = hash(frozenset(css.items()))
ans, _ = self.classes.get(h, (None, None)) ans, _ = self.classes.get(h, (None, None))
if ans is None: if ans is None:
self.counter[prefix] += 1 self.counter[prefix] += 1
@@ -429,17 +428,17 @@ class Styles(object):
return ans return ans
def generate_classes(self): def generate_classes(self):
for bs in itervalues(self.para_cache): for bs in self.para_cache.values():
css = bs.css css = bs.css
if css: if css:
self.register(css, 'block') self.register(css, 'block')
for bs in itervalues(self.run_cache): for bs in self.run_cache.values():
css = bs.css css = bs.css
if css: if css:
self.register(css, 'text') self.register(css, 'text')
def class_name(self, css): def class_name(self, css):
h = hash(frozenset(iteritems(css))) h = hash(frozenset(css.items()))
return self.classes.get(h, (None, None))[0] return self.classes.get(h, (None, None))[0]
def generate_css(self, dest_dir, docx, notes_nopb, nosupsub): def generate_css(self, dest_dir, docx, notes_nopb, nosupsub):
@@ -494,8 +493,8 @@ class Styles(object):
prefix = ef + '\n' + prefix prefix = ef + '\n' + prefix
ans = [] ans = []
for (cls, css) in sorted(itervalues(self.classes), key=lambda x:x[0]): for (cls, css) in sorted(self.classes.values(), key=lambda x:x[0]):
b = ('\t%s: %s;' % (k, v) for k, v in iteritems(css)) b = ('\t%s: %s;' % (k, v) for k, v in css.items())
b = '\n'.join(b) b = '\n'.join(b)
ans.append('.%s {\n%s\n}\n' % (cls, b.rstrip(';'))) ans.append('.%s {\n%s\n}\n' % (cls, b.rstrip(';')))
return prefix + '\n' + '\n'.join(ans) return prefix + '\n' + '\n'.join(ans)
+4 -5
View File
@@ -2,7 +2,6 @@ from lxml.html.builder import TABLE, TR, TD
from ebook_converter.ebooks.docx.block_styles import inherit, read_shd as rs, read_border, binary_property, border_props, ParagraphStyle, border_to_css from ebook_converter.ebooks.docx.block_styles import inherit, read_shd as rs, read_border, binary_property, border_props, ParagraphStyle, border_to_css
from ebook_converter.ebooks.docx.char_styles import RunStyle from ebook_converter.ebooks.docx.char_styles import RunStyle
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -82,7 +81,7 @@ def read_spacing(parent, dest, XPath, get):
def read_float(parent, dest, XPath, get): def read_float(parent, dest, XPath, get):
ans = inherit ans = inherit
for x in XPath('./w:tblpPr')(parent): for x in XPath('./w:tblpPr')(parent):
ans = {k.rpartition('}')[-1]: v for k, v in iteritems(x.attrib)} ans = {k.rpartition('}')[-1]: v for k, v in x.attrib.items()}
setattr(dest, 'float', ans) setattr(dest, 'float', ans)
@@ -614,7 +613,7 @@ class Table(object):
def __iter__(self): def __iter__(self):
for p in self.paragraphs: for p in self.paragraphs:
yield p yield p
for t in itervalues(self.sub_tables): for t in self.sub_tables.values():
for p in t: for p in t:
yield p yield p
@@ -661,7 +660,7 @@ class Table(object):
table_style = self.table_style.css table_style = self.table_style.css
if table_style: if table_style:
table.set('class', self.styles.register(table_style, 'table')) table.set('class', self.styles.register(table_style, 'table'))
for elem, style in iteritems(style_map): for elem, style in style_map.items():
css = style.css css = style.css
if css: if css:
elem.set('class', self.styles.register(css, elem.tag)) elem.set('class', self.styles.register(css, elem.tag))
@@ -682,7 +681,7 @@ class Tables(object):
self.sub_tables |= set(self.tables[-1].sub_tables) self.sub_tables |= set(self.tables[-1].sub_tables)
def apply_markup(self, object_map, page_map): def apply_markup(self, object_map, page_map):
rmap = {v:k for k, v in iteritems(object_map)} rmap = {v:k for k, v in object_map.items()}
for table in self.tables: for table in self.tables:
table.apply_markup(rmap, page_map[table.tbl]) table.apply_markup(rmap, page_map[table.tbl])
+14 -15
View File
@@ -21,7 +21,6 @@ from ebook_converter.ebooks.docx.fields import Fields
from ebook_converter.ebooks.docx.settings import Settings from ebook_converter.ebooks.docx.settings import Settings
from ebook_converter.ebooks.metadata.opf2 import OPFCreator from ebook_converter.ebooks.metadata.opf2 import OPFCreator
from ebook_converter.utils.localization import canonicalize_lang, lang_as_iso639_1 from ebook_converter.utils.localization import canonicalize_lang, lang_as_iso639_1
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -119,7 +118,7 @@ class Convert(object):
self.read_page_properties(doc) self.read_page_properties(doc)
self.current_rels = relationships_by_id self.current_rels = relationships_by_id
for wp, page_properties in iteritems(self.page_map): for wp, page_properties in self.page_map.items():
self.current_page = page_properties self.current_page = page_properties
if wp.tag.endswith('}p'): if wp.tag.endswith('}p'):
p = self.convert_p(wp) p = self.convert_p(wp)
@@ -159,7 +158,7 @@ class Convert(object):
self.styles.apply_contextual_spacing(paras) self.styles.apply_contextual_spacing(paras)
self.mark_block_runs(paras) self.mark_block_runs(paras)
for p, wp in iteritems(self.object_map): for p, wp in self.object_map.items():
if len(p) > 0 and not p.text and len(p[0]) > 0 and not p[0].text and p[0][0].get('class', None) == 'tab': if len(p) > 0 and not p.text and len(p[0]) > 0 and not p[0].text and p[0][0].get('class', None) == 'tab':
# Paragraph uses tabs for indentation, convert to text-indent # Paragraph uses tabs for indentation, convert to text-indent
parent = p[0] parent = p[0]
@@ -189,7 +188,7 @@ class Convert(object):
self.tables.apply_markup(self.object_map, self.page_map) self.tables.apply_markup(self.object_map, self.page_map)
numbered = [] numbered = []
for html_obj, obj in iteritems(self.object_map): for html_obj, obj in self.object_map.items():
raw = obj.get('calibre_num_id', None) raw = obj.get('calibre_num_id', None)
if raw is not None: if raw is not None:
lvl, num_id = raw.partition(':')[0::2] lvl, num_id = raw.partition(':')[0::2]
@@ -209,7 +208,7 @@ class Convert(object):
self.log.debug('Converting styles to CSS') self.log.debug('Converting styles to CSS')
self.styles.generate_classes() self.styles.generate_classes()
for html_obj, obj in iteritems(self.object_map): for html_obj, obj in self.object_map.items():
style = self.styles.resolve(obj) style = self.styles.resolve(obj)
if style is not None: if style is not None:
css = style.css css = style.css
@@ -217,7 +216,7 @@ class Convert(object):
cls = self.styles.class_name(css) cls = self.styles.class_name(css)
if cls: if cls:
html_obj.set('class', cls) html_obj.set('class', cls)
for html_obj, css in iteritems(self.framed_map): for html_obj, css in self.framed_map.items():
cls = self.styles.class_name(css) cls = self.styles.class_name(css)
if cls: if cls:
html_obj.set('class', cls) html_obj.set('class', cls)
@@ -404,13 +403,13 @@ class Convert(object):
doc_anchors = frozenset(self.namespace.XPath('./w:body/w:bookmarkStart[@w:name]')(doc)) doc_anchors = frozenset(self.namespace.XPath('./w:body/w:bookmarkStart[@w:name]')(doc))
if doc_anchors: if doc_anchors:
current_bm = set() current_bm = set()
rmap = {v:k for k, v in iteritems(self.object_map)} rmap = {v:k for k, v in self.object_map.items()}
for p in self.namespace.descendants(doc, 'w:p', 'w:bookmarkStart[@w:name]'): for p in self.namespace.descendants(doc, 'w:p', 'w:bookmarkStart[@w:name]'):
if p.tag.endswith('}p'): if p.tag.endswith('}p'):
if current_bm and p in rmap: if current_bm and p in rmap:
para = rmap[p] para = rmap[p]
if 'id' not in para.attrib: if 'id' not in para.attrib:
para.set('id', generate_anchor(next(iter(current_bm)), frozenset(itervalues(self.anchor_map)))) para.set('id', generate_anchor(next(iter(current_bm)), frozenset(self.anchor_map.values())))
for name in current_bm: for name in current_bm:
self.anchor_map[name] = para.get('id') self.anchor_map[name] = para.get('id')
current_bm = set() current_bm = set()
@@ -466,10 +465,10 @@ class Convert(object):
# _GoBack is a special bookmark inserted by Word 2010 for # _GoBack is a special bookmark inserted by Word 2010 for
# the return to previous edit feature, we ignore it # the return to previous edit feature, we ignore it
old_anchor = current_anchor old_anchor = current_anchor
self.anchor_map[anchor] = current_anchor = generate_anchor(anchor, frozenset(itervalues(self.anchor_map))) self.anchor_map[anchor] = current_anchor = generate_anchor(anchor, frozenset(self.anchor_map.values()))
if old_anchor is not None: if old_anchor is not None:
# The previous anchor was not applied to any element # The previous anchor was not applied to any element
for a, t in tuple(iteritems(self.anchor_map)): for a, t in tuple(self.anchor_map.items()):
if t == old_anchor: if t == old_anchor:
self.anchor_map[a] = current_anchor self.anchor_map[a] = current_anchor
elif x.tag.endswith('}hyperlink'): elif x.tag.endswith('}hyperlink'):
@@ -477,11 +476,11 @@ class Convert(object):
elif x.tag.endswith('}instrText') and x.text and x.text.strip().startswith('TOC '): elif x.tag.endswith('}instrText') and x.text and x.text.strip().startswith('TOC '):
old_anchor = current_anchor old_anchor = current_anchor
anchor = str(uuid.uuid4()) anchor = str(uuid.uuid4())
self.anchor_map[anchor] = current_anchor = generate_anchor('toc', frozenset(itervalues(self.anchor_map))) self.anchor_map[anchor] = current_anchor = generate_anchor('toc', frozenset(self.anchor_map.values()))
self.toc_anchor = current_anchor self.toc_anchor = current_anchor
if old_anchor is not None: if old_anchor is not None:
# The previous anchor was not applied to any element # The previous anchor was not applied to any element
for a, t in tuple(iteritems(self.anchor_map)): for a, t in tuple(self.anchor_map.items()):
if t == old_anchor: if t == old_anchor:
self.anchor_map[a] = current_anchor self.anchor_map[a] = current_anchor
if current_anchor is not None: if current_anchor is not None:
@@ -557,7 +556,7 @@ class Convert(object):
def resolve_links(self): def resolve_links(self):
self.resolved_link_map = {} self.resolved_link_map = {}
for hyperlink, spans in iteritems(self.link_map): for hyperlink, spans in self.link_map.items():
relationships_by_id = self.link_source_map[hyperlink] relationships_by_id = self.link_source_map[hyperlink]
span = spans[0] span = spans[0]
if len(spans) > 1: if len(spans) > 1:
@@ -583,7 +582,7 @@ class Convert(object):
# hrefs that point nowhere give epubcheck a hernia. The element # hrefs that point nowhere give epubcheck a hernia. The element
# should be styled explicitly by Word anyway. # should be styled explicitly by Word anyway.
# span.set('href', '#') # span.set('href', '#')
rmap = {v:k for k, v in iteritems(self.object_map)} rmap = {v:k for k, v in self.object_map.items()}
for hyperlink, runs in self.fields.hyperlink_fields: for hyperlink, runs in self.fields.hyperlink_fields:
spans = [rmap[r] for r in runs if r in rmap] spans = [rmap[r] for r in runs if r in rmap]
if not spans: if not spans:
@@ -743,7 +742,7 @@ class Convert(object):
if not self.block_runs: if not self.block_runs:
return return
rmap = {v:k for k, v in iteritems(self.object_map)} rmap = {v:k for k, v in self.object_map.items()}
for border_style, blocks in self.block_runs: for border_style, blocks in self.block_runs:
paras = tuple(rmap[p] for p in blocks) paras = tuple(rmap[p] for p in blocks)
for p in paras: for p in paras:
+1 -2
View File
@@ -5,7 +5,6 @@ from lxml.etree import tostring
from ebook_converter.ebooks.metadata.toc import TOC from ebook_converter.ebooks.metadata.toc import TOC
from ebook_converter.ebooks.oeb.polish.toc import elem_to_toc_text from ebook_converter.ebooks.oeb.polish.toc import elem_to_toc_text
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -21,7 +20,7 @@ def from_headings(body, log, namespace, num_levels=3):
level_item_map = {i:frozenset( level_item_map = {i:frozenset(
x for x in all_heading_nodes if int(x.get('data-heading-level')) == i) x for x in all_heading_nodes if int(x.get('data-heading-level')) == i)
for i in range(1, num_levels+1)} for i in range(1, num_levels+1)}
item_level_map = {e:i for i, elems in iteritems(level_item_map) for e in elems} item_level_map = {e:i for i, elems in level_item_map.items() for e in elems}
idcount = count() idcount = count()
+12 -15
View File
@@ -11,7 +11,7 @@ from ebook_converter.ebooks.pdf.render.common import PAPER_SIZES
from ebook_converter.utils.date import utcnow from ebook_converter.utils.date import utcnow
from ebook_converter.utils.localization import canonicalize_lang, lang_as_iso639_1 from ebook_converter.utils.localization import canonicalize_lang, lang_as_iso639_1
from ebook_converter.utils.zipfile import ZipFile from ebook_converter.utils.zipfile import ZipFile
from ebook_converter.polyglot.builtins import iteritems, native_string_type from ebook_converter.polyglot.builtins import native_string_type
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -52,7 +52,7 @@ def create_skeleton(opts, namespaces=None):
def w(x): def w(x):
return '{%s}%s' % (namespaces['w'], x) return '{%s}%s' % (namespaces['w'], x)
dn = {k:v for k, v in iteritems(namespaces) if k in {'w', 'r', 'm', 've', 'o', 'wp', 'w10', 'wne', 'a', 'pic'}} dn = {k:v for k, v in namespaces.items() if k in {'w', 'r', 'm', 've', 'o', 'wp', 'w10', 'wne', 'a', 'pic'}}
E = ElementMaker(namespace=dn['w'], nsmap=dn) E = ElementMaker(namespace=dn['w'], nsmap=dn)
doc = E.document() doc = E.document()
body = E.body() body = E.body()
@@ -70,7 +70,7 @@ def create_skeleton(opts, namespaces=None):
E.docGrid(**{w('linePitch'):"360"}), E.docGrid(**{w('linePitch'):"360"}),
)) ))
dn = {k:v for k, v in iteritems(namespaces) if k in tuple('wra') + ('wp',)} dn = {k:v for k, v in namespaces.items() if k in tuple('wra') + ('wp',)}
E = ElementMaker(namespace=dn['w'], nsmap=dn) E = ElementMaker(namespace=dn['w'], nsmap=dn)
styles = E.styles( styles = E.styles(
E.docDefaults( E.docDefaults(
@@ -117,12 +117,11 @@ class DocumentRelationships(object):
def __init__(self, namespace): def __init__(self, namespace):
self.rmap = {} self.rmap = {}
self.namespace = namespace self.namespace = namespace
for typ, target in iteritems({ for typ, target in {namespace.names['STYLES']: 'styles.xml',
namespace.names['STYLES']: 'styles.xml',
namespace.names['NUMBERING']: 'numbering.xml', namespace.names['NUMBERING']: 'numbering.xml',
namespace.names['WEB_SETTINGS']: 'webSettings.xml', namespace.names['WEB_SETTINGS']: 'webSettings.xml',
namespace.names['FONTS']: 'fontTable.xml', namespace.names['FONTS']: 'fontTable.xml',
}): }.items():
self.add_relationship(target, typ) self.add_relationship(target, typ)
def get_relationship_id(self, target, rtype, target_mode=None): def get_relationship_id(self, target, rtype, target_mode=None):
@@ -142,7 +141,7 @@ class DocumentRelationships(object):
namespaces = self.namespace.namespaces namespaces = self.namespace.namespaces
E = ElementMaker(namespace=namespaces['pr'], nsmap={None:namespaces['pr']}) E = ElementMaker(namespace=namespaces['pr'], nsmap={None:namespaces['pr']})
relationships = E.Relationships() relationships = E.Relationships()
for (target, rtype, target_mode), rid in iteritems(self.rmap): for (target, rtype, target_mode), rid in self.rmap.items():
r = E.Relationship(Id=rid, Type=rtype, Target=target) r = E.Relationship(Id=rid, Type=rtype, Target=target)
if target_mode is not None: if target_mode is not None:
r.set('TargetMode', target_mode) r.set('TargetMode', target_mode)
@@ -169,7 +168,7 @@ class DOCX(object):
def contenttypes(self): def contenttypes(self):
E = ElementMaker(namespace=self.namespace.namespaces['ct'], nsmap={None:self.namespace.namespaces['ct']}) E = ElementMaker(namespace=self.namespace.namespaces['ct'], nsmap={None:self.namespace.namespaces['ct']})
types = E.Types() types = E.Types()
for partname, mt in iteritems({ for partname, mt in {
"/word/footnotes.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml", "/word/footnotes.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml",
"/word/document.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml", "/word/document.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
"/word/numbering.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml", "/word/numbering.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
@@ -181,15 +180,13 @@ class DOCX(object):
"/word/webSettings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml", "/word/webSettings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml",
"/docProps/core.xml": "application/vnd.openxmlformats-package.core-properties+xml", "/docProps/core.xml": "application/vnd.openxmlformats-package.core-properties+xml",
"/docProps/app.xml": "application/vnd.openxmlformats-officedocument.extended-properties+xml", "/docProps/app.xml": "application/vnd.openxmlformats-officedocument.extended-properties+xml",
}): }.items():
types.append(E.Override(PartName=partname, ContentType=mt)) types.append(E.Override(PartName=partname, ContentType=mt))
added = {'png', 'gif', 'jpeg', 'jpg', 'svg', 'xml'} added = {'png', 'gif', 'jpeg', 'jpg', 'svg', 'xml'}
for ext in added: for ext in added:
types.append(E.Default(Extension=ext, ContentType=guess_type('a.'+ext)[0])) types.append(E.Default(Extension=ext, ContentType=guess_type('a.'+ext)[0]))
for ext, mt in iteritems({ for ext, mt in {"rels": "application/vnd.openxmlformats-package.relationships+xml",
"rels": "application/vnd.openxmlformats-package.relationships+xml", "odttf": "application/vnd.openxmlformats-officedocument.obfuscatedFont"}.items():
"odttf": "application/vnd.openxmlformats-officedocument.obfuscatedFont",
}):
added.add(ext) added.add(ext)
types.append(E.Default(Extension=ext, ContentType=mt)) types.append(E.Default(Extension=ext, ContentType=mt))
for fname in self.images: for fname in self.images:
@@ -267,9 +264,9 @@ class DOCX(object):
zf.writestr('word/fontTable.xml', xml2str(self.font_table)) zf.writestr('word/fontTable.xml', xml2str(self.font_table))
zf.writestr('word/_rels/document.xml.rels', self.document_relationships.serialize()) zf.writestr('word/_rels/document.xml.rels', self.document_relationships.serialize())
zf.writestr('word/_rels/fontTable.xml.rels', xml2str(self.embedded_fonts)) zf.writestr('word/_rels/fontTable.xml.rels', xml2str(self.embedded_fonts))
for fname, data_getter in iteritems(self.images): for fname, data_getter in self.images.items():
zf.writestr(fname, data_getter()) zf.writestr(fname, data_getter())
for fname, data in iteritems(self.fonts): for fname, data in self.fonts.items():
zf.writestr(fname, data) zf.writestr(fname, data)
+2 -3
View File
@@ -2,7 +2,6 @@ import os
import posixpath import posixpath
from collections import namedtuple from collections import namedtuple
from functools import partial from functools import partial
from ebook_converter.polyglot.builtins import iteritems, itervalues
from lxml import etree from lxml import etree
@@ -127,7 +126,7 @@ class ImagesManager(object):
if fake_margins: if fake_margins:
# DOCX does not support setting margins for inline images, so we # DOCX does not support setting margins for inline images, so we
# fake it by using effect extents to simulate margins # fake it by using effect extents to simulate margins
makeelement(parent, 'wp:effectExtent', **{k[-1].lower():v for k, v in iteritems(get_image_margins(style))}) makeelement(parent, 'wp:effectExtent', **{k[-1].lower():v for k, v in get_image_margins(style).items()})
else: else:
makeelement(parent, 'wp:effectExtent', l='0', r='0', t='0', b='0') makeelement(parent, 'wp:effectExtent', l='0', r='0', t='0', b='0')
if floating is not None: if floating is not None:
@@ -171,7 +170,7 @@ class ImagesManager(object):
return fname return fname
def serialize(self, images_map): def serialize(self, images_map):
for img in itervalues(self.images): for img in self.images.values():
images_map['word/' + img.fname] = partial(self.get_data, img.item) images_map['word/' + img.fname] = partial(self.get_data, img.item)
def get_data(self, item): def get_data(self, item):
+5 -7
View File
@@ -1,8 +1,6 @@
from collections import defaultdict from collections import defaultdict
from operator import attrgetter from operator import attrgetter
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
@@ -60,7 +58,7 @@ class NumberingDefinition(object):
items_for_level = defaultdict(list) items_for_level = defaultdict(list)
container_for_level = {} container_for_level = {}
type_for_level = {} type_for_level = {}
for ilvl, items in iteritems(self.level_map): for ilvl, items in self.level_map.items():
for container, list_tag, block, list_type, tag_style in items: for container, list_tag, block, list_type, tag_style in items:
items_for_level[ilvl].append(list_tag) items_for_level[ilvl].append(list_tag)
container_for_level[ilvl] = container container_for_level[ilvl] = container
@@ -74,7 +72,7 @@ class NumberingDefinition(object):
return hash(self.levels) return hash(self.levels)
def link_blocks(self): def link_blocks(self):
for ilvl, items in iteritems(self.level_map): for ilvl, items in self.level_map.items():
for container, list_tag, block, list_type, tag_style in items: for container, list_tag, block, list_type, tag_style in items:
block.numbering_id = (self.num_id + 1, ilvl) block.numbering_id = (self.num_id + 1, ilvl)
@@ -146,16 +144,16 @@ class ListsManager(object):
ilvl = len(container_tags) - 1 ilvl = len(container_tags) - 1
l.level_map[ilvl].append((container_tags[0], list_tag, block, list_type, tag_style)) l.level_map[ilvl].append((container_tags[0], list_tag, block, list_type, tag_style))
[nd.finalize() for nd in itervalues(lists)] [nd.finalize() for nd in lists.values()]
definitions = {} definitions = {}
for defn in itervalues(lists): for defn in lists.values():
try: try:
defn = definitions[defn] defn = definitions[defn]
except KeyError: except KeyError:
definitions[defn] = defn definitions[defn] = defn
defn.num_id = len(definitions) - 1 defn.num_id = len(definitions) - 1
defn.link_blocks() defn.link_blocks()
self.definitions = sorted(itervalues(definitions), key=attrgetter('num_id')) self.definitions = sorted(definitions.values(), key=attrgetter('num_id'))
def serialize(self, parent): def serialize(self, parent):
for defn in self.definitions: for defn in self.definitions:
+4 -5
View File
@@ -7,7 +7,6 @@ from lxml import etree
from ebook_converter.ebooks import parse_css_length from ebook_converter.ebooks import parse_css_length
from ebook_converter.ebooks.docx.writer.utils import convert_color, int_or_zero from ebook_converter.ebooks.docx.writer.utils import convert_color, int_or_zero
from ebook_converter.utils.localization import lang_as_iso639_1 from ebook_converter.utils.localization import lang_as_iso639_1
from ebook_converter.polyglot.builtins import iteritems
from ebook_converter.tinycss.css21 import CSS21Parser from ebook_converter.tinycss.css21 import CSS21Parser
@@ -155,7 +154,7 @@ class DOCXStyle(object):
getattr(self, x) for x in self.ALL_PROPS)) getattr(self, x) for x in self.ALL_PROPS))
def makeelement(self, parent, name, **attrs): def makeelement(self, parent, name, **attrs):
return parent.makeelement(self.w(name), **{self.w(k):v for k, v in iteritems(attrs)}) return parent.makeelement(self.w(name), **{self.w(k):v for k, v in attrs.items()})
def __hash__(self): def __hash__(self):
return self._hash return self._hash
@@ -362,7 +361,7 @@ class DescendantTextStyle(object):
p = [] p = []
def add(name, **props): def add(name, **props):
p.append((name, frozenset(iteritems(props)))) p.append((name, frozenset(props.items())))
def vals(attr): def vals(attr):
return getattr(parent_style, attr), getattr(child_style, attr) return getattr(parent_style, attr), getattr(child_style, attr)
@@ -559,7 +558,7 @@ class BlockStyle(DOCXStyle):
def serialize_properties(self, pPr, normal_style): def serialize_properties(self, pPr, normal_style):
makeelement, w = self.makeelement, self.w makeelement, w = self.makeelement, self.w
spacing = makeelement(pPr, 'spacing') spacing = makeelement(pPr, 'spacing')
for edge, attr in iteritems({'top':'before', 'bottom':'after'}): for edge, attr in {'top':'before', 'bottom':'after'}.items():
getter = attrgetter('css_margin_' + edge) getter = attrgetter('css_margin_' + edge)
css_val, css_unit = parse_css_length(getter(self)) css_val, css_unit = parse_css_length(getter(self))
if css_unit in ('em', 'ex'): if css_unit in ('em', 'ex'):
@@ -693,7 +692,7 @@ class StylesManager(object):
counts = Counter() counts = Counter()
smap = {} smap = {}
for (bs, rs), blocks in iteritems(used_pairs): for (bs, rs), blocks in used_pairs.items():
s = CombinedStyle(bs, rs, blocks, self.namespace) s = CombinedStyle(bs, rs, blocks, self.namespace)
smap[(bs, rs)] = s smap[(bs, rs)] = s
counts[s] += sum(1 for b in blocks if not b.is_empty()) counts[s] += sum(1 for b in blocks if not b.is_empty())
+1 -2
View File
@@ -2,7 +2,6 @@ from collections import namedtuple
from ebook_converter.ebooks.docx.writer.utils import convert_color from ebook_converter.ebooks.docx.writer.utils import convert_color
from ebook_converter.ebooks.docx.writer.styles import read_css_block_borders as rcbb, border_edges from ebook_converter.ebooks.docx.writer.styles import read_css_block_borders as rcbb, border_edges
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -121,7 +120,7 @@ class Cell(object):
makeelement(tcPr, 'w:shd', w_val="clear", w_color="auto", w_fill=bc) makeelement(tcPr, 'w:shd', w_val="clear", w_color="auto", w_fill=bc)
b = makeelement(tcPr, 'w:tcBorders', append=False) b = makeelement(tcPr, 'w:tcBorders', append=False)
for edge, border in iteritems(self.borders): for edge, border in self.borders.items():
if border is not None and border.width > 0 and border.style != 'none': if border is not None and border.width > 0 and border.style != 'none':
makeelement(b, 'w:' + edge, w_val=border.style, w_sz=str(border.width), w_color=border.color) makeelement(b, 'w:' + edge, w_val=border.style, w_sz=str(border.width), w_color=border.color)
if len(b) > 0: if len(b) > 0:
@@ -37,7 +37,6 @@ from ebook_converter.ebooks.lrf.pylrs.pylrs import (
RuledLine, Span, Sub, Sup, TextBlock RuledLine, Span, Sub, Sup, TextBlock
) )
from ebook_converter.ptempfile import PersistentTemporaryFile from ebook_converter.ptempfile import PersistentTemporaryFile
from ebook_converter.polyglot.builtins import itervalues
from ebook_converter.polyglot.urllib import unquote from ebook_converter.polyglot.urllib import unquote
from PIL import Image as PILImage from PIL import Image as PILImage
@@ -1774,7 +1773,7 @@ class HTMLConverter(object):
self.book.renderLrs(path) if lrs else self.book.renderLrf(path) self.book.renderLrs(path) if lrs else self.book.renderLrf(path)
def cleanup(self): def cleanup(self):
for _file in chain(itervalues(self.scaled_images), itervalues(self.rotated_images)): for _file in chain(self.scaled_images.values(), self.rotated_images.values()):
_file.__del__() _file.__del__()
+1 -2
View File
@@ -9,7 +9,6 @@ import codecs
import os import os
from .pylrfopt import tagListOptimizer from .pylrfopt import tagListOptimizer
from ebook_converter.polyglot.builtins import iteritems
PYLRF_VERSION = "1.0" PYLRF_VERSION = "1.0"
@@ -525,7 +524,7 @@ class LrfObject(object):
# belongs somewhere, so here it is. # belongs somewhere, so here it is.
# #
composites = {} composites = {}
for name, value in iteritems(tagDict): for name, value in tagDict.items():
if name == 'rubyAlignAndAdjust': if name == 'rubyAlignAndAdjust':
continue continue
if name in { if name in {
+2 -2
View File
@@ -51,7 +51,7 @@ DEFAULT_GENREADING = "fs" # default is yes to both lrf and lrs
from ebook_converter import __appname__, __version__ from ebook_converter import __appname__, __version__
from ebook_converter import entity_to_unicode from ebook_converter import entity_to_unicode
from ebook_converter.polyglot.builtins import iteritems, native_string_type from ebook_converter.polyglot.builtins import native_string_type
class LrsError(Exception): class LrsError(Exception):
@@ -1835,7 +1835,7 @@ class Span(LrsSimpleChar1, LrsContainer):
oldTextStyle = self.findCurrentTextStyle() oldTextStyle = self.findCurrentTextStyle()
# set the attributes we want changed # set the attributes we want changed
for (name, value) in tuple(iteritems(self.attrs)): for name, value in tuple(self.attrs.items()):
if name in oldTextStyle.attrs and oldTextStyle.attrs[name] == self.attrs[name]: if name in oldTextStyle.attrs and oldTextStyle.attrs[name] == self.attrs[name]:
self.attrs.pop(name) self.attrs.pop(name)
else: else:
+3 -3
View File
@@ -9,7 +9,7 @@ import urllib.parse
from ebook_converter import relpath, guess_type, prints, force_unicode from ebook_converter import relpath, guess_type, prints, force_unicode
from ebook_converter.utils.config_base import tweaks from ebook_converter.utils.config_base import tweaks
from ebook_converter.polyglot.builtins import iteritems, itervalues, as_unicode from ebook_converter.polyglot.builtins import as_unicode
from ebook_converter.polyglot.urllib import unquote from ebook_converter.polyglot.urllib import unquote
@@ -49,7 +49,7 @@ def remove_bracketed_text(src, brackets=None):
counts = Counter() counts = Counter()
buf = [] buf = []
src = force_unicode(src) src = force_unicode(src)
rmap = {v: k for k, v in iteritems(brackets)} rmap = {v: k for k, v in brackets.items()}
for char in src: for char in src:
if char in brackets: if char in brackets:
counts[char] += 1 counts[char] += 1
@@ -57,7 +57,7 @@ def remove_bracketed_text(src, brackets=None):
idx = rmap[char] idx = rmap[char]
if counts[idx] > 0: if counts[idx] > 0:
counts[idx] -= 1 counts[idx] -= 1
elif sum(itervalues(counts)) < 1: elif sum(counts.values()) < 1:
buf.append(char) buf.append(char)
return ''.join(buf) return ''.join(buf)
+4 -5
View File
@@ -7,7 +7,6 @@ from ebook_converter.ebooks.metadata.book import (SC_COPYABLE_FIELDS,
TOP_LEVEL_IDENTIFIERS, ALL_METADATA_FIELDS) TOP_LEVEL_IDENTIFIERS, ALL_METADATA_FIELDS)
from ebook_converter.library.field_metadata import FieldMetadata from ebook_converter.library.field_metadata import FieldMetadata
from ebook_converter.utils.icu import sort_key from ebook_converter.utils.icu import sort_key
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -253,7 +252,7 @@ class Metadata(object):
Set all identifiers. Note that if you previously set ISBN, calling Set all identifiers. Note that if you previously set ISBN, calling
this method will delete it. this method will delete it.
''' '''
cleaned = {ck(k):cv(v) for k, v in iteritems(identifiers) if k and v} cleaned = {ck(k):cv(v) for k, v in identifiers.items() if k and v}
object.__getattribute__(self, '_data')['identifiers'] = cleaned object.__getattribute__(self, '_data')['identifiers'] = cleaned
def set_identifier(self, typ, val): def set_identifier(self, typ, val):
@@ -394,7 +393,7 @@ class Metadata(object):
return return
um = {} um = {}
for key, meta in iteritems(metadata): for key, meta in metadata.items():
m = meta.copy() m = meta.copy()
if '#value#' not in m: if '#value#' not in m:
if m['datatype'] == 'text' and m['is_multiple']: if m['datatype'] == 'text' and m['is_multiple']:
@@ -574,7 +573,7 @@ class Metadata(object):
if callable(getattr(other, 'get_identifiers', None)): if callable(getattr(other, 'get_identifiers', None)):
d = self.get_identifiers() d = self.get_identifiers()
s = other.get_identifiers() s = other.get_identifiers()
d.update([v for v in iteritems(s) if v[1] is not None]) d.update([v for v in s.items() if v[1] is not None])
self.set_identifiers(d) self.set_identifiers(d)
else: else:
# other structure not Metadata. Copy the top-level identifiers # other structure not Metadata. Copy the top-level identifiers
@@ -748,7 +747,7 @@ class Metadata(object):
fmt('Rights', str(self.rights)) fmt('Rights', str(self.rights))
if self.identifiers: if self.identifiers:
fmt('Identifiers', ', '.join(['%s:%s'%(k, v) for k, v in fmt('Identifiers', ', '.join(['%s:%s'%(k, v) for k, v in
iteritems(self.identifiers)])) self.identifiers.items()]))
if self.comments: if self.comments:
fmt('Comments', self.comments) fmt('Comments', self.comments)
@@ -10,7 +10,7 @@ from ebook_converter.ebooks.metadata.book import SERIALIZABLE_FIELDS
from ebook_converter.constants import filesystem_encoding, preferred_encoding from ebook_converter.constants import filesystem_encoding, preferred_encoding
from ebook_converter.library.field_metadata import FieldMetadata from ebook_converter.library.field_metadata import FieldMetadata
from ebook_converter import isbytestring from ebook_converter import isbytestring
from ebook_converter.polyglot.builtins import iteritems, itervalues, as_bytes from ebook_converter.polyglot.builtins import as_bytes
from ebook_converter.polyglot.binary import as_base64_unicode, from_base64_bytes from ebook_converter.polyglot.binary import as_base64_unicode, from_base64_bytes
@@ -151,7 +151,7 @@ class JsonCodec(object):
def encode_metadata_attr(self, book, key): def encode_metadata_attr(self, book, key):
if key == 'user_metadata': if key == 'user_metadata':
meta = book.get_all_user_metadata(make_copy=True) meta = book.get_all_user_metadata(make_copy=True)
for fm in itervalues(meta): for fm in meta.values():
if fm['datatype'] == 'datetime': if fm['datatype'] == 'datetime':
fm['#value#'] = datetime_to_string(fm['#value#']) fm['#value#'] = datetime_to_string(fm['#value#'])
encode_is_multiple(fm) encode_is_multiple(fm)
@@ -186,7 +186,7 @@ class JsonCodec(object):
def raw_to_book(self, json_book, book_class, prefix): def raw_to_book(self, json_book, book_class, prefix):
try: try:
book = book_class(prefix, json_book.get('lpath', None)) book = book_class(prefix, json_book.get('lpath', None))
for key,val in iteritems(json_book): for key,val in json_book.items():
meta = self.decode_metadata(key, val) meta = self.decode_metadata(key, val)
if key == 'user_metadata': if key == 'user_metadata':
book.set_all_user_metadata(meta) book.set_all_user_metadata(meta)
@@ -203,7 +203,7 @@ class JsonCodec(object):
if key == 'classifiers': if key == 'classifiers':
key = 'identifiers' key = 'identifiers'
if key == 'user_metadata': if key == 'user_metadata':
for fm in itervalues(value): for fm in value.values():
if fm['datatype'] == 'datetime': if fm['datatype'] == 'datetime':
fm['#value#'] = string_to_datetime(fm['#value#']) fm['#value#'] = string_to_datetime(fm['#value#'])
decode_is_multiple(fm) decode_is_multiple(fm)
+3 -4
View File
@@ -13,7 +13,6 @@ from ebook_converter.ebooks.metadata.book.base import Metadata
from ebook_converter.ebooks.chardet import xml_to_unicode from ebook_converter.ebooks.chardet import xml_to_unicode
from ebook_converter import replace_entities, isbytestring from ebook_converter import replace_entities, isbytestring
from ebook_converter.utils.date import parse_date, is_date_undefined from ebook_converter.utils.date import parse_date, is_date_undefined
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -54,8 +53,8 @@ META_NAMES = {
'comments': ('comments', 'dc.description'), 'comments': ('comments', 'dc.description'),
'tags': ('tags',), 'tags': ('tags',),
} }
rmap_comment = {v:k for k, v in iteritems(COMMENT_NAMES)} rmap_comment = {v:k for k, v in COMMENT_NAMES.items()}
rmap_meta = {v:k for k, l in iteritems(META_NAMES) for v in l} rmap_meta = {v:k for k, l in META_NAMES.items() for v in l}
# Extract an HTML attribute value, supports both single and double quotes and # Extract an HTML attribute value, supports both single and double quotes and
@@ -230,7 +229,7 @@ def get_metadata_(src, encoding=None):
mi.tags = tags mi.tags = tags
# IDENTIFIERS # IDENTIFIERS
for (k,v) in iteritems(meta_tag_ids): for (k,v) in meta_tag_ids.items():
v = [x.strip() for x in v if x.strip()] v = [x.strip() for x in v if x.strip()]
if v: if v:
mi.set_identifier(k, v[0]) mi.set_identifier(k, v[0])
+7 -8
View File
@@ -27,7 +27,6 @@ from ebook_converter import prints, guess_type
from ebook_converter.utils.cleantext import clean_ascii_chars, clean_xml_chars from ebook_converter.utils.cleantext import clean_ascii_chars, clean_xml_chars
from ebook_converter.utils.config import tweaks from ebook_converter.utils.config import tweaks
from ebook_converter.utils.xml_parse import safe_xml_fromstring from ebook_converter.utils.xml_parse import safe_xml_fromstring
from ebook_converter.polyglot.builtins import iteritems
from ebook_converter.polyglot.urllib import unquote from ebook_converter.polyglot.urllib import unquote
@@ -970,7 +969,7 @@ class OPF(object): # {{{
'descendant::*[local-name() = "identifier" and text()]')( 'descendant::*[local-name() = "identifier" and text()]')(
self.metadata): self.metadata):
found_scheme = False found_scheme = False
for attr, val in iteritems(x.attrib): for attr, val in x.attrib.items():
if attr.endswith('scheme'): if attr.endswith('scheme'):
typ = val.lower() typ = val.lower()
val = etree.tostring(x, with_tail=False, encoding='unicode', val = etree.tostring(x, with_tail=False, encoding='unicode',
@@ -1003,7 +1002,7 @@ class OPF(object): # {{{
self.metadata): self.metadata):
xid = x.get('id', None) xid = x.get('id', None)
is_package_identifier = uuid_id is not None and uuid_id == xid is_package_identifier = uuid_id is not None and uuid_id == xid
typ = {val.lower() for attr, val in iteritems(x.attrib) if attr.endswith('scheme')} typ = {val.lower() for attr, val in x.attrib.items() if attr.endswith('scheme')}
if is_package_identifier: if is_package_identifier:
typ = tuple(typ) typ = tuple(typ)
if typ and typ[0] in identifiers: if typ and typ[0] in identifiers:
@@ -1012,7 +1011,7 @@ class OPF(object): # {{{
if typ and not (typ & {'calibre', 'uuid'}): if typ and not (typ & {'calibre', 'uuid'}):
x.getparent().remove(x) x.getparent().remove(x)
for typ, val in iteritems(identifiers): for typ, val in identifiers.items():
attrib = {'{%s}scheme'%self.NAMESPACES['opf']: typ.upper()} attrib = {'{%s}scheme'%self.NAMESPACES['opf']: typ.upper()}
self.set_text(self.create_metadata_element( self.set_text(self.create_metadata_element(
'identifier', attrib=attrib), str(val)) 'identifier', attrib=attrib), str(val))
@@ -1134,7 +1133,7 @@ class OPF(object): # {{{
def page_progression_direction(self): def page_progression_direction(self):
spine = self.XPath('descendant::*[re:match(name(), "spine", "i")][1]')(self.root) spine = self.XPath('descendant::*[re:match(name(), "spine", "i")][1]')(self.root)
if spine: if spine:
for k, v in iteritems(spine[0].attrib): for k, v in spine[0].attrib.items():
if k == 'page-progression-direction' or k.endswith('}page-progression-direction'): if k == 'page-progression-direction' or k.endswith('}page-progression-direction'):
return v return v
@@ -1501,7 +1500,7 @@ class OPFCreator(Metadata):
a(DC_ELEM('description', self.comments)) a(DC_ELEM('description', self.comments))
if self.publisher: if self.publisher:
a(DC_ELEM('publisher', self.publisher)) a(DC_ELEM('publisher', self.publisher))
for key, val in iteritems(self.get_identifiers()): for key, val in self.get_identifiers().items():
a(DC_ELEM('identifier', val, opf_attrs={'scheme':key.upper()})) a(DC_ELEM('identifier', val, opf_attrs={'scheme':key.upper()}))
if self.rights: if self.rights:
a(DC_ELEM('rights', self.rights)) a(DC_ELEM('rights', self.rights))
@@ -1627,7 +1626,7 @@ def metadata_to_opf(mi, as_string=True, default_lang=None):
try: try:
elem = metadata.makeelement(tag, attrib=attrib) elem = metadata.makeelement(tag, attrib=attrib)
except ValueError: except ValueError:
elem = metadata.makeelement(tag, attrib={k:clean_xml_chars(v) for k, v in iteritems(attrib)}) elem = metadata.makeelement(tag, attrib={k:clean_xml_chars(v) for k, v in attrib.items()})
elem.tail = '\n'+(' '*8) elem.tail = '\n'+(' '*8)
if text: if text:
try: try:
@@ -1648,7 +1647,7 @@ def metadata_to_opf(mi, as_string=True, default_lang=None):
factory(DC('description'), clean_ascii_chars(mi.comments)) factory(DC('description'), clean_ascii_chars(mi.comments))
if mi.publisher: if mi.publisher:
factory(DC('publisher'), mi.publisher) factory(DC('publisher'), mi.publisher)
for key, val in iteritems(mi.get_identifiers()): for key, val in mi.get_identifiers().items():
factory(DC('identifier'), val, scheme=key.upper()) factory(DC('identifier'), val, scheme=key.upper())
if mi.rights: if mi.rights:
factory(DC('rights'), mi.rights) factory(DC('rights'), mi.rights)
+6 -7
View File
@@ -2,7 +2,6 @@ import json
import re import re
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from functools import wraps from functools import wraps
from ebook_converter.polyglot.builtins import iteritems
from lxml import etree from lxml import etree
@@ -185,9 +184,9 @@ def ensure_prefix(root, prefixes, prefix, value=None):
if prefixes is None: if prefixes is None:
prefixes = read_prefixes(root) prefixes = read_prefixes(root)
prefixes[prefix] = value or reserved_prefixes[prefix] prefixes[prefix] = value or reserved_prefixes[prefix]
prefixes = {k:v for k, v in iteritems(prefixes) if reserved_prefixes.get(k) != v} prefixes = {k:v for k, v in prefixes.items() if reserved_prefixes.get(k) != v}
if prefixes: if prefixes:
root.set('prefix', ' '.join('%s: %s' % (k, v) for k, v in iteritems(prefixes))) root.set('prefix', ' '.join('%s: %s' % (k, v) for k, v in prefixes.items()))
else: else:
root.attrib.pop('prefix', None) root.attrib.pop('prefix', None)
@@ -294,7 +293,7 @@ def set_identifiers(root, prefixes, refines, new_identifiers, force_identifiers=
remove_element(ident, refines) remove_element(ident, refines)
continue continue
metadata = XPath('./opf:metadata')(root)[0] metadata = XPath('./opf:metadata')(root)[0]
for scheme, val in iteritems(new_identifiers): for scheme, val in new_identifiers.items():
ident = metadata.makeelement(DC('identifier')) ident = metadata.makeelement(DC('identifier'))
ident.text = '%s:%s' % (scheme, val) ident.text = '%s:%s' % (scheme, val)
if package_identifier is None: if package_identifier is None:
@@ -850,7 +849,7 @@ set_author_link_map = dict_writer('author_link_map')
def deserialize_user_metadata(val): def deserialize_user_metadata(val):
val = json.loads(val, object_hook=from_json) val = json.loads(val, object_hook=from_json)
ans = {} ans = {}
for name, fm in iteritems(val): for name, fm in val.items():
decode_is_multiple(fm) decode_is_multiple(fm)
ans[name] = fm ans[name] = fm
return ans return ans
@@ -965,7 +964,7 @@ def read_metadata(root, ver=None, return_extra_data=False):
prefixes, refines = read_prefixes(root), read_refines(root) prefixes, refines = read_prefixes(root), read_refines(root)
identifiers = read_identifiers(root, prefixes, refines) identifiers = read_identifiers(root, prefixes, refines)
ids = {} ids = {}
for key, vals in iteritems(identifiers): for key, vals in identifiers.items():
if key == 'calibre': if key == 'calibre':
ans.application_id = vals[0] ans.application_id = vals[0]
elif key == 'uuid': elif key == 'uuid':
@@ -1003,7 +1002,7 @@ def read_metadata(root, ver=None, return_extra_data=False):
ans.series, ans.series_index = s, si ans.series, ans.series_index = s, si
ans.author_link_map = read_author_link_map(root, prefixes, refines) or ans.author_link_map ans.author_link_map = read_author_link_map(root, prefixes, refines) or ans.author_link_map
ans.user_categories = read_user_categories(root, prefixes, refines) or ans.user_categories ans.user_categories = read_user_categories(root, prefixes, refines) or ans.user_categories
for name, fm in iteritems((read_user_metadata(root, prefixes, refines) or {})): for name, fm in (read_user_metadata(root, prefixes, refines) or {}).items():
ans.set_user_metadata(name, fm) ans.set_user_metadata(name, fm)
if return_extra_data: if return_extra_data:
ans = ans, ver, read_raster_cover(root, prefixes, refines), first_spine_item(root, prefixes, refines) ans = ans, ver, read_raster_cover(root, prefixes, refines), first_spine_item(root, prefixes, refines)
+2 -3
View File
@@ -10,7 +10,6 @@ from ebook_converter.ptempfile import TemporaryDirectory
from ebook_converter.ebooks.metadata import ( from ebook_converter.ebooks.metadata import (
MetaInformation, string_to_authors, check_isbn, check_doi) MetaInformation, string_to_authors, check_isbn, check_doi)
from ebook_converter.utils.ipc.simple_worker import fork_job, WorkerError from ebook_converter.utils.ipc.simple_worker import fork_job, WorkerError
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -157,9 +156,9 @@ def get_metadata(stream, cover=True):
# Look for recognizable identifiers in the info dict, if they were not # Look for recognizable identifiers in the info dict, if they were not
# found in the XMP metadata # found in the XMP metadata
for scheme, check_func in iteritems({'doi':check_doi, 'isbn':check_isbn}): for scheme, check_func in {'doi':check_doi, 'isbn':check_isbn}.items():
if scheme not in mi.get_identifiers(): if scheme not in mi.get_identifiers():
for k, v in iteritems(info): for k, v in info.items():
if k != 'xmp_metadata': if k != 'xmp_metadata':
val = check_func(v) val = check_func(v)
if val: if val:
+11 -12
View File
@@ -12,7 +12,6 @@ from ebook_converter.ebooks.metadata.book.base import Metadata
from ebook_converter.ebooks.metadata.opf2 import dump_dict from ebook_converter.ebooks.metadata.opf2 import dump_dict
from ebook_converter.utils.date import parse_date, isoformat, now from ebook_converter.utils.date import parse_date, isoformat, now
from ebook_converter.utils.localization import canonicalize_lang, lang_as_iso639_1 from ebook_converter.utils.localization import canonicalize_lang, lang_as_iso639_1
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -320,7 +319,7 @@ def metadata_from_xmp_packet(raw_bytes):
identifiers[scheme] = val identifiers[scheme] = val
# Check Dublin Core for recognizable identifier types # Check Dublin Core for recognizable identifier types
for scheme, check_func in iteritems({'doi':check_doi, 'isbn':check_isbn}): for scheme, check_func in {'doi':check_doi, 'isbn':check_isbn}.items():
if scheme not in identifiers: if scheme not in identifiers:
val = check_func(first_simple('//dc:identifier', root)) val = check_func(first_simple('//dc:identifier', root))
if val: if val:
@@ -404,7 +403,7 @@ def create_identifiers(xmp, identifiers):
xmp.append(xmpid) xmp.append(xmpid)
bag = xmpid.makeelement(expand('rdf:Bag')) bag = xmpid.makeelement(expand('rdf:Bag'))
xmpid.append(bag) xmpid.append(bag)
for scheme, value in iteritems(identifiers): for scheme, value in identifiers.items():
li = bag.makeelement(expand('rdf:li')) li = bag.makeelement(expand('rdf:li'))
li.set(expand('rdf:parseType'), 'Resource') li.set(expand('rdf:parseType'), 'Resource')
bag.append(li) bag.append(li)
@@ -440,7 +439,7 @@ def create_user_metadata(calibre, all_user_metadata):
calibre.append(s) calibre.append(s)
bag = s.makeelement(expand('rdf:Bag')) bag = s.makeelement(expand('rdf:Bag'))
s.append(bag) s.append(bag)
for name, fm in iteritems(all_user_metadata): for name, fm in all_user_metadata.items():
try: try:
fm = copy.copy(fm) fm = copy.copy(fm)
encode_is_multiple(fm) encode_is_multiple(fm)
@@ -470,12 +469,12 @@ def metadata_to_xmp_packet(mi):
dc = rdf.makeelement(expand('rdf:Description'), nsmap=nsmap('dc')) dc = rdf.makeelement(expand('rdf:Description'), nsmap=nsmap('dc'))
dc.set(expand('rdf:about'), '') dc.set(expand('rdf:about'), '')
rdf.append(dc) rdf.append(dc)
for prop, tag in iteritems({'title':'dc:title', 'comments':'dc:description'}): for prop, tag in {'title':'dc:title', 'comments':'dc:description'}.items():
val = mi.get(prop) or '' val = mi.get(prop) or ''
create_alt_property(dc, tag, val) create_alt_property(dc, tag, val)
for prop, (tag, ordered) in iteritems({ for prop, (tag, ordered) in {'authors': ('dc:creator', True),
'authors':('dc:creator', True), 'tags':('dc:subject', False), 'publisher':('dc:publisher', False), 'tags': ('dc:subject', False),
}): 'publisher': ('dc:publisher', False)}.items():
val = mi.get(prop) or () val = mi.get(prop) or ()
if isinstance(val, (str, bytes)): if isinstance(val, (str, bytes)):
val = [val] val = [val]
@@ -499,9 +498,9 @@ def metadata_to_xmp_packet(mi):
identifiers = mi.get_identifiers() identifiers = mi.get_identifiers()
if identifiers: if identifiers:
create_identifiers(xmp, identifiers) create_identifiers(xmp, identifiers)
for scheme, val in iteritems(identifiers): for scheme, val in identifiers.items():
if scheme in {'isbn', 'doi'}: if scheme in {'isbn', 'doi'}:
for prefix, parent in iteritems(extra_ids): for prefix, parent in extra_ids.items():
ie = parent.makeelement(expand('%s:%s'%(prefix, scheme))) ie = parent.makeelement(expand('%s:%s'%(prefix, scheme)))
ie.text = val ie.text = val
parent.append(ie) parent.append(ie)
@@ -549,7 +548,7 @@ def find_used_namespaces(elem):
def find_preferred_prefix(namespace, elems): def find_preferred_prefix(namespace, elems):
for elem in elems: for elem in elems:
ans = {v:k for k, v in iteritems(elem.nsmap)}.get(namespace, None) ans = {v:k for k, v in elem.nsmap.items()}.get(namespace, None)
if ans is not None: if ans is not None:
return ans return ans
return find_preferred_prefix(namespace, elem.iterchildren(etree.Element)) return find_preferred_prefix(namespace, elem.iterchildren(etree.Element))
@@ -561,7 +560,7 @@ def find_nsmap(elems):
used_namespaces |= find_used_namespaces(elem) used_namespaces |= find_used_namespaces(elem)
ans = {} ans = {}
used_namespaces -= {NS_MAP['xml'], NS_MAP['x'], None, NS_MAP['rdf']} used_namespaces -= {NS_MAP['xml'], NS_MAP['x'], None, NS_MAP['rdf']}
rmap = {v:k for k, v in iteritems(NS_MAP)} rmap = {v:k for k, v in NS_MAP.items()}
i = 0 i = 0
for ns in used_namespaces: for ns in used_namespaces:
if ns in rmap: if ns in rmap:
+2 -3
View File
@@ -3,7 +3,6 @@ from collections import OrderedDict, namedtuple
from ebook_converter.ebooks.mobi.utils import (decint, count_set_bits, from ebook_converter.ebooks.mobi.utils import (decint, count_set_bits,
decode_string) decode_string)
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -119,10 +118,10 @@ class CNCX(object): # {{{
__nonzero__ = __bool__ __nonzero__ = __bool__
def iteritems(self): def iteritems(self):
return iteritems(self.records) return self.records.items()
def items(self): def items(self):
return iteritems(self.records) return self.records.items()
# }}} # }}}
+2 -5
View File
@@ -16,7 +16,6 @@ from ebook_converter.ebooks.metadata.toc import TOC
from ebook_converter.ebooks.mobi.reader.headers import BookHeader from ebook_converter.ebooks.mobi.reader.headers import BookHeader
from ebook_converter.utils.img import save_cover_data_to, gif_data_to_png_data, AnimatedGIF from ebook_converter.utils.img import save_cover_data_to, gif_data_to_png_data, AnimatedGIF
from ebook_converter.utils.imghdr import what from ebook_converter.utils.imghdr import what
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -918,8 +917,7 @@ class MobiReader(object):
def test_mbp_regex(): def test_mbp_regex():
for raw, m in iteritems({ for raw, m in {'<mbp:pagebreak></mbp:pagebreak>':'',
'<mbp:pagebreak></mbp:pagebreak>':'',
'<mbp:pagebreak xxx></mbp:pagebreak>yyy':' xxxyyy', '<mbp:pagebreak xxx></mbp:pagebreak>yyy':' xxxyyy',
'<mbp:pagebreak> </mbp:pagebreak>':'', '<mbp:pagebreak> </mbp:pagebreak>':'',
'<mbp:pagebreak>xxx':'xxx', '<mbp:pagebreak>xxx':'xxx',
@@ -928,8 +926,7 @@ def test_mbp_regex():
'<mbp:pagebreak / >':' ', '<mbp:pagebreak / >':' ',
'</mbp:pagebreak>':'', '</mbp:pagebreak>':'',
'</mbp:pagebreak sdf>':' sdf', '</mbp:pagebreak sdf>':' sdf',
'</mbp:pagebreak><mbp:pagebreak></mbp:pagebreak>xxx':'xxx', '</mbp:pagebreak><mbp:pagebreak></mbp:pagebreak>xxx':'xxx'}.items():
}):
ans = MobiReader.PAGE_BREAK_PAT.sub(r'\1', raw) ans = MobiReader.PAGE_BREAK_PAT.sub(r'\1', raw)
if ans != m: if ans != m:
raise Exception('%r != %r for %r'%(ans, m, raw)) raise Exception('%r != %r for %r'%(ans, m, raw))
+3 -5
View File
@@ -4,7 +4,6 @@ from ebook_converter import replace_entities
from ebook_converter.ebooks.metadata.toc import TOC from ebook_converter.ebooks.metadata.toc import TOC
from ebook_converter.ebooks.mobi.reader.headers import NULL_INDEX from ebook_converter.ebooks.mobi.reader.headers import NULL_INDEX
from ebook_converter.ebooks.mobi.reader.index import read_index from ebook_converter.ebooks.mobi.reader.index import read_index
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -53,8 +52,7 @@ def read_ncx(sections, index, codec):
if index != NULL_INDEX: if index != NULL_INDEX:
table, cncx = read_index(sections, index, codec) table, cncx = read_index(sections, index, codec)
for num, x in enumerate(iteritems(table)): for num, (text, tag_map) in enumerate(table.items()):
text, tag_map = x
entry = default_entry.copy() entry = default_entry.copy()
entry['name'] = text entry['name'] = text
entry['num'] = num entry['num'] = num
@@ -68,9 +66,9 @@ def read_ncx(sections, index, codec):
# offset # offset
fieldvalue = tuple(tag_map[tag]) fieldvalue = tuple(tag_map[tag])
entry[fieldname] = fieldvalue entry[fieldname] = fieldvalue
for which, name in iteritems({3:'text', 5:'kind', 70:'description', for which, name in {3:'text', 5:'kind', 70:'description',
71:'author', 72:'image_caption', 71:'author', 72:'image_caption',
73:'image_attribution'}): 73:'image_attribution'}.items():
if tag == which: if tag == which:
entry[name] = cncx.get(fieldvalue, entry[name] = cncx.get(fieldvalue,
default_entry[name]) default_entry[name])
@@ -5,7 +5,6 @@ from collections import OrderedDict, defaultdict
from ebook_converter.ebooks.mobi.utils import (encint, encode_number_as_hex, from ebook_converter.ebooks.mobi.utils import (encint, encode_number_as_hex,
encode_tbs, align_block, RECORD_SIZE, CNCX as CNCX_) encode_tbs, align_block, RECORD_SIZE, CNCX as CNCX_)
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -104,7 +103,7 @@ class IndexEntry(object):
'author_offset': 71, 'author_offset': 71,
} }
RTAG_MAP = {v:k for k, v in iteritems(TAG_VALUES)} # noqa RTAG_MAP = {v:k for k, v in TAG_VALUES.items()} # noqa
def __init__(self, offset, label_offset): def __init__(self, offset, label_offset):
self.offset, self.label_offset = offset, label_offset self.offset, self.label_offset = offset, label_offset
@@ -220,8 +219,8 @@ class SecondaryIndexEntry(IndexEntry):
# The values for this index entry # The values for this index entry
# I dont know what the 5 means, it is not the number of entries # I dont know what the 5 means, it is not the number of entries
self.secondary = [5 if tag == min( self.secondary = [5 if tag == min(self.INDEX_MAP.values())
itervalues(self.INDEX_MAP)) else 0, 0, tag] else 0, 0, tag]
@property @property
def tag_nums(self): def tag_nums(self):
@@ -233,7 +232,7 @@ class SecondaryIndexEntry(IndexEntry):
@classmethod @classmethod
def entries(cls): def entries(cls):
rmap = {v:k for k,v in iteritems(cls.INDEX_MAP)} rmap = {v:k for k,v in cls.INDEX_MAP.items()}
for tag in sorted(rmap, reverse=True): for tag in sorted(rmap, reverse=True):
yield cls(rmap[tag]) yield cls(rmap[tag])
@@ -278,7 +277,7 @@ class TBS(object): # {{{
for x in ('starts', 'ends', 'completes'): for x in ('starts', 'ends', 'completes'):
for idx in data[x]: for idx in data[x]:
depth_map[idx.depth].append(idx) depth_map[idx.depth].append(idx)
for l in itervalues(depth_map): for l in depth_map.values():
l.sort(key=lambda x:x.offset) l.sort(key=lambda x:x.offset)
self.periodical_tbs(data, first, depth_map) self.periodical_tbs(data, first, depth_map)
else: else:
+2 -4
View File
@@ -10,7 +10,6 @@ from ebook_converter.ebooks.mobi.writer2 import (PALMDOC, UNCOMPRESSED)
from ebook_converter.ebooks.mobi.utils import (encint, encode_trailing_data, from ebook_converter.ebooks.mobi.utils import (encint, encode_trailing_data,
align_block, detect_periodical, RECORD_SIZE, create_text_record) align_block, detect_periodical, RECORD_SIZE, create_text_record)
from ebook_converter.ebooks.mobi.writer2.indexer import Indexer from ebook_converter.ebooks.mobi.writer2.indexer import Indexer
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -421,10 +420,9 @@ class MobiWriter(object):
extra_data_flags |= 0b10 extra_data_flags |= 0b10
header_fields['extra_data_flags'] = extra_data_flags header_fields['extra_data_flags'] = extra_data_flags
for k, v in iteritems({'last_text_record':'last_text_record_idx', for k, v in {'last_text_record':'last_text_record_idx',
'first_non_text_record':'first_non_text_record_idx', 'first_non_text_record':'first_non_text_record_idx',
'ncx_index':'primary_index_record_idx', 'ncx_index':'primary_index_record_idx'}.items():
}):
header_fields[k] = getattr(self, v) header_fields[k] = getattr(self, v)
if header_fields['ncx_index'] is None: if header_fields['ncx_index'] is None:
header_fields['ncx_index'] = NULL_INDEX header_fields['ncx_index'] = NULL_INDEX
@@ -8,7 +8,6 @@ from ebook_converter.ebooks import generate_masthead
from ebook_converter.ebooks.oeb.base import OEB_RASTER_IMAGES from ebook_converter.ebooks.oeb.base import OEB_RASTER_IMAGES
from ebook_converter.ptempfile import PersistentTemporaryFile from ebook_converter.ptempfile import PersistentTemporaryFile
from ebook_converter.utils.imghdr import what from ebook_converter.utils.imghdr import what
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -155,7 +154,7 @@ class Resources(object):
def serialize(self, records, used_images): def serialize(self, records, used_images):
used_image_indices = self.used_image_indices | { used_image_indices = self.used_image_indices | {
v-1 for k, v in iteritems(self.item_map) if k in used_images} v-1 for k, v in self.item_map.items() if k in used_images}
for i in self.image_indices-used_image_indices: for i in self.image_indices-used_image_indices:
self.records[i] = PLACEHOLDER_GIF self.records[i] = PLACEHOLDER_GIF
records.extend(self.records) records.extend(self.records)
+1 -2
View File
@@ -6,7 +6,6 @@ from ebook_converter.constants import iswindows, isosx
from ebook_converter.ebooks.mobi.utils import (utf8_text, to_base) from ebook_converter.ebooks.mobi.utils import (utf8_text, to_base)
from ebook_converter.utils.localization import lang_as_iso639_1 from ebook_converter.utils.localization import lang_as_iso639_1
from ebook_converter.ebooks.metadata import authors_to_sort_string from ebook_converter.ebooks.metadata import authors_to_sort_string
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -159,7 +158,7 @@ def build_exth(metadata, prefer_author_sort=False, is_periodical=False,
else: else:
# Pretend to be kindlegen 1.2 # Pretend to be kindlegen 1.2
vals = {204:201, 205:1, 206:2, 207:33307} vals = {204:201, 205:1, 206:2, 207:33307}
for code, val in iteritems(vals): for code, val in vals.items():
exth.write(pack(b'>III', code, 12, val)) exth.write(pack(b'>III', code, 12, val))
nrecs += 1 nrecs += 1
if be_kindlegen2: if be_kindlegen2:
+6 -7
View File
@@ -17,7 +17,6 @@ from ebook_converter import (isbytestring, as_unicode, get_types_map)
from ebook_converter.ebooks.oeb.parse_utils import barename, XHTML_NS, namespace, XHTML, parse_html, NotHTML from ebook_converter.ebooks.oeb.parse_utils import barename, XHTML_NS, namespace, XHTML, parse_html, NotHTML
from ebook_converter.utils.cleantext import clean_xml_chars from ebook_converter.utils.cleantext import clean_xml_chars
from ebook_converter.utils.short_uuid import uuid4 from ebook_converter.utils.short_uuid import uuid4
from ebook_converter.polyglot.builtins import iteritems, itervalues
from ebook_converter.polyglot.urllib import unquote as urlunquote from ebook_converter.polyglot.urllib import unquote as urlunquote
@@ -700,7 +699,7 @@ class Metadata(object):
term = CALIBRE(local) term = CALIBRE(local)
self.term = term self.term = term
self.value = value self.value = value
for attr, value in tuple(iteritems(attrib)): for attr, value in tuple(attrib.items()):
if isprefixname(value): if isprefixname(value):
attrib[attr] = qname(value, nsmap) attrib[attr] = qname(value, nsmap)
nsattr = Metadata.OPF_ATTRS.get(attr, attr) nsattr = Metadata.OPF_ATTRS.get(attr, attr)
@@ -857,7 +856,7 @@ class Metadata(object):
def to_opf1(self, parent=None): def to_opf1(self, parent=None):
nsmap = self._opf1_nsmap nsmap = self._opf1_nsmap
nsrmap = {value: key for key, value in iteritems(nsmap)} nsrmap = {value: key for key, value in nsmap.items()}
elem = element(parent, 'metadata', nsmap=nsmap) elem = element(parent, 'metadata', nsmap=nsmap)
dcmeta = element(elem, 'dc-metadata', nsmap=OPF1_NSMAP) dcmeta = element(elem, 'dc-metadata', nsmap=OPF1_NSMAP)
xmeta = element(elem, 'x-metadata') xmeta = element(elem, 'x-metadata')
@@ -871,7 +870,7 @@ class Metadata(object):
def to_opf2(self, parent=None): def to_opf2(self, parent=None):
nsmap = self._opf2_nsmap nsmap = self._opf2_nsmap
nsrmap = {value: key for key, value in iteritems(nsmap)} nsrmap = {value: key for key, value in nsmap.items()}
elem = element(parent, OPF('metadata'), nsmap=nsmap) elem = element(parent, OPF('metadata'), nsmap=nsmap)
for term in self.items: for term in self.items:
for item in self.items[term]: for item in self.items[term]:
@@ -1424,7 +1423,7 @@ class Guide(object):
@property @property
def item(self): def item(self):
"""The manifest item associated with this reference.""" """The manifest item associated with this reference."""
path = uurllib.parse.rldefrag(self.href)[0] path = urllib.parse.urldefrag(self.href)[0]
hrefs = self.oeb.manifest.hrefs hrefs = self.oeb.manifest.hrefs
return hrefs.get(path, None) return hrefs.get(path, None)
@@ -1444,7 +1443,7 @@ class Guide(object):
return self.refs.pop(type, None) return self.refs.pop(type, None)
def remove_by_href(self, href): def remove_by_href(self, href):
remove = [r for r, i in iteritems(self.refs) if i.href == href] remove = [r for r, i in self.refs.items() if i.href == href]
for r in remove: for r in remove:
self.remove(r) self.remove(r)
@@ -1454,7 +1453,7 @@ class Guide(object):
__iter__ = iterkeys __iter__ = iterkeys
def values(self): def values(self):
return sorted(itervalues(self.refs), key=lambda ref: ref.ORDER.get(ref.type, 10000)) return sorted(self.refs.values(), key=lambda ref: ref.ORDER.get(ref.type, 10000))
def items(self): def items(self):
for type, ref in self.refs.items(): for type, ref in self.refs.items():
+56 -41
View File
@@ -5,7 +5,6 @@ from css_parser.css import PropertyValue
from css_parser import profile as cssprofiles, CSSParser from css_parser import profile as cssprofiles, CSSParser
from ebook_converter.tinycss.fonts3 import parse_font, serialize_font_family from ebook_converter.tinycss.fonts3 import parse_font, serialize_font_family
from ebook_converter.ebooks.oeb.base import css_text from ebook_converter.ebooks.oeb.base import css_text
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -137,7 +136,7 @@ def normalize_border(name, cssvalue):
style = normalizers['border-' + EDGES[0]]('border-' + EDGES[0], cssvalue) style = normalizers['border-' + EDGES[0]]('border-' + EDGES[0], cssvalue)
vals = style.copy() vals = style.copy()
for edge in EDGES[1:]: for edge in EDGES[1:]:
style.update({k.replace(EDGES[0], edge):v for k, v in iteritems(vals)}) style.update({k.replace(EDGES[0], edge):v for k, v in vals.items()})
return style return style
@@ -251,7 +250,7 @@ def condense_rule(style):
if prop.name and prop.name.startswith(x): if prop.name and prop.name.startswith(x):
expanded[x].append(prop) expanded[x].append(prop)
break break
for prefix, vals in iteritems(expanded): for prefix, vals in expanded.items():
if len(vals) > 1 and {x.priority for x in vals} == {''}: if len(vals) > 1 and {x.priority for x in vals} == {''}:
condensers[prefix[:-1]](style, vals) condensers[prefix[:-1]](style, vals)
@@ -277,18 +276,35 @@ def test_normalization(return_tests=False): # {{{
ans.update(expected) ans.update(expected)
return ans return ans
for raw, expected in iteritems({ for raw, expected in {'some_font': {'font-family':'some_font'},
'some_font': {'font-family':'some_font'}, 'inherit':{k:'inherit' for k in font_composition}, 'inherit':{k:'inherit' for k in font_composition},
'1.2pt/1.4 A_Font': {'font-family':'A_Font', 'font-size':'1.2pt', 'line-height':'1.4'}, '1.2pt/1.4 A_Font': {'font-family':'A_Font',
'bad font': {'font-family':'"bad font"'}, '10% serif': {'font-family':'serif', 'font-size':'10%'}, 'font-size':'1.2pt',
'12px "My Font", serif': {'font-family':'"My Font", serif', 'font-size': '12px'}, 'line-height':'1.4'},
'normal 0.6em/135% arial,sans-serif': {'font-family': 'arial, sans-serif', 'font-size': '0.6em', 'line-height':'135%', 'font-style':'normal'}, 'bad font': {'font-family':'"bad font"'},
'bold italic large serif': {'font-family':'serif', 'font-weight':'bold', 'font-style':'italic', 'font-size':'large'}, '10% serif': {'font-family':'serif',
'font-size':'10%'},
'12px "My Font", serif':
{'font-family':'"My Font", serif',
'font-size': '12px'},
'normal 0.6em/135% arial,sans-serif':
{'font-family': 'arial, sans-serif',
'font-size': '0.6em',
'line-height':'135%',
'font-style':'normal'},
'bold italic large serif': {'font-family':'serif',
'font-weight':'bold',
'font-style':'italic',
'font-size':'large'},
'bold italic small-caps larger/normal serif': 'bold italic small-caps larger/normal serif':
{'font-family':'serif', 'font-weight':'bold', 'font-style':'italic', 'font-size':'larger', {'font-family':'serif',
'line-height':'normal', 'font-variant':'small-caps'}, 'font-weight':'bold',
'2em A B': {'font-family': '"A B"', 'font-size': '2em'}, 'font-style':'italic',
}): 'font-size':'larger',
'line-height':'normal',
'font-variant':'small-caps'},
'2em A B': {'font-family': '"A B"',
'font-size': '2em'}}.items():
val = tuple(parseStyle('font: %s' % raw, validate=False))[0].cssValue val = tuple(parseStyle('font: %s' % raw, validate=False))[0].cssValue
style = normalizers['font']('font', val) style = normalizers['font']('font', val)
self.assertDictEqual(font_dict(expected), style, raw) self.assertDictEqual(font_dict(expected), style, raw)
@@ -296,7 +312,7 @@ def test_normalization(return_tests=False): # {{{
def test_border_normalization(self): def test_border_normalization(self):
def border_edge_dict(expected, edge='right'): def border_edge_dict(expected, edge='right'):
ans = {'border-%s-%s' % (edge, x): DEFAULTS['border-%s-%s' % (edge, x)] for x in ('style', 'width', 'color')} ans = {'border-%s-%s' % (edge, x): DEFAULTS['border-%s-%s' % (edge, x)] for x in ('style', 'width', 'color')}
for x, v in iteritems(expected): for x, v in expected.items():
ans['border-%s-%s' % (edge, x)] = v ans['border-%s-%s' % (edge, x)] = v
return ans return ans
@@ -312,39 +328,41 @@ def test_normalization(return_tests=False): # {{{
ans['border-%s-%s' % (edge, val)] = expected ans['border-%s-%s' % (edge, val)] = expected
return ans return ans
for raw, expected in iteritems({ for raw, expected in {'solid 1px red': {'color':'red',
'solid 1px red': {'color':'red', 'width':'1px', 'style':'solid'}, 'width':'1px',
'1px': {'width': '1px'}, '#aaa': {'color': '#aaa'}, 'style':'solid'},
'2em groove': {'width':'2em', 'style':'groove'}, '1px': {'width': '1px'},
}): '#aaa': {'color': '#aaa'},
'2em groove': {'width':'2em',
'style':'groove'}}.items():
for edge in EDGES: for edge in EDGES:
br = 'border-%s' % edge br = 'border-%s' % edge
val = tuple(parseStyle('%s: %s' % (br, raw), validate=False))[0].cssValue val = tuple(parseStyle('%s: %s' % (br, raw), validate=False))[0].cssValue
self.assertDictEqual(border_edge_dict(expected, edge), normalizers[br](br, val)) self.assertDictEqual(border_edge_dict(expected, edge), normalizers[br](br, val))
for raw, expected in iteritems({ for raw, expected in {'solid 1px red': {'color':'red',
'solid 1px red': {'color':'red', 'width':'1px', 'style':'solid'}, 'width':'1px',
'1px': {'width': '1px'}, '#aaa': {'color': '#aaa'}, 'style':'solid'},
'thin groove': {'width':'thin', 'style':'groove'}, '1px': {'width': '1px'},
}): '#aaa': {'color': '#aaa'},
'thin groove': {'width':'thin',
'style':'groove'}}.items():
val = tuple(parseStyle('%s: %s' % ('border', raw), validate=False))[0].cssValue val = tuple(parseStyle('%s: %s' % ('border', raw), validate=False))[0].cssValue
self.assertDictEqual(border_dict(expected), normalizers['border']('border', val)) self.assertDictEqual(border_dict(expected), normalizers['border']('border', val))
for name, val in iteritems({ for name, val in {'width': '10%',
'width': '10%', 'color': 'rgb(0, 1, 1)', 'style': 'double', 'color': 'rgb(0, 1, 1)',
}): 'style': 'double'}.items():
cval = tuple(parseStyle('border-%s: %s' % (name, val), validate=False))[0].cssValue cval = tuple(parseStyle('border-%s: %s' % (name, val), validate=False))[0].cssValue
self.assertDictEqual(border_val_dict(val, name), normalizers['border-'+name]('border-'+name, cval)) self.assertDictEqual(border_val_dict(val, name), normalizers['border-'+name]('border-'+name, cval))
def test_edge_normalization(self): def test_edge_normalization(self):
def edge_dict(prefix, expected): def edge_dict(prefix, expected):
return {'%s-%s' % (prefix, edge) : x for edge, x in zip(EDGES, expected)} return {'%s-%s' % (prefix, edge) : x for edge, x in zip(EDGES, expected)}
for raw, expected in iteritems({ for raw, expected in {'2px': ('2px', '2px', '2px', '2px'),
'2px': ('2px', '2px', '2px', '2px'),
'1em 2em': ('1em', '2em', '1em', '2em'), '1em 2em': ('1em', '2em', '1em', '2em'),
'1em 2em 3em': ('1em', '2em', '3em', '2em'), '1em 2em 3em': ('1em', '2em', '3em', '2em'),
'1 2 3 4': ('1', '2', '3', '4'), '1 2 3 4': ('1', '2', '3', '4')}.items():
}):
for prefix in ('margin', 'padding'): for prefix in ('margin', 'padding'):
cval = tuple(parseStyle('%s: %s' % (prefix, raw), validate=False))[0].cssValue cval = tuple(parseStyle('%s: %s' % (prefix, raw), validate=False))[0].cssValue
self.assertDictEqual(edge_dict(prefix, expected), normalizers[prefix](prefix, cval)) self.assertDictEqual(edge_dict(prefix, expected), normalizers[prefix](prefix, cval))
@@ -352,14 +370,13 @@ def test_normalization(return_tests=False): # {{{
def test_list_style_normalization(self): def test_list_style_normalization(self):
def ls_dict(expected): def ls_dict(expected):
ans = {'list-style-%s' % x : DEFAULTS['list-style-%s' % x] for x in ('type', 'image', 'position')} ans = {'list-style-%s' % x : DEFAULTS['list-style-%s' % x] for x in ('type', 'image', 'position')}
for k, v in iteritems(expected): for k, v in expected.items():
ans['list-style-%s' % k] = v ans['list-style-%s' % k] = v
return ans return ans
for raw, expected in iteritems({ for raw, expected in {'url(http://www.example.com/images/list.png)': {'image': 'url(http://www.example.com/images/list.png)'},
'url(http://www.example.com/images/list.png)': {'image': 'url(http://www.example.com/images/list.png)'},
'inside square': {'position':'inside', 'type':'square'}, 'inside square': {'position':'inside', 'type':'square'},
'upper-roman url(img) outside': {'position':'outside', 'type':'upper-roman', 'image':'url(img)'}, 'upper-roman url(img) outside': {'position':'outside', 'type':'upper-roman', 'image':'url(img)'},
}): }.items():
cval = tuple(parseStyle('list-style: %s' % raw, validate=False))[0].cssValue cval = tuple(parseStyle('list-style: %s' % raw, validate=False))[0].cssValue
self.assertDictEqual(ls_dict(expected), normalizers['list-style']('list-style', cval)) self.assertDictEqual(ls_dict(expected), normalizers['list-style']('list-style', cval))
@@ -379,20 +396,18 @@ def test_normalization(return_tests=False): # {{{
ae({'list-style', 'list-style-image', 'list-style-type', 'list-style-position'}, normalize_filter_css({'list-style'})) ae({'list-style', 'list-style-image', 'list-style-type', 'list-style-position'}, normalize_filter_css({'list-style'}))
def test_edge_condensation(self): def test_edge_condensation(self):
for s, v in iteritems({ for s, v in {(1, 1, 3) : None,
(1, 1, 3) : None,
(1, 2, 3, 4) : '2pt 3pt 4pt 1pt', (1, 2, 3, 4) : '2pt 3pt 4pt 1pt',
(1, 2, 3, 2) : '2pt 3pt 2pt 1pt', (1, 2, 3, 2) : '2pt 3pt 2pt 1pt',
(1, 2, 1, 3) : '2pt 1pt 3pt', (1, 2, 1, 3) : '2pt 1pt 3pt',
(1, 2, 1, 2) : '2pt 1pt', (1, 2, 1, 2) : '2pt 1pt',
(1, 1, 1, 1) : '1pt', (1, 1, 1, 1) : '1pt',
('2%', '2%', '2%', '2%') : '2%', ('2%', '2%', '2%', '2%') : '2%',
tuple('0 0 0 0'.split()) : '0', tuple('0 0 0 0'.split()) : '0'}.items():
}):
for prefix in ('margin', 'padding'): for prefix in ('margin', 'padding'):
css = {'%s-%s' % (prefix, x) : str(y)+'pt' if isinstance(y, numbers.Number) else y css = {'%s-%s' % (prefix, x) : str(y)+'pt' if isinstance(y, numbers.Number) else y
for x, y in zip(('left', 'top', 'right', 'bottom'), s)} for x, y in zip(('left', 'top', 'right', 'bottom'), s)}
css = '; '.join(('%s:%s' % (k, v) for k, v in iteritems(css))) css = '; '.join(('%s:%s' % (k, v) for k, v in css.items()))
style = parseStyle(css) style = parseStyle(css)
condense_rule(style) condense_rule(style)
val = getattr(style.getProperty(prefix), 'value', None) val = getattr(style.getProperty(prefix), 'value', None)
+3 -4
View File
@@ -6,7 +6,6 @@ from ebook_converter import xml_replace_entities, force_unicode
from ebook_converter.utils.xml_parse import safe_xml_fromstring from ebook_converter.utils.xml_parse import safe_xml_fromstring
from ebook_converter.constants import filesystem_encoding from ebook_converter.constants import filesystem_encoding
from ebook_converter.ebooks.chardet import xml_to_unicode, strip_encoding_declarations from ebook_converter.ebooks.chardet import xml_to_unicode, strip_encoding_declarations
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -136,8 +135,8 @@ def clean_word_doc(data, log):
def ensure_namespace_prefixes(node, nsmap): def ensure_namespace_prefixes(node, nsmap):
namespace_uris = frozenset(itervalues(nsmap)) namespace_uris = frozenset(nsmap.values())
fnsmap = {k:v for k, v in iteritems(node.nsmap) if v not in namespace_uris} fnsmap = {k:v for k, v in node.nsmap.items() if v not in namespace_uris}
fnsmap.update(nsmap) fnsmap.update(nsmap)
if fnsmap != dict(node.nsmap): if fnsmap != dict(node.nsmap):
node = clone_element(node, nsmap=fnsmap, in_context=False) node = clone_element(node, nsmap=fnsmap, in_context=False)
@@ -230,7 +229,7 @@ def parse_html(data, log=None, decoder=None, preprocessor=None,
for x in data.iterdescendants(): for x in data.iterdescendants():
try: try:
x.tag = x.tag.lower() x.tag = x.tag.lower()
for key, val in list(iteritems(x.attrib)): for key, val in tuple(x.attrib.items()):
del x.attrib[key] del x.attrib[key]
key = key.lower() key = key.lower()
x.attrib[key] = val x.attrib[key] = val
@@ -49,7 +49,6 @@ from ebook_converter.utils.ipc.simple_worker import WorkerError, fork_job
from ebook_converter.utils.logging import default_log from ebook_converter.utils.logging import default_log
from ebook_converter.utils.xml_parse import safe_xml_fromstring from ebook_converter.utils.xml_parse import safe_xml_fromstring
from ebook_converter.utils.zipfile import ZipFile from ebook_converter.utils.zipfile import ZipFile
from ebook_converter.polyglot.builtins import iteritems
exists, join, relpath = os.path.exists, os.path.join, os.path.relpath exists, join, relpath = os.path.exists, os.path.join, os.path.relpath
@@ -306,7 +305,7 @@ class Container(ContainerBase): # {{{
'tweak_mode': self.tweak_mode, 'tweak_mode': self.tweak_mode,
'name_path_map': { 'name_path_map': {
name:os.path.join(dest_dir, os.path.relpath(path, self.root)) name:os.path.join(dest_dir, os.path.relpath(path, self.root))
for name, path in iteritems(self.name_path_map)} for name, path in self.name_path_map.items()}
} }
def clone_data(self, dest_dir): def clone_data(self, dest_dir):
@@ -667,7 +666,7 @@ class Container(ContainerBase): # {{{
for item in self.opf_xpath('//opf:manifest/opf:item[@href and @media-type]'): for item in self.opf_xpath('//opf:manifest/opf:item[@href and @media-type]'):
ans[item.get('media-type').lower()].append(self.href_to_name( ans[item.get('media-type').lower()].append(self.href_to_name(
item.get('href'), self.opf_name)) item.get('href'), self.opf_name))
return {mt:tuple(v) for mt, v in iteritems(ans)} return {mt:tuple(v) for mt, v in ans.items()}
def manifest_items_with_property(self, property_name): def manifest_items_with_property(self, property_name):
' All manifest items that have the specified property ' ' All manifest items that have the specified property '
@@ -685,7 +684,7 @@ class Container(ContainerBase): # {{{
predicate = predicate.__eq__ predicate = predicate.__eq__
elif hasattr(predicate, '__contains__'): elif hasattr(predicate, '__contains__'):
predicate = predicate.__contains__ predicate = predicate.__contains__
for mt, names in iteritems(self.manifest_type_map): for mt, names in self.manifest_type_map.items():
if predicate(mt): if predicate(mt):
for name in names: for name in names:
yield name yield name
@@ -807,7 +806,7 @@ class Container(ContainerBase): # {{{
the form (name, linear). Will raise an error if one of the names is not the form (name, linear). Will raise an error if one of the names is not
present in the manifest. ''' present in the manifest. '''
imap = self.manifest_id_map imap = self.manifest_id_map
imap = {name:item_id for item_id, name in iteritems(imap)} imap = {name:item_id for item_id, name in imap.items()}
items = [item for item, name, linear in self.spine_iter] items = [item for item, name, linear in self.spine_iter]
tail, last_tail = (items[0].tail, items[-1].tail) if items else ('\n ', '\n ') tail, last_tail = (items[0].tail, items[-1].tail) if items else ('\n ', '\n ')
tuple(map(self.remove_from_xml, items)) tuple(map(self.remove_from_xml, items))
@@ -1071,7 +1070,7 @@ class Container(ContainerBase): # {{{
if set(self.name_path_map) != set(other.name_path_map): if set(self.name_path_map) != set(other.name_path_map):
return 'Set of files is not the same' return 'Set of files is not the same'
mismatches = [] mismatches = []
for name, path in iteritems(self.name_path_map): for name, path in self.name_path_map.items():
opath = other.name_path_map[name] opath = other.name_path_map[name]
with open(path, 'rb') as f1, open(opath, 'rb') as f2: with open(path, 'rb') as f1, open(opath, 'rb') as f2:
if f1.read() != f2.read(): if f1.read() != f2.read():
@@ -1275,7 +1274,7 @@ class EpubContainer(Container):
return return
package_id = raw_unique_identifier = idpf_key = None package_id = raw_unique_identifier = idpf_key = None
for attrib, val in iteritems(self.opf.attrib): for attrib, val in self.opf.attrib.items():
if attrib.endswith('unique-identifier'): if attrib.endswith('unique-identifier'):
package_id = val package_id = val
break break
@@ -1304,7 +1303,7 @@ class EpubContainer(Container):
self.log.exception('Failed to parse obfuscation key') self.log.exception('Failed to parse obfuscation key')
key = None key = None
for font, alg in iteritems(fonts): for font, alg in fonts.items():
tkey = key if alg == ADOBE_OBFUSCATION else idpf_key tkey = key if alg == ADOBE_OBFUSCATION else idpf_key
if not tkey: if not tkey:
raise ObfuscationKeyMissing('Failed to find obfuscation key') raise ObfuscationKeyMissing('Failed to find obfuscation key')
@@ -1374,7 +1373,7 @@ class EpubContainer(Container):
et = et.encode('ascii') et = et.encode('ascii')
f.write(et) f.write(et)
zip_rebuilder(self.root, outpath) zip_rebuilder(self.root, outpath)
for name, data in iteritems(restore_fonts): for name, data in restore_fonts.items():
with self.open(name, 'wb') as f: with self.open(name, 'wb') as f:
f.write(data) f.write(data)
+9 -10
View File
@@ -10,7 +10,6 @@ from ebook_converter.ebooks.oeb.normalize_css import normalize_filter_css, norma
from ebook_converter.ebooks.oeb.polish.pretty import pretty_script_or_style, pretty_xml_tree, serialize from ebook_converter.ebooks.oeb.polish.pretty import pretty_script_or_style, pretty_xml_tree, serialize
from ebook_converter.utils.icu import numeric_sort_key from ebook_converter.utils.icu import numeric_sort_key
from ebook_converter.css_selectors import Select, SelectorError from ebook_converter.css_selectors import Select, SelectorError
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -60,7 +59,7 @@ def merge_identical_selectors(sheet):
for rule in sheet.cssRules.rulesOfType(CSSRule.STYLE_RULE): for rule in sheet.cssRules.rulesOfType(CSSRule.STYLE_RULE):
selector_map[rule.selectorText].append(rule) selector_map[rule.selectorText].append(rule)
remove = [] remove = []
for rule_group in itervalues(selector_map): for rule_group in selector_map.values():
if len(rule_group) > 1: if len(rule_group) > 1:
for i in range(1, len(rule_group)): for i in range(1, len(rule_group)):
merge_declarations(rule_group[0].style, rule_group[i].style) merge_declarations(rule_group[0].style, rule_group[i].style)
@@ -85,23 +84,23 @@ def remove_unused_css(container, report=None, remove_unused_classes=False, merge
return container.parsed(name) return container.parsed(name)
except TypeError: except TypeError:
pass pass
sheets = {name:safe_parse(name) for name, mt in iteritems(container.mime_map) if mt in OEB_STYLES} sheets = {name:safe_parse(name) for name, mt in container.mime_map.items() if mt in OEB_STYLES}
sheets = {k:v for k, v in iteritems(sheets) if v is not None} sheets = {k:v for k, v in sheets.items() if v is not None}
num_merged = 0 num_merged = 0
if merge_rules: if merge_rules:
for name, sheet in iteritems(sheets): for name, sheet in sheets.items():
num = merge_identical_selectors(sheet) num = merge_identical_selectors(sheet)
if num: if num:
container.dirty(name) container.dirty(name)
num_merged += num num_merged += num
import_map = {name:get_imported_sheets(name, container, sheets) for name in sheets} import_map = {name:get_imported_sheets(name, container, sheets) for name in sheets}
if remove_unused_classes: if remove_unused_classes:
class_map = {name:{icu_lower(x) for x in classes_in_rule_list(sheet.cssRules)} for name, sheet in iteritems(sheets)} class_map = {name:{icu_lower(x) for x in classes_in_rule_list(sheet.cssRules)} for name, sheet in sheets.items()}
style_rules = {name:tuple(sheet.cssRules.rulesOfType(CSSRule.STYLE_RULE)) for name, sheet in iteritems(sheets)} style_rules = {name:tuple(sheet.cssRules.rulesOfType(CSSRule.STYLE_RULE)) for name, sheet in sheets.items()}
num_of_removed_rules = num_of_removed_classes = 0 num_of_removed_rules = num_of_removed_classes = 0
for name, mt in iteritems(container.mime_map): for name, mt in container.mime_map.items():
if mt not in OEB_DOCS: if mt not in OEB_DOCS:
continue continue
root = container.parsed(name) root = container.parsed(name)
@@ -158,7 +157,7 @@ def remove_unused_css(container, report=None, remove_unused_classes=False, merge
num_of_removed_classes += len(original_classes) - len(classes) num_of_removed_classes += len(original_classes) - len(classes)
container.dirty(name) container.dirty(name)
for name, sheet in iteritems(sheets): for name, sheet in sheets.items():
unused_rules = style_rules[name] unused_rules = style_rules[name]
if unused_rules: if unused_rules:
num_of_removed_rules += len(unused_rules) num_of_removed_rules += len(unused_rules)
@@ -245,7 +244,7 @@ def transform_css(container, transform_sheet=None, transform_style=None, names=(
if not names: if not names:
types = OEB_STYLES | OEB_DOCS types = OEB_STYLES | OEB_DOCS
names = [] names = []
for name, mt in iteritems(container.mime_map): for name, mt in container.mime_map.items():
if mt in types: if mt in types:
names.append(name) names.append(name)
+2 -3
View File
@@ -1,5 +1,4 @@
import textwrap import textwrap
from ebook_converter.polyglot.builtins import iteritems
# from lxml.etree import Element # from lxml.etree import Element
@@ -219,7 +218,7 @@ def pretty_xml(container, name, raw):
def fix_all_html(container): def fix_all_html(container):
' Fix any parsing errors in all HTML files in the container. Fixing is done using the HTML5 parsing algorithm. ' ' Fix any parsing errors in all HTML files in the container. Fixing is done using the HTML5 parsing algorithm. '
for name, mt in iteritems(container.mime_map): for name, mt in container.mime_map.items():
if mt in OEB_DOCS: if mt in OEB_DOCS:
container.parsed(name) container.parsed(name)
container.dirty(name) container.dirty(name)
@@ -228,7 +227,7 @@ def fix_all_html(container):
def pretty_all(container): def pretty_all(container):
' Pretty print all HTML/CSS/XML files in the container ' ' Pretty print all HTML/CSS/XML files in the container '
xml_types = {guess_type('a.ncx'), guess_type('a.xml'), guess_type('a.svg')} xml_types = {guess_type('a.ncx'), guess_type('a.xml'), guess_type('a.svg')}
for name, mt in iteritems(container.mime_map): for name, mt in container.mime_map.items():
prettied = False prettied = False
if mt in OEB_DOCS: if mt in OEB_DOCS:
pretty_html_tree(container, container.parsed(name)) pretty_html_tree(container, container.parsed(name))
+10 -11
View File
@@ -1,5 +1,4 @@
import codecs, shutil, os, posixpath import codecs, shutil, os, posixpath
from ebook_converter.polyglot.builtins import iteritems, itervalues
from functools import partial from functools import partial
from collections import Counter, defaultdict from collections import Counter, defaultdict
import urllib.parse import urllib.parse
@@ -115,7 +114,7 @@ def replace_links(container, link_map, frag_map=lambda name, frag:frag, replace_
:param replace_in_opf: If False, links are not replaced in the OPF file. :param replace_in_opf: If False, links are not replaced in the OPF file.
''' '''
for name, media_type in iteritems(container.mime_map): for name, media_type in container.mime_map.items():
if name == container.opf_name and not replace_in_opf: if name == container.opf_name and not replace_in_opf:
continue continue
repl = LinkReplacer(name, container, link_map, frag_map) repl = LinkReplacer(name, container, link_map, frag_map)
@@ -131,7 +130,7 @@ def replace_ids(container, id_map):
''' '''
changed = False changed = False
for name, media_type in iteritems(container.mime_map): for name, media_type in container.mime_map.items():
repl = IdReplacer(name, container, id_map) repl = IdReplacer(name, container, id_map)
container.replace_links(name, repl) container.replace_links(name, repl)
if name == container.opf_name: if name == container.opf_name:
@@ -183,19 +182,19 @@ def rename_files(container, file_map):
:param file_map: A mapping of old canonical name to new canonical name, for :param file_map: A mapping of old canonical name to new canonical name, for
example: :code:`{'text/chapter1.html': 'chapter1.html'}`. example: :code:`{'text/chapter1.html': 'chapter1.html'}`.
''' '''
overlap = set(file_map).intersection(set(itervalues(file_map))) overlap = set(file_map).intersection(set(file_map.values()))
if overlap: if overlap:
raise ValueError('Circular rename detected. The files %s are both rename targets and destinations' % ', '.join(overlap)) raise ValueError('Circular rename detected. The files %s are both rename targets and destinations' % ', '.join(overlap))
for name, dest in iteritems(file_map): for name, dest in file_map.items():
if container.exists(dest): if container.exists(dest):
if name != dest and name.lower() == dest.lower(): if name != dest and name.lower() == dest.lower():
# A case change on an OS with a case insensitive file-system. # A case change on an OS with a case insensitive file-system.
continue continue
raise ValueError('Cannot rename {0} to {1} as {1} already exists'.format(name, dest)) raise ValueError('Cannot rename {0} to {1} as {1} already exists'.format(name, dest))
if len(tuple(itervalues(file_map))) != len(set(itervalues(file_map))): if len(file_map.values()) != len(set(file_map.values())):
raise ValueError('Cannot rename, the set of destination files contains duplicates') raise ValueError('Cannot rename, the set of destination files contains duplicates')
link_map = {} link_map = {}
for current_name, new_name in iteritems(file_map): for current_name, new_name in file_map.items():
container.rename(current_name, new_name) container.rename(current_name, new_name)
if new_name != container.opf_name: # OPF is handled by the container if new_name != container.opf_name: # OPF is handled by the container
link_map[current_name] = new_name link_map[current_name] = new_name
@@ -217,7 +216,7 @@ def replace_file(container, name, path, basename, force_mt=None):
rename_files(container, {name:nname}) rename_files(container, {name:nname})
mt = force_mt or container.guess_type(nname) mt = force_mt or container.guess_type(nname)
container.mime_map[nname] = mt container.mime_map[nname] = mt
for itemid, q in iteritems(container.manifest_id_map): for itemid, q in container.manifest_id_map.items():
if q == nname: if q == nname:
for item in container.opf_xpath('//opf:manifest/opf:item[@href and @id="%s"]' % itemid): for item in container.opf_xpath('//opf:manifest/opf:item[@href and @id="%s"]' % itemid):
item.set('media-type', mt) item.set('media-type', mt)
@@ -252,7 +251,7 @@ def get_recommended_folders(container, names):
recommended folder is assumed to be the folder containing the OPF file. ''' recommended folder is assumed to be the folder containing the OPF file. '''
from ebook_converter.ebooks.oeb.polish.utils import guess_type from ebook_converter.ebooks.oeb.polish.utils import guess_type
counts = defaultdict(Counter) counts = defaultdict(Counter)
for name, mt in iteritems(container.mime_map): for name, mt in container.mime_map.items():
folder = name.rpartition('/')[0] if '/' in name else '' folder = name.rpartition('/')[0] if '/' in name else ''
counts[mt_to_category(container, mt)][folder] += 1 counts[mt_to_category(container, mt)][folder] += 1
@@ -261,7 +260,7 @@ def get_recommended_folders(container, names):
except KeyError: except KeyError:
opf_folder = '' opf_folder = ''
recommendations = {category:counter.most_common(1)[0][0] for category, counter in iteritems(counts)} recommendations = {category:counter.most_common(1)[0][0] for category, counter in counts.items()}
return {n:recommendations.get(mt_to_category(container, guess_type(os.path.basename(n))), opf_folder) for n in names} return {n:recommendations.get(mt_to_category(container, guess_type(os.path.basename(n))), opf_folder) for n in names}
@@ -348,7 +347,7 @@ def remove_links_to(container, predicate):
stylepath = XPath('//h:style') stylepath = XPath('//h:style')
styleattrpath = XPath('//*[@style]') styleattrpath = XPath('//*[@style]')
changed = set() changed = set()
for name, mt in iteritems(container.mime_map): for name, mt in container.mime_map.items():
removed = False removed = False
if mt in OEB_DOCS: if mt in OEB_DOCS:
root = container.parsed(name) root = container.parsed(name)
+3 -4
View File
@@ -5,7 +5,6 @@ from ebook_converter.ebooks.oeb.base import barename, XPNSMAP, XPath, OPF, XHTML
from ebook_converter.ebooks.oeb.polish.errors import MalformedMarkup from ebook_converter.ebooks.oeb.polish.errors import MalformedMarkup
from ebook_converter.ebooks.oeb.polish.toc import node_from_loc from ebook_converter.ebooks.oeb.polish.toc import node_from_loc
from ebook_converter.ebooks.oeb.polish.replace import LinkRebaser from ebook_converter.ebooks.oeb.polish.replace import LinkRebaser
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -237,7 +236,7 @@ def split(container, name, loc_or_xpath, before=True, totals=None):
a.set('href', '#' + purl.fragment) a.set('href', '#' + purl.fragment)
# Fix all links in the container that point to anchors in the bottom tree # Fix all links in the container that point to anchors in the bottom tree
for fname, media_type in iteritems(container.mime_map): for fname, media_type in container.mime_map.items():
if fname not in {name, bottom_name}: if fname not in {name, bottom_name}:
repl = SplitLinkReplacer(fname, anchors_in_bottom, name, bottom_name, container) repl = SplitLinkReplacer(fname, anchors_in_bottom, name, bottom_name, container)
container.replace_links(fname, repl) container.replace_links(fname, repl)
@@ -438,7 +437,7 @@ def merge_html(container, names, master, insert_page_breaks=False):
container.remove_item(name, remove_from_guide=False) container.remove_item(name, remove_from_guide=False)
# Fix all links in the container that point to merged files # Fix all links in the container that point to merged files
for fname, media_type in iteritems(container.mime_map): for fname, media_type in container.mime_map.items():
repl = MergeLinkReplacer(fname, anchor_map, master, container) repl = MergeLinkReplacer(fname, anchor_map, master, container)
container.replace_links(fname, repl) container.replace_links(fname, repl)
@@ -471,7 +470,7 @@ def merge_css(container, names, master):
# Remove links to merged stylesheets in the html files, replacing with a # Remove links to merged stylesheets in the html files, replacing with a
# link to the master sheet # link to the master sheet
for name, mt in iteritems(container.mime_map): for name, mt in container.mime_map.items():
if mt in OEB_DOCS: if mt in OEB_DOCS:
removed = False removed = False
root = p(name) root = p(name)
+7 -8
View File
@@ -16,7 +16,6 @@ from ebook_converter.ebooks.oeb.polish.utils import guess_type, extract
from ebook_converter.ebooks.oeb.polish.opf import set_guide_item, get_book_language from ebook_converter.ebooks.oeb.polish.opf import set_guide_item, get_book_language
from ebook_converter.ebooks.oeb.polish.pretty import pretty_html_tree from ebook_converter.ebooks.oeb.polish.pretty import pretty_html_tree
from ebook_converter.utils.localization import get_lang, canonicalize_lang, lang_as_iso639_1 from ebook_converter.utils.localization import get_lang, canonicalize_lang, lang_as_iso639_1
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -168,7 +167,7 @@ def parse_ncx(container, ncx_name):
if navmaps: if navmaps:
process_ncx_node(container, navmaps[0], toc_root, ncx_name) process_ncx_node(container, navmaps[0], toc_root, ncx_name)
toc_root.lang = toc_root.uid = None toc_root.lang = toc_root.uid = None
for attr, val in iteritems(root.attrib): for attr, val in root.attrib.items():
if attr.endswith('lang'): if attr.endswith('lang'):
toc_root.lang = str(val) toc_root.lang = str(val)
break break
@@ -415,14 +414,14 @@ def from_xpaths(container, xpaths):
name = container.abspath_to_name(spinepath) name = container.abspath_to_name(spinepath)
root = container.parsed(name) root = container.parsed(name)
level_item_map = maps[name] = {i+1:frozenset(xp(root)) for i, xp in enumerate(xpaths)} level_item_map = maps[name] = {i+1:frozenset(xp(root)) for i, xp in enumerate(xpaths)}
for lvl, elems in iteritems(level_item_map): for lvl, elems in level_item_map.items():
if elems: if elems:
empty_levels.discard(lvl) empty_levels.discard(lvl)
# Remove empty levels from all level_maps # Remove empty levels from all level_maps
if empty_levels: if empty_levels:
for name, lmap in tuple(iteritems(maps)): for name, lmap in tuple(maps.items()):
lmap = {lvl:items for lvl, items in iteritems(lmap) if lvl not in empty_levels} lmap = {lvl:items for lvl, items in lmap.items() if lvl not in empty_levels}
lmap = sorted(iteritems(lmap), key=itemgetter(0)) lmap = sorted(lmap.items(), key=itemgetter(0))
lmap = {i+1:items for i, (l, items) in enumerate(lmap)} lmap = {i+1:items for i, (l, items) in enumerate(lmap)}
maps[name] = lmap maps[name] = lmap
@@ -440,9 +439,9 @@ def from_xpaths(container, xpaths):
return process_node(tocroot) return process_node(tocroot)
for name, level_item_map in iteritems(maps): for name, level_item_map in maps.items():
root = container.parsed(name) root = container.parsed(name)
item_level_map = {e:i for i, elems in iteritems(level_item_map) for e in elems} item_level_map = {e:i for i, elems in level_item_map.items() for e in elems}
item_dirtied = False item_dirtied = False
all_ids = set(root.xpath('//*/@id')) all_ids = set(root.xpath('//*/@id'))
+3 -4
View File
@@ -15,7 +15,6 @@ from ebook_converter.ebooks import unit_convert
from ebook_converter.ebooks.oeb.base import XHTML, XHTML_NS, CSS_MIME, OEB_STYLES, xpath, urlnormalize from ebook_converter.ebooks.oeb.base import XHTML, XHTML_NS, CSS_MIME, OEB_STYLES, xpath, urlnormalize
from ebook_converter.ebooks.oeb.normalize_css import DEFAULTS, normalizers from ebook_converter.ebooks.oeb.normalize_css import DEFAULTS, normalizers
from ebook_converter.css_selectors import Select, SelectorError, INAPPROPRIATE_PSEUDO_CLASSES from ebook_converter.css_selectors import Select, SelectorError, INAPPROPRIATE_PSEUDO_CLASSES
from ebook_converter.polyglot.builtins import iteritems
from ebook_converter.tinycss.media3 import CSSMedia3Parser from ebook_converter.tinycss.media3 import CSSMedia3Parser
@@ -785,7 +784,7 @@ class Style(object):
self._get('padding-right'), base=self.parent_width) self._get('padding-right'), base=self.parent_width)
def __str__(self): def __str__(self):
items = sorted(iteritems(self._style)) items = sorted(self._style.items())
return '; '.join("%s: %s" % (key, val) for key, val in items) return '; '.join("%s: %s" % (key, val) for key, val in items)
def cssdict(self): def cssdict(self):
@@ -794,12 +793,12 @@ class Style(object):
def pseudo_classes(self, filter_css): def pseudo_classes(self, filter_css):
if filter_css: if filter_css:
css = copy.deepcopy(self._pseudo_classes) css = copy.deepcopy(self._pseudo_classes)
for psel, cssdict in iteritems(css): for psel, cssdict in css.items():
for k in filter_css: for k in filter_css:
cssdict.pop(k, None) cssdict.pop(k, None)
else: else:
css = self._pseudo_classes css = self._pseudo_classes
return {k:v for k, v in iteritems(css) if v} return {k:v for k, v in css.items() if v}
@property @property
def is_hidden(self): def is_hidden(self):
@@ -16,7 +16,6 @@ from ebook_converter.ebooks.oeb.base import (XHTML, XHTML_NS, CSS_MIME, OEB_STYL
from ebook_converter.ebooks.oeb.stylizer import Stylizer from ebook_converter.ebooks.oeb.stylizer import Stylizer
from ebook_converter.utils.filenames import ascii_filename, ascii_text from ebook_converter.utils.filenames import ascii_filename, ascii_text
from ebook_converter.utils.icu import numeric_sort_key from ebook_converter.utils.icu import numeric_sort_key
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -208,7 +207,7 @@ class CSSFlattener(object):
def store_page_margins(self): def store_page_margins(self):
self.opts._stored_page_margins = {} self.opts._stored_page_margins = {}
for item, stylizer in iteritems(self.stylizers): for item, stylizer in self.stylizers.items():
margins = self.opts._stored_page_margins[item.href] = {} margins = self.opts._stored_page_margins[item.href] = {}
for prop, val in stylizer.page_rule.items(): for prop, val in stylizer.page_rule.items():
p, w = prop.partition('-')[::2] p, w = prop.partition('-')[::2]
@@ -262,7 +261,7 @@ class CSSFlattener(object):
if font[k] != 'normal': if font[k] != 'normal':
cfont[k] = font[k] cfont[k] = font[k]
rule = '@font-face { %s }'%('; '.join('%s:%s'%(k, v) for k, v in rule = '@font-face { %s }'%('; '.join('%s:%s'%(k, v) for k, v in
iteritems(cfont))) cfont.items()))
rule = css_parser.parseString(rule) rule = css_parser.parseString(rule)
efi.append(rule) efi.append(rule)
@@ -527,7 +526,7 @@ class CSSFlattener(object):
keep_classes = set() keep_classes = set()
if cssdict: if cssdict:
items = sorted(iteritems(cssdict)) items = sorted(cssdict.items())
css = ';\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 = node.get('class', '').strip() or 'calibre'
classes_list = classes.split() classes_list = classes.split()
@@ -544,8 +543,8 @@ class CSSFlattener(object):
node.attrib['class'] = match node.attrib['class'] = match
keep_classes.add(match) keep_classes.add(match)
for psel, cssdict in iteritems(pseudo_classes): for psel, cssdict in pseudo_classes.items():
items = sorted(iteritems(cssdict)) items = sorted(cssdict.items())
css = ';\n'.join('%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] pstyles = pseudo_styles[psel]
if css in pstyles: if css in pstyles:
@@ -647,7 +646,7 @@ class CSSFlattener(object):
gc_map[css] = href gc_map[css] = href
ans = {} ans = {}
for css, items in iteritems(global_css): for css, items in global_css.items():
for item in items: for item in items:
ans[item] = gc_map[css] ans[item] = gc_map[css]
return ans return ans
@@ -663,7 +662,7 @@ class CSSFlattener(object):
fsize = self.context.dest.fbase fsize = self.context.dest.fbase
self.flatten_node(html, stylizer, names, styles, pseudo_styles, fsize, item.id, recurse=False) self.flatten_node(html, stylizer, names, styles, pseudo_styles, fsize, item.id, recurse=False)
self.flatten_node(html.find(XHTML('body')), stylizer, names, styles, pseudo_styles, fsize, item.id) self.flatten_node(html.find(XHTML('body')), stylizer, names, styles, pseudo_styles, fsize, item.id)
items = sorted(((key, val) for (val, key) in iteritems(styles))) items = sorted(((key, val) for (val, key) in styles.items()))
# :hover must come after link and :active must come after :hover # :hover must come after link and :active must come after :hover
psels = sorted(pseudo_styles, key=lambda x : psels = sorted(pseudo_styles, key=lambda x :
{'hover':1, 'active':2}.get(x, 0)) {'hover':1, 'active':2}.get(x, 0))
@@ -671,7 +670,7 @@ class CSSFlattener(object):
styles = pseudo_styles[psel] styles = pseudo_styles[psel]
if not styles: if not styles:
continue continue
x = sorted(((k+':'+psel, v) for v, k in iteritems(styles))) x = sorted(((k+':'+psel, v) for v, k in styles.items()))
items.extend(x) items.extend(x)
css = ''.join(".%s {\n%s;\n}\n\n" % (key, val) for key, val in items) css = ''.join(".%s {\n%s;\n}\n\n" % (key, val) for key, val in items)
@@ -1,7 +1,6 @@
import os, re import os, re
from ebook_converter.utils.date import isoformat, now from ebook_converter.utils.date import isoformat, now
from ebook_converter import guess_type from ebook_converter import guess_type
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -48,7 +47,7 @@ def meta_info_to_oeb_metadata(mi, m, log, override_input_metadata=False):
m.clear('series') m.clear('series')
identifiers = mi.get_identifiers() identifiers = mi.get_identifiers()
set_isbn = False set_isbn = False
for typ, val in iteritems(identifiers): for typ, val in identifiers.items():
has = False has = False
if typ.lower() == 'isbn': if typ.lower() == 'isbn':
set_isbn = True set_isbn = True
@@ -2,7 +2,6 @@ import numbers
from collections import Counter from collections import Counter
from ebook_converter.ebooks.oeb.base import barename, XPath from ebook_converter.ebooks.oeb.base import barename, XPath
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -149,7 +148,7 @@ class RemoveFakeMargins(object):
self.levels[level].append(p) self.levels[level].append(p)
remove = set() remove = set()
for k, v in iteritems(self.levels): for k, v in self.levels.items():
num = len(v) num = len(v)
self.log.debug('Found %d items of level:'%num, k) self.log.debug('Found %d items of level:'%num, k)
level = int(k.split('_')[-1]) level = int(k.split('_')[-1])
@@ -15,7 +15,6 @@ from ebook_converter.ebooks.epub import rules
from ebook_converter.ebooks.oeb.base import (OEB_STYLES, XPNSMAP as NAMESPACES, from ebook_converter.ebooks.oeb.base import (OEB_STYLES, XPNSMAP as NAMESPACES,
rewrite_links, XHTML, urlnormalize) rewrite_links, XHTML, urlnormalize)
from ebook_converter.ebooks.oeb.polish.split import do_split from ebook_converter.ebooks.oeb.polish.split import do_split
from ebook_converter.polyglot.builtins import iteritems
from ebook_converter.polyglot.urllib import unquote from ebook_converter.polyglot.urllib import unquote
from ebook_converter.css_selectors import Select, SelectorError from ebook_converter.css_selectors import Select, SelectorError
@@ -243,7 +242,7 @@ class FlowSplitter(object):
self.trees = [orig_tree] self.trees = [orig_tree]
while ordered_ids: while ordered_ids:
pb_id, (pattern, before) = next(iteritems(ordered_ids)) pb_id, (pattern, before) = next(iter(ordered_ids.items()))
del ordered_ids[pb_id] del ordered_ids[pb_id]
for i in range(len(self.trees)-1, -1, -1): for i in range(len(self.trees)-1, -1, -1):
tree = self.trees[i] tree = self.trees[i]
@@ -7,7 +7,6 @@ from collections import OrderedDict, Counter
from ebook_converter.ebooks.oeb.base import XPNSMAP, TOC, XHTML, xml2text, barename from ebook_converter.ebooks.oeb.base import XPNSMAP, TOC, XHTML, xml2text, barename
from ebook_converter.ebooks import ConversionError from ebook_converter.ebooks import ConversionError
from ebook_converter.polyglot.builtins import itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -269,8 +268,8 @@ class DetectStructure(object):
return [] return []
for document in self.oeb.spine: for document in self.oeb.spine:
previous_level1 = list(itervalues(added))[-1] if added else None previous_level1 = list(added.values())[-1] if added else None
previous_level2 = list(itervalues(added2))[-1] if added2 else None previous_level2 = list(added2.values())[-1] if added2 else None
level1_toc, level1_title = self.get_toc_parts_for_xpath(self.opts.level1_toc) level1_toc, level1_title = self.get_toc_parts_for_xpath(self.opts.level1_toc)
for elem in find_matches(level1_toc, document.data): for elem in find_matches(level1_toc, document.data):
@@ -2,7 +2,6 @@ from collections import defaultdict
from ebook_converter.ebooks.oeb.base import urlnormalize, css_text from ebook_converter.ebooks.oeb.base import urlnormalize, css_text
from ebook_converter.utils.fonts.sfnt.subset import subset, NoGlyphs, UnsupportedFont from ebook_converter.utils.fonts.sfnt.subset import subset, NoGlyphs, UnsupportedFont
from ebook_converter.polyglot.builtins import iteritems, itervalues
from ebook_converter.tinycss.fonts3 import parse_font_family from ebook_converter.tinycss.fonts3 import parse_font_family
@@ -148,7 +147,7 @@ class SubsetFonts(object):
else: else:
fonts[item.href] = font fonts[item.href] = font
for font in itervalues(fonts): for font in fonts.values():
if not font['chars']: if not font['chars']:
self.log('The font %s is unused. Removing it.'%font['src']) self.log('The font %s is unused. Removing it.'%font['src'])
remove(font) remove(font)
@@ -167,8 +166,8 @@ class SubsetFonts(object):
totals[1] += sz totals[1] += sz
else: else:
font['item'].data = raw font['item'].data = raw
nlen = sum(itervalues(new_stats)) nlen = sum(new_stats.values())
olen = sum(itervalues(old_stats)) olen = sum(old_stats.values())
self.log('Decreased the font %s to %.1f%% of its original size'% self.log('Decreased the font %s to %.1f%% of its original size'%
(font['src'], nlen/olen *100)) (font['src'], nlen/olen *100))
totals[0] += nlen totals[0] += nlen
@@ -204,7 +203,7 @@ class SubsetFonts(object):
if rule.type != rule.STYLE_RULE: if rule.type != rule.STYLE_RULE:
continue continue
props = {k:v for k,v in props = {k:v for k,v in
iteritems(get_font_properties(rule)) if v} get_font_properties(rule).items() if v}
if not props: if not props:
continue continue
for sel in rule.selectorList: for sel in rule.selectorList:
+1 -2
View File
@@ -4,7 +4,6 @@ from datetime import datetime
from ebook_converter.constants import ispy3 from ebook_converter.constants import ispy3
from ebook_converter.utils.logging import default_log from ebook_converter.utils.logging import default_log
from ebook_converter.polyglot.builtins import iteritems
from ebook_converter.polyglot.binary import as_hex_bytes from ebook_converter.polyglot.binary import as_hex_bytes
@@ -160,7 +159,7 @@ class InlineDictionary(Dictionary):
def pdf_serialize(self, stream): def pdf_serialize(self, stream):
stream.write(b'<< ') stream.write(b'<< ')
for k, v in iteritems(self): for k, v in self.items():
serialize(Name(k), stream) serialize(Name(k), stream)
stream.write(b' ') stream.write(b' ')
serialize(v, stream) serialize(v, stream)
@@ -15,7 +15,6 @@ import sys, os
from ebook_converter.ebooks.rtf2xml import copy, check_brackets from ebook_converter.ebooks.rtf2xml import copy, check_brackets
from ebook_converter.ptempfile import better_mktemp from ebook_converter.ptempfile import better_mktemp
from ebook_converter.polyglot.builtins import iteritems
from . import open_for_read, open_for_write from . import open_for_read, open_for_write
@@ -163,7 +162,7 @@ class AddBrackets:
self.__open_bracket = False self.__open_bracket = False
inline_string = ''.join(['%s<nu<%s\n' % (k, v) inline_string = ''.join(['%s<nu<%s\n' % (k, v)
for k, v in iteritems(self.__inline) for k, v in self.__inline.items()
if v != 'false']) if v != 'false'])
if inline_string: if inline_string:
self.__write_obj.write('ob<nu<open-brack<0003\n' self.__write_obj.write('ob<nu<open-brack<0003\n'
+1 -2
View File
@@ -8,7 +8,6 @@ from ebook_converter.ebooks.metadata.opf2 import OPFCreator
from ebook_converter.ebooks.conversion.preprocess import DocAnalysis from ebook_converter.ebooks.conversion.preprocess import DocAnalysis
from ebook_converter.utils.cleantext import clean_ascii_chars from ebook_converter.utils.cleantext import clean_ascii_chars
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -145,7 +144,7 @@ def convert_markdown_with_metadata(txt, title='', extensions=DEFAULT_MD_EXTENSIO
html = md.convert(txt) html = md.convert(txt)
mi = Metadata(title or _('Unknown')) mi = Metadata(title or _('Unknown'))
m = md.Meta m = md.Meta
for k, v in iteritems({'date':'pubdate', 'summary':'comments'}): for k, v in {'date':'pubdate', 'summary':'comments'}.items():
if v not in m and k in m: if v not in m and k in m:
m[v] = m.pop(k) m[v] = m.pop(k)
for k in 'title authors series tags pubdate comments publisher rating'.split(): for k in 'title authors series tags pubdate comments publisher rating'.split():
+5 -6
View File
@@ -7,7 +7,6 @@ import traceback
from collections import OrderedDict from collections import OrderedDict
from ebook_converter.utils.config_base import tweaks from ebook_converter.utils.config_base import tweaks
from ebook_converter.polyglot.builtins import iteritems, itervalues
category_icon_map = { category_icon_map = {
'authors' : 'user_profile.png', 'authors' : 'user_profile.png',
@@ -485,7 +484,7 @@ class FieldMetadata(object):
yield key yield key
def itervalues(self): def itervalues(self):
return itervalues(self._tb_cats) return self._tb_cats.values()
def values(self): def values(self):
return list(self._tb_cats.values()) return list(self._tb_cats.values())
@@ -496,7 +495,7 @@ class FieldMetadata(object):
iter_items = iteritems iter_items = iteritems
def custom_iteritems(self): def custom_iteritems(self):
for key, meta in iteritems(self._tb_custom_fields): for key, meta in self._tb_custom_fields.items():
yield (key, meta) yield (key, meta)
def items(self): def items(self):
@@ -683,8 +682,8 @@ def fm_as_dict(self):
'custom_fields': self._tb_custom_fields, 'custom_fields': self._tb_custom_fields,
'search_term_map': self._search_term_map, 'search_term_map': self._search_term_map,
'custom_label_to_key_map': self.custom_label_to_key_map, 'custom_label_to_key_map': self.custom_label_to_key_map,
'user_categories': {k:v for k, v in iteritems(self._tb_cats) if v['kind'] == 'user'}, 'user_categories': {k:v for k, v in self._tb_cats.items() if v['kind'] == 'user'},
'search_categories': {k:v for k, v in iteritems(self._tb_cats) if v['kind'] == 'search'}, 'search_categories': {k:v for k, v in self._tb_cats.items() if v['kind'] == 'search'},
} }
@@ -694,6 +693,6 @@ def fm_from_dict(src):
ans._search_term_map = src['search_term_map'] ans._search_term_map = src['search_term_map']
ans.custom_label_to_key_map = src['custom_label_to_key_map'] ans.custom_label_to_key_map = src['custom_label_to_key_map']
for q in ('custom_fields', 'user_categories', 'search_categories'): for q in ('custom_fields', 'user_categories', 'search_categories'):
for k, v in iteritems(src[q]): for k, v in src[q].items():
ans._tb_cats[k] = v ans._tb_cats[k] = v
return ans return ans
-8
View File
@@ -47,14 +47,6 @@ def error_message(exc):
return str(exc) return str(exc)
def iteritems(d):
return iter(d.items())
def itervalues(d):
return iter(d.values())
def environ_item(x): def environ_item(x):
if isinstance(x, bytes): if isinstance(x, bytes):
x = x.decode('utf-8') x = x.decode('utf-8')
+3 -7
View File
@@ -1,8 +1,6 @@
from tinycss.fonts3 import CSSFonts3Parser, parse_font_family, parse_font, serialize_font from tinycss.fonts3 import CSSFonts3Parser, parse_font_family, parse_font, serialize_font
from tinycss.tests import BaseTest from tinycss.tests import BaseTest
from polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2014, Kovid Goyal <kovid at kovidgoyal.net>'
@@ -29,8 +27,7 @@ class TestFonts3(BaseTest):
def test_parse_font_family(self): def test_parse_font_family(self):
' Test parsing of font-family values ' ' Test parsing of font-family values '
for raw, q in iteritems({ for raw, q in {'"1as"': ['1as'],
'"1as"': ['1as'],
'A B C, serif': ['A B C', 'serif'], 'A B C, serif': ['A B C', 'serif'],
r'Red\/Black': ['Red/Black'], r'Red\/Black': ['Red/Black'],
'A B': ['A B'], 'A B': ['A B'],
@@ -41,15 +38,14 @@ class TestFonts3(BaseTest):
r'"X \"Y"': ['X "Y'], r'"X \"Y"': ['X "Y'],
'A B, C D, "E", serif': ['A B', 'C D', 'E', 'serif'], 'A B, C D, "E", serif': ['A B', 'C D', 'E', 'serif'],
'': [], '': [],
'"", a': ['a'], '"", a': ['a']}.items():
}):
self.ae(q, parse_font_family(raw)) self.ae(q, parse_font_family(raw))
for single in ('serif', 'sans-serif', 'A B C'): for single in ('serif', 'sans-serif', 'A B C'):
self.ae([single], parse_font_family(single)) self.ae([single], parse_font_family(single))
def test_parse_font(self): def test_parse_font(self):
def t(raw, **kw): def t(raw, **kw):
q = {('line' if k == 'height' else 'font') + '-' + k:v for k, v in iteritems(kw)} q = {('line' if k == 'height' else 'font') + '-' + k:v for k, v in kw.items()}
self.ae(q, parse_font(raw)) self.ae(q, parse_font(raw))
self.ae(q, parse_font(serialize_font(q))) self.ae(q, parse_font(serialize_font(q)))
t('caption', family=['sans-serif']) t('caption', family=['sans-serif'])
+4 -5
View File
@@ -10,7 +10,6 @@ import pkg_resources
from ebook_converter.utils.lock import ExclusiveFile from ebook_converter.utils.lock import ExclusiveFile
from ebook_converter.constants import config_dir, CONFIG_DIR_MODE, ispy3, preferred_encoding, filesystem_encoding, iswindows from ebook_converter.constants import config_dir, CONFIG_DIR_MODE, ispy3, preferred_encoding, filesystem_encoding, iswindows
from ebook_converter.polyglot.builtins import iteritems
plugin_dir = os.path.join(config_dir, 'plugins') plugin_dir = os.path.join(config_dir, 'plugins')
@@ -92,7 +91,7 @@ def force_unicode_recursive(obj):
if isinstance(obj, (list, tuple)): if isinstance(obj, (list, tuple)):
return type(obj)(map(force_unicode_recursive, obj)) return type(obj)(map(force_unicode_recursive, obj))
if isinstance(obj, dict): if isinstance(obj, dict):
return {force_unicode_recursive(k): force_unicode_recursive(v) for k, v in iteritems(obj)} return {force_unicode_recursive(k): force_unicode_recursive(v) for k, v in obj.items()}
return obj return obj
@@ -569,7 +568,7 @@ def make_unicode(obj):
if isinstance(obj, (list, tuple)): if isinstance(obj, (list, tuple)):
return list(map(make_unicode, obj)) return list(map(make_unicode, obj))
if isinstance(obj, dict): if isinstance(obj, dict):
return {make_unicode(k): make_unicode(v) for k, v in iteritems(obj)} return {make_unicode(k): make_unicode(v) for k, v in obj.items()}
return obj return obj
@@ -577,7 +576,7 @@ def normalize_tweak(val):
if isinstance(val, (list, tuple)): if isinstance(val, (list, tuple)):
return tuple(map(normalize_tweak, val)) return tuple(map(normalize_tweak, val))
if isinstance(val, dict): if isinstance(val, dict):
return {k: normalize_tweak(v) for k, v in iteritems(val)} return {k: normalize_tweak(v) for k, v in val.items()}
return val return val
@@ -586,7 +585,7 @@ def write_custom_tweaks(tweaks_dict):
tweaks_dict = make_unicode(tweaks_dict) tweaks_dict = make_unicode(tweaks_dict)
changed_tweaks = {} changed_tweaks = {}
default_tweaks = exec_tweaks(default_tweaks_raw()) default_tweaks = exec_tweaks(default_tweaks_raw())
for key, cval in iteritems(tweaks_dict): for key, cval in tweaks_dict.items():
if key in default_tweaks and normalize_tweak(cval) == normalize_tweak(default_tweaks[key]): if key in default_tweaks and normalize_tweak(cval) == normalize_tweak(default_tweaks[key]):
continue continue
changed_tweaks[key] = cval changed_tweaks[key] = cval
+5 -6
View File
@@ -13,7 +13,6 @@ from ebook_converter.constants import (
filesystem_encoding, iswindows, plugins, preferred_encoding, isosx, ispy3 filesystem_encoding, iswindows, plugins, preferred_encoding, isosx, ispy3
) )
from ebook_converter.utils.localization import get_udc from ebook_converter.utils.localization import get_udc
from ebook_converter.polyglot.builtins import iteritems, itervalues
def ascii_text(orig): def ascii_text(orig):
@@ -367,7 +366,7 @@ class WindowsAtomicFolderMove(object):
names = os.listdir(path) names = os.listdir(path)
name_to_fileid = {x:windows_get_fileid(os.path.join(path, x)) for x in names} name_to_fileid = {x:windows_get_fileid(os.path.join(path, x)) for x in names}
fileid_to_names = defaultdict(set) fileid_to_names = defaultdict(set)
for name, fileid in iteritems(name_to_fileid): for name, fileid in name_to_fileid.items():
fileid_to_names[fileid].add(name) fileid_to_names[fileid].add(name)
for x in names: for x in names:
@@ -417,7 +416,7 @@ class WindowsAtomicFolderMove(object):
def copy_path_to(self, path, dest): def copy_path_to(self, path, dest):
import win32file import win32file
handle = None handle = None
for p, h in iteritems(self.handle_map): for p, h in self.handle_map.items():
if samefile_windows(path, p): if samefile_windows(path, p):
handle = h handle = h
break break
@@ -446,20 +445,20 @@ class WindowsAtomicFolderMove(object):
def release_file(self, path): def release_file(self, path):
' Release the lock on the file pointed to by path. Will also release the lock on any hardlinks to path ' ' Release the lock on the file pointed to by path. Will also release the lock on any hardlinks to path '
key = None key = None
for p, h in iteritems(self.handle_map): for p, h in self.handle_map.items():
if samefile_windows(path, p): if samefile_windows(path, p):
key = (p, h) key = (p, h)
break break
if key is not None: if key is not None:
import win32file import win32file
win32file.CloseHandle(key[1]) win32file.CloseHandle(key[1])
remove = [f for f, h in iteritems(self.handle_map) if h is key[1]] remove = [f for f, h in self.handle_map.items() if h is key[1]]
for x in remove: for x in remove:
self.handle_map.pop(x) self.handle_map.pop(x)
def close_handles(self): def close_handles(self):
import win32file import win32file
for h in itervalues(self.handle_map): for h in self.handle_map.values():
win32file.CloseHandle(h) win32file.CloseHandle(h)
self.handle_map = {} self.handle_map = {}
+3 -4
View File
@@ -6,7 +6,6 @@ from ebook_converter import walk, prints, as_unicode
from ebook_converter.constants import (config_dir, iswindows, isosx, plugins, DEBUG, from ebook_converter.constants import (config_dir, iswindows, isosx, plugins, DEBUG,
isworker, filesystem_encoding) isworker, filesystem_encoding)
from ebook_converter.utils.fonts.metadata import FontMetadata, UnsupportedFont from ebook_converter.utils.fonts.metadata import FontMetadata, UnsupportedFont
from ebook_converter.polyglot.builtins import itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -149,14 +148,14 @@ def path_significance(path, folders):
def build_families(cached_fonts, folders, family_attr='font-family'): def build_families(cached_fonts, folders, family_attr='font-family'):
families = defaultdict(list) families = defaultdict(list)
for font in itervalues(cached_fonts): for font in cached_fonts.values():
if not font: if not font:
continue continue
lf = (font.get(family_attr) or '').lower() lf = (font.get(family_attr) or '').lower()
if lf: if lf:
families[lf].append(font) families[lf].append(font)
for fonts in itervalues(families): for fonts in families.values():
# Look for duplicate font files and choose the copy that is from a # Look for duplicate font files and choose the copy that is from a
# more significant font directory (prefer user directories over # more significant font directory (prefer user directories over
# system directories). # system directories).
@@ -181,7 +180,7 @@ def build_families(cached_fonts, folders, family_attr='font-family'):
font_family_map = dict.copy(families) font_family_map = dict.copy(families)
font_families = tuple(sorted((font[0]['font-family'] for font in font_families = tuple(sorted((font[0]['font-family'] for font in
itervalues(font_family_map)))) font_family_map.values())))
return font_family_map, font_families return font_family_map, font_families
# }}} # }}}
@@ -6,7 +6,6 @@ from ebook_converter.utils.fonts.sfnt.errors import UnsupportedFont, NoGlyphs
from ebook_converter.utils.fonts.sfnt.cff.dict_data import TopDict, PrivateDict from ebook_converter.utils.fonts.sfnt.cff.dict_data import TopDict, PrivateDict
from ebook_converter.utils.fonts.sfnt.cff.constants import (cff_standard_strings, from ebook_converter.utils.fonts.sfnt.cff.constants import (cff_standard_strings,
STANDARD_CHARSETS) STANDARD_CHARSETS)
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -195,8 +194,8 @@ class CFFTable(UnknownTable):
# Map codes from the cmap table to glyph names, this will be used to # Map codes from the cmap table to glyph names, this will be used to
# reconstruct character_map for the subset font # reconstruct character_map for the subset font
charset_map = {code:self.cff.charset.safe_lookup(glyph_id) for code, charset_map = {code:self.cff.charset.safe_lookup(glyph_id) for code,
glyph_id in iteritems(character_map)} glyph_id in character_map.items()}
charset = set(itervalues(charset_map)) charset = set(charset_map.values())
charset.discard(None) charset.discard(None)
if not charset and character_map: if not charset and character_map:
raise NoGlyphs('This font has no glyphs for the specified characters') raise NoGlyphs('This font has no glyphs for the specified characters')
@@ -207,7 +206,7 @@ class CFFTable(UnknownTable):
# Rebuild character_map with the glyph ids from the subset font # Rebuild character_map with the glyph ids from the subset font
character_map.clear() character_map.clear()
for code, charname in iteritems(charset_map): for code, charname in charset_map.items():
glyph_id = s.charname_map.get(charname, None) glyph_id = s.charname_map.get(charname, None)
if glyph_id: if glyph_id:
character_map[code] = glyph_id character_map[code] = glyph_id
+1 -2
View File
@@ -2,7 +2,6 @@ from struct import unpack_from, calcsize
from collections import OrderedDict, namedtuple from collections import OrderedDict, namedtuple
from ebook_converter.utils.fonts.sfnt.errors import UnsupportedFont from ebook_converter.utils.fonts.sfnt.errors import UnsupportedFont
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -78,7 +77,7 @@ class ListTable(OrderedDict):
def dump(self, prefix=''): def dump(self, prefix=''):
print(prefix, self.__class__.__name__, sep='') print(prefix, self.__class__.__name__, sep='')
prefix += ' ' prefix += ' '
for tag, child in iteritems(self): for tag, child in self.items():
print(prefix, tag, sep='') print(prefix, tag, sep='')
child.dump(prefix=prefix+' ') child.dump(prefix=prefix+' ')
+1 -2
View File
@@ -2,7 +2,6 @@ from struct import unpack_from
from collections import OrderedDict from collections import OrderedDict
from ebook_converter.utils.fonts.sfnt import UnknownTable from ebook_converter.utils.fonts.sfnt import UnknownTable
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -80,7 +79,7 @@ class GlyfTable(UnknownTable):
ans = OrderedDict() ans = OrderedDict()
offset = 0 offset = 0
block = [] block = []
for glyph_id, glyph in iteritems(sorted_glyph_map): for glyph_id, glyph in sorted_glyph_map.items():
raw = glyph() raw = glyph()
pad = 4 - (len(raw) % 4) pad = 4 - (len(raw) % 4)
if pad < 4: if pad < 4:
+4 -5
View File
@@ -6,7 +6,6 @@ from ebook_converter.utils.fonts.sfnt.errors import UnsupportedFont
from ebook_converter.utils.fonts.sfnt.common import (ScriptListTable, FeatureListTable, from ebook_converter.utils.fonts.sfnt.common import (ScriptListTable, FeatureListTable,
SimpleListTable, LookupTable, ExtensionSubstitution, SimpleListTable, LookupTable, ExtensionSubstitution,
UnknownLookupSubTable) UnknownLookupSubTable)
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -29,7 +28,7 @@ class SingleSubstitution(UnknownLookupSubTable):
gid_index_map = self.coverage.coverage_indices(glyph_ids) gid_index_map = self.coverage.coverage_indices(glyph_ids)
if self.format == 1: if self.format == 1:
return {gid + self.delta for gid in gid_index_map} return {gid + self.delta for gid in gid_index_map}
return {self.substitutes[i] for i in itervalues(gid_index_map)} return {self.substitutes[i] for i in gid_index_map.values()}
class MultipleSubstitution(UnknownLookupSubTable): class MultipleSubstitution(UnknownLookupSubTable):
@@ -42,7 +41,7 @@ class MultipleSubstitution(UnknownLookupSubTable):
def all_substitutions(self, glyph_ids): def all_substitutions(self, glyph_ids):
gid_index_map = self.coverage.coverage_indices(glyph_ids) gid_index_map = self.coverage.coverage_indices(glyph_ids)
ans = set() ans = set()
for index in itervalues(gid_index_map): for index in gid_index_map.values():
glyphs = set(self.coverage_to_subs_map[index]) glyphs = set(self.coverage_to_subs_map[index])
ans |= glyphs ans |= glyphs
return ans return ans
@@ -67,7 +66,7 @@ class LigatureSubstitution(UnknownLookupSubTable):
def all_substitutions(self, glyph_ids): def all_substitutions(self, glyph_ids):
gid_index_map = self.coverage.coverage_indices(glyph_ids) gid_index_map = self.coverage.coverage_indices(glyph_ids)
ans = set() ans = set()
for start_glyph_id, index in iteritems(gid_index_map): for start_glyph_id, index in gid_index_map.items():
for glyph_id, components in self.coverage_to_lig_map[index]: for glyph_id, components in self.coverage_to_lig_map[index]:
components = (start_glyph_id,) + components components = (start_glyph_id,) + components
if set(components).issubset(glyph_ids): if set(components).issubset(glyph_ids):
@@ -126,7 +125,7 @@ class ReverseChainSingleSubstitution(UnknownLookupSubTable):
def all_substitutions(self, glyph_ids): def all_substitutions(self, glyph_ids):
gid_index_map = self.coverage.coverage_indices(glyph_ids) gid_index_map = self.coverage.coverage_indices(glyph_ids)
return {self.substitutes[i] for i in itervalues(gid_index_map)} return {self.substitutes[i] for i in gid_index_map.values()}
subtable_map = { subtable_map = {
+1 -2
View File
@@ -3,7 +3,6 @@ from operator import itemgetter
from itertools import repeat from itertools import repeat
from ebook_converter.utils.fonts.sfnt import UnknownTable from ebook_converter.utils.fonts.sfnt import UnknownTable
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -54,7 +53,7 @@ class LocaTable(UnknownTable):
max_glyph_id = max(max_glyph_id, current_max_glyph_id) max_glyph_id = max(max_glyph_id, current_max_glyph_id)
self.offset_map = list(repeat(0, max_glyph_id + 2)) self.offset_map = list(repeat(0, max_glyph_id + 2))
glyphs = [(glyph_id, x[0], x[1]) for glyph_id, x in glyphs = [(glyph_id, x[0], x[1]) for glyph_id, x in
iteritems(resolved_glyph_map)] resolved_glyph_map.items()]
glyphs.sort(key=itemgetter(1)) glyphs.sort(key=itemgetter(1))
for glyph_id, offset, sz in glyphs: for glyph_id, offset, sz in glyphs:
self.offset_map[glyph_id] = offset self.offset_map[glyph_id] = offset
+10 -10
View File
@@ -6,7 +6,6 @@ from functools import partial
from ebook_converter.utils.icu import safe_chr, ord_string from ebook_converter.utils.icu import safe_chr, ord_string
from ebook_converter.utils.fonts.sfnt.container import Sfnt from ebook_converter.utils.fonts.sfnt.container import Sfnt
from ebook_converter.utils.fonts.sfnt.errors import UnsupportedFont, NoGlyphs from ebook_converter.utils.fonts.sfnt.errors import UnsupportedFont, NoGlyphs
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -17,7 +16,7 @@ __docformat__ = 'restructuredtext en'
def resolve_glyphs(loca, glyf, character_map, extra_glyphs): def resolve_glyphs(loca, glyf, character_map, extra_glyphs):
unresolved_glyphs = set(itervalues(character_map)) | extra_glyphs unresolved_glyphs = set(character_map.values()) | extra_glyphs
unresolved_glyphs.add(0) # We always want the .notdef glyph unresolved_glyphs.add(0) # We always want the .notdef glyph
resolved_glyphs = {} resolved_glyphs = {}
@@ -33,7 +32,7 @@ def resolve_glyphs(loca, glyf, character_map, extra_glyphs):
if gid not in resolved_glyphs: if gid not in resolved_glyphs:
unresolved_glyphs.add(gid) unresolved_glyphs.add(gid)
return OrderedDict(sorted(iteritems(resolved_glyphs), key=itemgetter(0))) return OrderedDict(sorted(resolved_glyphs.items(), key=itemgetter(0)))
def subset_truetype(sfnt, character_map, extra_glyphs): def subset_truetype(sfnt, character_map, extra_glyphs):
@@ -52,7 +51,7 @@ def subset_truetype(sfnt, character_map, extra_glyphs):
'set, subsetting it is pointless') 'set, subsetting it is pointless')
# Keep only character codes that have resolved glyphs # Keep only character codes that have resolved glyphs
for code, glyph_id in tuple(iteritems(character_map)): for code, glyph_id in tuple(character_map.items()):
if glyph_id not in resolved_glyphs: if glyph_id not in resolved_glyphs:
del character_map[code] del character_map[code]
@@ -154,7 +153,7 @@ def subset(raw, individual_chars, ranges=(), warnings=None):
gsub = sfnt[b'GSUB'] gsub = sfnt[b'GSUB']
try: try:
gsub.decompile() gsub.decompile()
extra_glyphs = gsub.all_substitutions(itervalues(character_map)) extra_glyphs = gsub.all_substitutions(character_map.values())
except UnsupportedFont as e: except UnsupportedFont as e:
warn('Usupported GSUB table: %s'%e) warn('Usupported GSUB table: %s'%e)
except Exception: except Exception:
@@ -175,7 +174,7 @@ def subset(raw, individual_chars, ranges=(), warnings=None):
if b'kern' in sfnt: if b'kern' in sfnt:
try: try:
sfnt[b'kern'].restrict_to_glyphs(frozenset(itervalues(character_map))) sfnt[b'kern'].restrict_to_glyphs(frozenset(character_map.values()))
except UnsupportedFont as e: except UnsupportedFont as e:
warn('kern table unsupported, ignoring: %s'%e) warn('kern table unsupported, ignoring: %s'%e)
except Exception: except Exception:
@@ -214,8 +213,8 @@ def print_stats(old_stats, new_stats):
prints('Table', ' ', '%10s'%'Size', ' ', 'Percent', ' ', '%10s'%'New Size', prints('Table', ' ', '%10s'%'Size', ' ', 'Percent', ' ', '%10s'%'New Size',
' New Percent') ' New Percent')
prints('='*80) prints('='*80)
old_total = sum(itervalues(old_stats)) old_total = sum(old_stats.values())
new_total = sum(itervalues(new_stats)) new_total = sum(new_stats.values())
tables = sorted(old_stats, key=lambda x:old_stats[x], tables = sorted(old_stats, key=lambda x:old_stats[x],
reverse=True) reverse=True)
for table in tables: for table in tables:
@@ -350,7 +349,8 @@ def all():
print('Failed!') print('Failed!')
failed.append((font['full_name'], font['path'], str(e))) failed.append((font['full_name'], font['path'], str(e)))
else: else:
averages.append(sum(itervalues(new_stats))/sum(itervalues(old_stats)) * 100) averages.append(sum(new_stats.values()) /
sum(old_stats.values()) * 100)
print('Reduced to:', '%.1f'%averages[-1] , '%') print('Reduced to:', '%.1f'%averages[-1] , '%')
if unsupported: if unsupported:
print('\n\nUnsupported:') print('\n\nUnsupported:')
@@ -359,7 +359,7 @@ def all():
print() print()
if warnings: if warnings:
print('\n\nWarnings:') print('\n\nWarnings:')
for name, w in iteritems(warnings): for name, w in warnings.items():
if w: if w:
print(name) print(name)
print('', '\n\t'.join(w), sep='\t') print('', '\n\t'.join(w), sep='\t')
+6 -5
View File
@@ -2,7 +2,7 @@ import struct
from io import BytesIO from io import BytesIO
from collections import defaultdict from collections import defaultdict
from ebook_converter.polyglot.builtins import iteritems, itervalues, as_bytes from ebook_converter.polyglot.builtins import as_bytes
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -162,7 +162,7 @@ def decode_name_record(recs):
return mac_names[0] return mac_names[0]
# Use unicode names # Use unicode names
for val in itervalues(unicode_names): for val in unicode_names.values():
return val return val
return None return None
@@ -223,9 +223,10 @@ def get_all_font_names(raw, raw_is_table=False):
records = _get_font_names(raw, raw_is_table) records = _get_font_names(raw, raw_is_table)
ans = {} ans = {}
for name, num in iteritems({'family_name':1, 'subfamily_name':2, 'full_name':4, for name, num in {'family_name': 1, 'subfamily_name': 2, 'full_name': 4,
'preferred_family_name':16, 'preferred_subfamily_name':17, 'preferred_family_name': 16,
'wws_family_name':21, 'wws_subfamily_name':22}): 'preferred_subfamily_name': 17, 'wws_family_name': 21,
'wws_subfamily_name': 22}.items():
try: try:
ans[name] = decode_name_record(records[num]) ans[name] = decode_name_record(records[num])
except (IndexError, KeyError, ValueError): except (IndexError, KeyError, ValueError):
+5 -6
View File
@@ -14,7 +14,6 @@ from ebook_converter.utils.titlecase import titlecase
from ebook_converter.utils.icu import capitalize, strcmp, sort_key from ebook_converter.utils.icu import capitalize, strcmp, sort_key
from ebook_converter.utils.date import parse_date, format_date, now, UNDEFINED_DATE from ebook_converter.utils.date import parse_date, format_date, now, UNDEFINED_DATE
from ebook_converter.utils.localization import calibre_langcode_to_name, canonicalize_lang from ebook_converter.utils.localization import calibre_langcode_to_name, canonicalize_lang
from ebook_converter.polyglot.builtins import iteritems, itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -60,7 +59,7 @@ class FormatterFunctions(object):
self._register_functions() self._register_functions()
def _register_functions(self): def _register_functions(self):
for compiled_funcs in itervalues(self._functions_from_library): for compiled_funcs in self._functions_from_library.values():
for cls in compiled_funcs: for cls in compiled_funcs:
f = self._functions.get(cls.name, None) f = self._functions.get(cls.name, None)
replace = False replace = False
@@ -90,7 +89,7 @@ class FormatterFunctions(object):
def get_builtins_and_aliases(self): def get_builtins_and_aliases(self):
res = {} res = {}
for f in itervalues(self._builtins): for f in self._builtins.values():
res[f.name] = f res[f.name] = f
for a in f.aliases: for a in f.aliases:
res[a] = f res[a] = f
@@ -834,7 +833,7 @@ class BuiltinFormatsSizes(BuiltinFormatterFunction):
def evaluate(self, formatter, kwargs, mi, locals): def evaluate(self, formatter, kwargs, mi, locals):
fmt_data = mi.get('format_metadata', {}) fmt_data = mi.get('format_metadata', {})
try: try:
return ','.join(k.upper()+':'+str(v['size']) for k,v in iteritems(fmt_data)) return ','.join(k.upper()+':'+str(v['size']) for k,v in fmt_data.items())
except: except:
return '' return ''
@@ -853,7 +852,7 @@ class BuiltinFormatsPaths(BuiltinFormatterFunction):
def evaluate(self, formatter, kwargs, mi, locals): def evaluate(self, formatter, kwargs, mi, locals):
fmt_data = mi.get('format_metadata', {}) fmt_data = mi.get('format_metadata', {})
try: try:
return ','.join(k.upper()+':'+str(v['path']) for k,v in iteritems(fmt_data)) return ','.join(k.upper()+':'+str(v['path']) for k,v in fmt_data.items())
except: except:
return '' return ''
@@ -1530,7 +1529,7 @@ class BuiltinUserCategories(BuiltinFormatterFunction):
def evaluate(self, formatter, kwargs, mi, locals_): def evaluate(self, formatter, kwargs, mi, locals_):
if hasattr(mi, '_proxy_metadata'): if hasattr(mi, '_proxy_metadata'):
cats = set(k for k, v in iteritems(mi._proxy_metadata.user_categories) if v) cats = set(k for k, v in mi._proxy_metadata.user_categories.items() if v)
cats = sorted(cats, key=sort_key) cats = sorted(cats, key=sort_key)
return ', '.join(cats) return ', '.join(cats)
return _('This function can be used only in the GUI') return _('This function can be used only in the GUI')
+2 -2
View File
@@ -5,7 +5,7 @@ from ebook_converter.constants import isosx, isfrozen, filesystem_encoding, ispy
from ebook_converter.utils.config import prefs from ebook_converter.utils.config import prefs
from ebook_converter.ptempfile import PersistentTemporaryFile, base_dir from ebook_converter.ptempfile import PersistentTemporaryFile, base_dir
from ebook_converter.utils.serialize import msgpack_dumps from ebook_converter.utils.serialize import msgpack_dumps
from ebook_converter.polyglot.builtins import iteritems, environ_item, native_string_type from ebook_converter.polyglot.builtins import environ_item, native_string_type
from ebook_converter.polyglot.binary import as_hex_unicode from ebook_converter.polyglot.binary import as_hex_unicode
try: try:
import win32process import win32process
@@ -162,7 +162,7 @@ class Worker(object):
self._env = env.copy() self._env = env.copy()
else: else:
# Windows cannot handle unicode env vars # Windows cannot handle unicode env vars
for k, v in iteritems(env): for k, v in env.items():
try: try:
if isinstance(k, str): if isinstance(k, str):
k = k.encode('ascii') k = k.encode('ascii')
+2 -4
View File
@@ -7,8 +7,6 @@ import json
from gettext import GNUTranslations, NullTranslations from gettext import GNUTranslations, NullTranslations
import pkg_resources import pkg_resources
from ebook_converter.polyglot.builtins import iteritems
_available_translations = None _available_translations = None
@@ -284,7 +282,7 @@ def lang_map():
translate = _ translate = _
global _lang_map global _lang_map
if _lang_map is None: if _lang_map is None:
_lang_map = {k:translate(v) for k, v in iteritems(iso639['by_3'])} _lang_map = {k:translate(v) for k, v in iso639['by_3'].items()}
return _lang_map return _lang_map
@@ -308,7 +306,7 @@ def langnames_to_langcodes(names):
translate = _ translate = _
ans = {} ans = {}
names = set(names) names = set(names)
for k, v in iteritems(iso639['by_3']): for k, v in iso639['by_3'].items():
tv = translate(v) tv = translate(v)
if tv in names: if tv in names:
names.remove(tv) names.remove(tv)
+1 -3
View File
@@ -9,8 +9,6 @@ from struct import calcsize, unpack, pack
from collections import namedtuple, OrderedDict from collections import namedtuple, OrderedDict
from tempfile import SpooledTemporaryFile from tempfile import SpooledTemporaryFile
from ebook_converter.polyglot.builtins import itervalues
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2012, Kovid Goyal <kovid at kovidgoyal.net>'
@@ -311,7 +309,7 @@ class LocalZipFile(object):
with SpooledTemporaryFile(max_size=100*1024*1024) as temp: with SpooledTemporaryFile(max_size=100*1024*1024) as temp:
ztemp = ZipFile(temp, 'w') ztemp = ZipFile(temp, 'w')
for offset, header in itervalues(self.file_info): for offset, header in self.file_info.values():
if header.filename in names: if header.filename in names:
zi = ZipInfo(header.filename) zi = ZipInfo(header.filename)
zi.compress_type = header.compression_method zi.compress_type = header.compression_method
+1 -2
View File
@@ -6,7 +6,6 @@ from functools import partial
from threading import Lock from threading import Lock
from ebook_converter import isbytestring, force_unicode, as_unicode, prints from ebook_converter import isbytestring, force_unicode, as_unicode, prints
from ebook_converter.polyglot.builtins import iteritems
__license__ = 'GPL 3' __license__ = 'GPL 3'
@@ -88,7 +87,7 @@ class HTMLStream(Stream):
class UnicodeHTMLStream(HTMLStream): class UnicodeHTMLStream(HTMLStream):
color = {k: v.decode('ascii') for k, v in iteritems(HTMLStream.color)} color = {k: v.decode('ascii') for k, v in HTMLStream.color.items()}
normal = HTMLStream.normal.decode('ascii') normal = HTMLStream.normal.decode('ascii')
def __init__(self): def __init__(self):
+4 -4
View File
@@ -7,7 +7,7 @@ except ValueError:
iswindows = False iswindows = False
from ebook_converter.constants import ispy3 from ebook_converter.constants import ispy3
from ebook_converter.polyglot.builtins import iteritems, native_string_type from ebook_converter.polyglot.builtins import native_string_type
__license__ = 'GPL v3' __license__ = 'GPL v3'
@@ -42,7 +42,7 @@ RATTRIBUTES = dict(
'concealed' 'concealed'
) )
)) ))
ATTRIBUTES = {v:fmt(k) for k, v in iteritems(RATTRIBUTES)} ATTRIBUTES = {v:fmt(k) for k, v in RATTRIBUTES.items()}
del ATTRIBUTES[''] del ATTRIBUTES['']
RBACKGROUNDS = dict( RBACKGROUNDS = dict(
@@ -56,7 +56,7 @@ RBACKGROUNDS = dict(
'white' 'white'
), ),
)) ))
BACKGROUNDS = {v:fmt(k) for k, v in iteritems(RBACKGROUNDS)} BACKGROUNDS = {v:fmt(k) for k, v in RBACKGROUNDS.items()}
RCOLORS = dict( RCOLORS = dict(
zip(range(31, 38), ( zip(range(31, 38), (
@@ -69,7 +69,7 @@ RCOLORS = dict(
'white', 'white',
), ),
)) ))
COLORS = {v:fmt(k) for k, v in iteritems(RCOLORS)} COLORS = {v:fmt(k) for k, v in RCOLORS.items()}
RESET = fmt(0) RESET = fmt(0)