From 16ca0fa0688ca3853ec9321f1f0628104f715e3e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 16 Jun 2011 09:23:02 -0600 Subject: [PATCH 1/9] Down to Earth by sexymax15 --- src/calibre/web/feeds/recipes/collection.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calibre/web/feeds/recipes/collection.py b/src/calibre/web/feeds/recipes/collection.py index dbedef6dbe..87a65dd9e6 100644 --- a/src/calibre/web/feeds/recipes/collection.py +++ b/src/calibre/web/feeds/recipes/collection.py @@ -21,8 +21,8 @@ NS = 'http://calibre-ebook.com/recipe_collection' E = ElementMaker(namespace=NS, nsmap={None:NS}) def iterate_over_builtin_recipe_files(): - exclude = ['craigslist', 'iht', 'outlook_india', 'toronto_sun', - 'indian_express', 'india_today', 'livemint'] + exclude = ['craigslist', 'iht', 'toronto_sun', + 'india_today', 'livemint'] d = os.path.dirname base = os.path.join(d(d(d(d(d(d(os.path.abspath(__file__))))))), 'recipes') for f in os.listdir(base): From 5e914a5a20923ca8966b4bdf22a918a06c82ceaf Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 16 Jun 2011 09:48:08 -0600 Subject: [PATCH 2/9] Workaround xisbn sometimes returning incomplete isbn pools --- src/calibre/ebooks/metadata/sources/identify.py | 6 +++++- src/calibre/ebooks/metadata/xisbn.py | 10 +++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/calibre/ebooks/metadata/sources/identify.py b/src/calibre/ebooks/metadata/sources/identify.py index 303bb2db6e..81f3e8247f 100644 --- a/src/calibre/ebooks/metadata/sources/identify.py +++ b/src/calibre/ebooks/metadata/sources/identify.py @@ -85,7 +85,11 @@ class ISBNMerge(object): isbns, min_year = xisbn.get_isbn_pool(isbn) if not isbns: isbns = frozenset([isbn]) - self.pools[isbns] = pool = (min_year, []) + if isbns in self.pools: + # xISBN had a brain fart + pool = self.pools[isbn] + else: + self.pools[isbns] = pool = (min_year, []) if not self.pool_has_result_from_same_source(pool, result): pool[1].append(result) diff --git a/src/calibre/ebooks/metadata/xisbn.py b/src/calibre/ebooks/metadata/xisbn.py index 56156c034e..ff21dfd89d 100644 --- a/src/calibre/ebooks/metadata/xisbn.py +++ b/src/calibre/ebooks/metadata/xisbn.py @@ -45,6 +45,11 @@ class xISBN(object): ans.append(rec) return ans + def isbns_in_data(self, data): + for rec in data: + for i in rec.get('isbn', []): + yield i + def get_data(self, isbn): isbn = self.purify(isbn) with self.lock: @@ -57,9 +62,8 @@ class xISBN(object): data = [] id_ = len(self._data) self._data.append(data) - for rec in data: - for i in rec.get('isbn', []): - self._map[i] = id_ + for i in self.isbns_in_data(data): + self._map[i] = id_ self._map[isbn] = id_ return self._data[self._map[isbn]] From 93dcb24eb5994bccad27b63912037485694cfc59 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 16 Jun 2011 10:04:43 -0600 Subject: [PATCH 3/9] ... --- src/calibre/ebooks/metadata/sources/identify.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/ebooks/metadata/sources/identify.py b/src/calibre/ebooks/metadata/sources/identify.py index 81f3e8247f..849dbd1555 100644 --- a/src/calibre/ebooks/metadata/sources/identify.py +++ b/src/calibre/ebooks/metadata/sources/identify.py @@ -87,7 +87,7 @@ class ISBNMerge(object): isbns = frozenset([isbn]) if isbns in self.pools: # xISBN had a brain fart - pool = self.pools[isbn] + pool = self.pools[isbns] else: self.pools[isbns] = pool = (min_year, []) From f56abca9dfe97516443fa8df3c8ebb9ecf71bcee Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 16 Jun 2011 10:56:37 -0600 Subject: [PATCH 4/9] MOBI Output: Allow setting of background color on tables. Fixes #797580 (Private bug) --- src/calibre/ebooks/mobi/mobiml.py | 6 ++++- src/calibre/ebooks/oeb/stylizer.py | 39 ++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/calibre/ebooks/mobi/mobiml.py b/src/calibre/ebooks/mobi/mobiml.py index 493767e233..d108742f3c 100644 --- a/src/calibre/ebooks/mobi/mobiml.py +++ b/src/calibre/ebooks/mobi/mobiml.py @@ -443,11 +443,15 @@ class MobiMLizer(object): tag = 'span' if tag == 'td' else 'div' if tag == 'table': + col = style.backgroundColor + if col: + elem.set('bgcolor', col) css = style.cssdict() if 'border' in css or 'border-width' in css: elem.set('border', '1') if tag in TABLE_TAGS: - for attr in ('rowspan', 'colspan', 'width', 'border', 'scope'): + for attr in ('rowspan', 'colspan', 'width', 'border', 'scope', + 'bgcolor'): if attr in elem.attrib: istate.attrib[attr] = elem.attrib[attr] if tag == 'q': diff --git a/src/calibre/ebooks/oeb/stylizer.py b/src/calibre/ebooks/oeb/stylizer.py index fc7a27b5cd..5ade915e4f 100644 --- a/src/calibre/ebooks/oeb/stylizer.py +++ b/src/calibre/ebooks/oeb/stylizer.py @@ -473,6 +473,7 @@ class Style(object): self._width = None self._height = None self._lineHeight = None + self._bgcolor = None stylizer._styles[element] = self def set(self, prop, val): @@ -533,6 +534,44 @@ class Style(object): def pt_to_px(self, value): return (self._profile.dpi / 72.0) * value + @property + def backgroundColor(self): + ''' + Return the background color by parsing both the background-color and + background shortcut properties. Note that inheritance/default values + are not used. + ''' + + def validate_color(col): + return cssutils.profile.validateWithProfile('color', + col, + profiles=[cssutils.profiles.Profiles.CSS_LEVEL_2])[1] + + if self._bgcolor is None: + val = self._style.get('background-color', None) + if val and validate_color(val): + col = val + else: + val = self._style.get('background', None) + if val is not None: + try: + style = cssutils.parseStyle('background: '+val) + val = style.getProperty('background').cssValue + try: + val = list(val) + except: + # val is CSSPrimitiveValue + val = [val] + for c in val: + c = c.cssText + if validate_color(c): + col = c + break + except: + pass + self._bgcolor = col + return self._bgcolor + @property def fontSize(self): def normalize_fontsize(value, base): From ce639c48f6cb06164e85e80c66c96fd091cab55f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 16 Jun 2011 11:00:31 -0600 Subject: [PATCH 5/9] ... --- src/calibre/ebooks/oeb/stylizer.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/calibre/ebooks/oeb/stylizer.py b/src/calibre/ebooks/oeb/stylizer.py index 5ade915e4f..67b92b5b5a 100644 --- a/src/calibre/ebooks/oeb/stylizer.py +++ b/src/calibre/ebooks/oeb/stylizer.py @@ -548,6 +548,7 @@ class Style(object): profiles=[cssutils.profiles.Profiles.CSS_LEVEL_2])[1] if self._bgcolor is None: + col = None val = self._style.get('background-color', None) if val and validate_color(val): col = val @@ -569,8 +570,11 @@ class Style(object): break except: pass - self._bgcolor = col - return self._bgcolor + if col is None: + self._bgcolor = False + else: + self._bgcolor = col + return self._bgcolor if self._bgcolor else None @property def fontSize(self): From 25c072d4ecc2cc7abe4dfed8309cefe066887613 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 16 Jun 2011 11:08:14 -0600 Subject: [PATCH 6/9] ... --- src/calibre/ebooks/oeb/stylizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/ebooks/oeb/stylizer.py b/src/calibre/ebooks/oeb/stylizer.py index 67b92b5b5a..911e4f8a05 100644 --- a/src/calibre/ebooks/oeb/stylizer.py +++ b/src/calibre/ebooks/oeb/stylizer.py @@ -539,7 +539,7 @@ class Style(object): ''' Return the background color by parsing both the background-color and background shortcut properties. Note that inheritance/default values - are not used. + are not used. None is returned if no background color is set. ''' def validate_color(col): From 0d2ba940cec94badc896028232477fb2563bcfff Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 16 Jun 2011 11:18:06 -0600 Subject: [PATCH 7/9] ... --- src/calibre/ebooks/oeb/stylizer.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/calibre/ebooks/oeb/stylizer.py b/src/calibre/ebooks/oeb/stylizer.py index 911e4f8a05..f6ff594701 100644 --- a/src/calibre/ebooks/oeb/stylizer.py +++ b/src/calibre/ebooks/oeb/stylizer.py @@ -11,7 +11,6 @@ __copyright__ = '2008, Marshall T. Vandegrift ' import os, itertools, re, logging, copy, unicodedata from weakref import WeakKeyDictionary from xml.dom import SyntaxErr as CSSSyntaxError -import cssutils from cssutils.css import (CSSStyleRule, CSSPageRule, CSSStyleDeclaration, CSSFontFaceRule, cssproperties) try: @@ -20,7 +19,8 @@ try: except ImportError: # cssutils >= 0.9.8 from cssutils.css import PropertyValue as CSSValueList -from cssutils import profile as cssprofiles +from cssutils import (profile as cssprofiles, parseString, parseStyle, log as + cssutils_log, CSSParser, profiles) from lxml import etree from lxml.cssselect import css_to_xpath, ExpressionError, SelectorSyntaxError from calibre import force_unicode @@ -28,7 +28,7 @@ from calibre.ebooks import unit_convert from calibre.ebooks.oeb.base import XHTML, XHTML_NS, CSS_MIME, OEB_STYLES from calibre.ebooks.oeb.base import XPNSMAP, xpath, urlnormalize -cssutils.log.setLevel(logging.WARN) +cssutils_log.setLevel(logging.WARN) _html_css_stylesheet = None @@ -36,7 +36,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 = cssutils.parseString(html_css) + _html_css_stylesheet = parseString(html_css) _html_css_stylesheet.namespaces['h'] = XHTML_NS return _html_css_stylesheet @@ -157,11 +157,11 @@ class Stylizer(object): # Add cssutils parsing profiles from output_profile for profile in self.opts.output_profile.extra_css_modules: - cssutils.profile.addProfile(profile['name'], + cssprofiles.addProfile(profile['name'], profile['props'], profile['macros']) - parser = cssutils.CSSParser(fetcher=self._fetch_css_file, + parser = CSSParser(fetcher=self._fetch_css_file, log=logging.getLogger('calibre.css')) self.font_face_rules = [] for elem in head: @@ -543,9 +543,9 @@ class Style(object): ''' def validate_color(col): - return cssutils.profile.validateWithProfile('color', + return cssprofiles.validateWithProfile('color', col, - profiles=[cssutils.profiles.Profiles.CSS_LEVEL_2])[1] + profiles=[profiles.Profiles.CSS_LEVEL_2])[1] if self._bgcolor is None: col = None @@ -556,7 +556,7 @@ class Style(object): val = self._style.get('background', None) if val is not None: try: - style = cssutils.parseStyle('background: '+val) + style = parseStyle('background: '+val) val = style.getProperty('background').cssValue try: val = list(val) From cc31246f08d0eb5619682bd54d33dfd05cb1abf7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 16 Jun 2011 18:09:56 -0600 Subject: [PATCH 8/9] Fix #798441 (Download Metadata hangs Calibre) --- src/calibre/gui2/metadata/single.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/calibre/gui2/metadata/single.py b/src/calibre/gui2/metadata/single.py index b62aa28a68..d818f2db2a 100644 --- a/src/calibre/gui2/metadata/single.py +++ b/src/calibre/gui2/metadata/single.py @@ -388,6 +388,10 @@ class MetadataSingleDialogBase(ResizableDialog): def apply_changes(self): self.changed.add(self.book_id) + if self.db is None: + # break_cycles has already been called, don't know why this should + # happen but a user reported it + return True for widget in self.basic_metadata_widgets: try: if not widget.commit(self.db, self.book_id): From 420f806a0b1be3e9e4a4f312d16e3cac2c0369c0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 17 Jun 2011 10:20:59 -0600 Subject: [PATCH 9/9] For the utterly stupid among us --- src/calibre/gui2/actions/choose_library.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/calibre/gui2/actions/choose_library.py b/src/calibre/gui2/actions/choose_library.py index ac13f2c94a..fb180176df 100644 --- a/src/calibre/gui2/actions/choose_library.py +++ b/src/calibre/gui2/actions/choose_library.py @@ -287,6 +287,18 @@ class ChooseLibraryAction(InterfaceAction): 'rate of approximately 1 book every three seconds.'), show=True) def restore_database(self): + m = self.gui.library_view.model() + db = m.db + if (iswindows and len(db.library_path) > + LibraryDatabase2.WINDOWS_LIBRARY_PATH_LIMIT): + return error_dialog(self.gui, _('Too long'), + _('Path to library too long. Must be less than' + ' %d characters. Move your library to a location with' + ' a shorter path using Windows Explorer, then point' + ' calibre to the new location and try again.')% + LibraryDatabase2.WINDOWS_LIBRARY_PATH_LIMIT, + show=True) + from calibre.gui2.dialogs.restore_library import restore_database m = self.gui.library_view.model() m.stop_metadata_backup()