From aee69f304ab9639d7ff91f543aa757e18e736f90 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 26 Apr 2012 15:11:22 +0530 Subject: [PATCH] Switch to using cssutils 0.9.9 for improved performance and robustness --- src/calibre/ebooks/mobi/writer8/main.py | 4 +-- src/calibre/ebooks/odt/input.py | 2 +- src/calibre/ebooks/oeb/base.py | 6 ++--- src/calibre/ebooks/oeb/stylizer.py | 26 +++++++++----------- src/calibre/ebooks/oeb/transforms/flatcss.py | 2 +- 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/calibre/ebooks/mobi/writer8/main.py b/src/calibre/ebooks/mobi/writer8/main.py index ef34692fd3..b237e39b3d 100644 --- a/src/calibre/ebooks/mobi/writer8/main.py +++ b/src/calibre/ebooks/mobi/writer8/main.py @@ -78,7 +78,7 @@ class KF8Writer(object): # in-memory CSSStylesheet, as deepcopy doesn't work (raises an # exception) self._data_cache[item.href] = cssutils.parseString( - item.data.cssText) + item.data.cssText, validate=False) def data(self, item): return self._data_cache.get(item.href, item.data) @@ -114,7 +114,7 @@ class KF8Writer(object): for tag in XPath('//h:style')(root): if tag.text: - sheet = cssutils.parseString(tag.text) + sheet = cssutils.parseString(tag.text, validate=False) replacer = partial(pointer, item) cssutils.replaceUrls(sheet, replacer, ignoreImportRules=True) diff --git a/src/calibre/ebooks/odt/input.py b/src/calibre/ebooks/odt/input.py index 430d95b31f..14e1ff5892 100644 --- a/src/calibre/ebooks/odt/input.py +++ b/src/calibre/ebooks/odt/input.py @@ -116,7 +116,7 @@ class Extract(ODF2XHTML): def do_filter_css(self, css): from cssutils import parseString from cssutils.css import CSSRule - sheet = parseString(css) + sheet = parseString(css, validate=False) rules = list(sheet.cssRules.rulesOfType(CSSRule.STYLE_RULE)) sel_map = {} count = 0 diff --git a/src/calibre/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py index f16aa0b718..7d22f981bf 100644 --- a/src/calibre/ebooks/oeb/base.py +++ b/src/calibre/ebooks/oeb/base.py @@ -212,7 +212,7 @@ def rewrite_links(root, link_repl_func, resolve_base_href=False): if tag == XHTML('style') and el.text and \ (_css_url_re.search(el.text) is not None or '@import' in el.text): - stylesheet = parseString(el.text) + stylesheet = parseString(el.text, validate=False) replaceUrls(stylesheet, link_repl_func) repl = stylesheet.cssText if isbytestring(repl): @@ -223,7 +223,7 @@ def rewrite_links(root, link_repl_func, resolve_base_href=False): text = el.attrib['style'] if _css_url_re.search(text) is not None: try: - stext = parseStyle(text) + stext = parseStyle(text, validate=False) except: # Parsing errors are raised by cssutils continue @@ -861,7 +861,7 @@ class Manifest(object): parser = CSSParser(loglevel=logging.WARNING, fetcher=self.override_css_fetch or self._fetch_css, log=_css_logger) - data = parser.parseString(data, href=self.href) + data = parser.parseString(data, href=self.href, validate=False) data = resolveImports(data) data.namespaces['h'] = XHTML_NS return data diff --git a/src/calibre/ebooks/oeb/stylizer.py b/src/calibre/ebooks/oeb/stylizer.py index 53bca0cb12..1ce404f502 100644 --- a/src/calibre/ebooks/oeb/stylizer.py +++ b/src/calibre/ebooks/oeb/stylizer.py @@ -14,11 +14,9 @@ from xml.dom import SyntaxErr as CSSSyntaxError from cssutils.css import (CSSStyleRule, CSSPageRule, CSSFontFaceRule, cssproperties) try: - from cssutils.css import CSSValueList - CSSValueList + from cssutils.css import PropertyValue except ImportError: - # cssutils >= 0.9.8 - from cssutils.css import PropertyValue as CSSValueList + raise RuntimeError('You need cssutils >= 0.9.9 for calibre') from cssutils import (profile as cssprofiles, parseString, parseStyle, log as cssutils_log, CSSParser, profiles, replaceUrls) from lxml import etree @@ -37,7 +35,7 @@ def html_css_stylesheet(): global _html_css_stylesheet if _html_css_stylesheet is None: html_css = open(P('templates/html.css'), 'rb').read() - _html_css_stylesheet = parseString(html_css) + _html_css_stylesheet = parseString(html_css, validate=False) _html_css_stylesheet.namespaces['h'] = XHTML_NS return _html_css_stylesheet @@ -218,7 +216,8 @@ class Stylizer(object): if text: text = XHTML_CSS_NAMESPACE + text text = oeb.css_preprocessor(text) - stylesheet = parser.parseString(text, href=cssname) + stylesheet = parser.parseString(text, href=cssname, + validate=False) stylesheet.namespaces['h'] = XHTML_NS stylesheets.append(stylesheet) # Make links to resources absolute, since these rules will @@ -247,7 +246,8 @@ class Stylizer(object): if x: try: text = XHTML_CSS_NAMESPACE + x - stylesheet = parser.parseString(text, href=cssname) + stylesheet = parser.parseString(text, href=cssname, + validate=False) stylesheet.namespaces['h'] = XHTML_NS stylesheets.append(stylesheet) except: @@ -374,7 +374,7 @@ class Stylizer(object): def _normalize_edge(self, cssvalue, name): style = {} - if isinstance(cssvalue, CSSValueList): + if isinstance(cssvalue, PropertyValue): primitives = [v.cssText for v in cssvalue] else: primitives = [cssvalue.cssText] @@ -507,15 +507,11 @@ class Style(object): css = [x for x in css if self.MS_PAT.match(x) is None] css = '; '.join(css) try: - style = parseStyle(css) + style = parseStyle(css, validate=False) except CSSSyntaxError: return if url_replacer is not None: - # Fool replaceUrls into processing our style declaration - class Fool: - def __init__(self, s): - self.style = s - replaceUrls(Fool(style), url_replacer, ignoreImportRules=True) + replaceUrls(style, url_replacer, ignoreImportRules=True) self._style.update(self._stylizer.flatten_style(style)) def _has_parent(self): @@ -579,7 +575,7 @@ class Style(object): val = self._style.get('background', None) if val is not None: try: - style = parseStyle('background: '+val) + style = parseStyle('background: '+val, validate=False) val = style.getProperty('background').cssValue try: val = list(val) diff --git a/src/calibre/ebooks/oeb/transforms/flatcss.py b/src/calibre/ebooks/oeb/transforms/flatcss.py index 7eb83c2657..8a828c908b 100644 --- a/src/calibre/ebooks/oeb/transforms/flatcss.py +++ b/src/calibre/ebooks/oeb/transforms/flatcss.py @@ -404,7 +404,7 @@ class CSSFlattener(object): rules = [r.cssText for r in stylizer.font_face_rules] raw = '\n\n'.join(rules) # Make URLs referring to fonts relative to this item - sheet = cssutils.parseString(raw) + sheet = cssutils.parseString(raw, validate=False) cssutils.replaceUrls(sheet, item.relhref, ignoreImportRules=True) style.text += '\n' + sheet.cssText