diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index b455c55553..5cdf03888a 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -114,9 +114,11 @@ def prints(*args, **kwargs): raise arg = repr(arg) if not isinstance(arg, str): - arg = str(arg) - if not isinstance(arg, unicode): - arg = arg.decode(preferred_encoding, 'replace') + try: + arg = str(arg) + except ValueError: + arg = unicode(arg) + if isinstance(arg, unicode): try: arg = arg.encode(enc) except UnicodeEncodeError: diff --git a/src/calibre/devices/cybookg3/driver.py b/src/calibre/devices/cybookg3/driver.py index a8ce905b00..d3ccf85461 100644 --- a/src/calibre/devices/cybookg3/driver.py +++ b/src/calibre/devices/cybookg3/driver.py @@ -13,7 +13,7 @@ from calibre.devices.usbms.driver import USBMS import calibre.devices.cybookg3.t2b as t2b class CYBOOKG3(USBMS): - name = 'Cybook Gen 3 Device Interface' + name = 'Cybook Gen 3/Opus Device Interface' description = _('Communicate with the Cybook eBook reader.') author = _('John Schember') supported_platforms = ['windows', 'osx', 'linux'] @@ -31,7 +31,7 @@ class CYBOOKG3(USBMS): WINDOWS_MAIN_MEM = 'CYBOOK_GEN3__-FD' WINDOWS_CARD_A_MEM = 'CYBOOK_GEN3__-SD' - OSX_MAIN_MEM = 'Bookeen Cybook Gen3 -FD Media' + OSX_MAIN_MEM = ['Bookeen Cybook Gen3 -FD Media', 'Bookeen Cybook Opus -FD Media'] OSX_CARD_A_MEM = 'Bookeen Cybook Gen3 -SD Media' MAIN_MEMORY_VOLUME_LABEL = 'Cybook Gen 3 Main Memory' diff --git a/src/calibre/devices/prs500/driver.py b/src/calibre/devices/prs500/driver.py index aba8a9d088..5c97144049 100644 --- a/src/calibre/devices/prs500/driver.py +++ b/src/calibre/devices/prs500/driver.py @@ -87,6 +87,7 @@ class PRS500(DeviceConfig, DevicePlugin): description = _('Communicate with the Sony PRS-500 eBook reader.') author = _('Kovid Goyal') supported_platforms = ['windows', 'osx', 'linux'] + log_packets = False VENDOR_ID = 0x054c #: SONY Vendor Id PRODUCT_ID = 0x029b #: Product Id for the PRS-500 diff --git a/src/calibre/ebooks/epub/output.py b/src/calibre/ebooks/epub/output.py index 18009a9a9f..d8bab20b1c 100644 --- a/src/calibre/ebooks/epub/output.py +++ b/src/calibre/ebooks/epub/output.py @@ -148,6 +148,20 @@ class EPUBOutput(OutputFormatPlugin): if not pre.text and len(pre) == 0: pre.tag = 'div' + # Remove hyperlinks with no content as they cause rendering + # artifacts in browser based renderers + for a in body.xpath('//a[@href]'): + if a.get('id', None) is None and a.get('name', None) is None \ + and len(a) == 0 and not a.text: + p = a.getparent() + idx = p.index(a) -1 + p.remove(a) + if a.tail: + if idx <= 0: + p.text += a.tail + else: + p[idx].tail += a.tail + def convert(self, oeb, output_path, input_plugin, opts, log): self.log, self.opts, self.oeb = log, opts, oeb diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index 0a305dbe1c..d1b4076cd9 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -1972,7 +1972,7 @@ class MobiWriter(object): continue if h not in self._id_offsets: self._oeb.logger.warn(' Ignoring missing TOC entry:', - child) + unicode(child)) continue currentOffset = self._id_offsets[h] diff --git a/src/calibre/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py index 23b01da1a2..8941f97304 100644 --- a/src/calibre/ebooks/oeb/base.py +++ b/src/calibre/ebooks/oeb/base.py @@ -904,12 +904,6 @@ class Manifest(object): if key == 'lang' or key.endswith('}lang'): body.attrib.pop(key) - # Remove invalid links as they casue overflow until the next link - # in rendering. - data = etree.tostring(data) - data = re.sub('', '', data) - data = etree.fromstring(data) - return data def _parse_txt(self, data): diff --git a/src/calibre/ebooks/oeb/stylizer.py b/src/calibre/ebooks/oeb/stylizer.py index 9a52709ca4..1d3b0515d4 100644 --- a/src/calibre/ebooks/oeb/stylizer.py +++ b/src/calibre/ebooks/oeb/stylizer.py @@ -137,6 +137,11 @@ class Stylizer(object): 'Stylesheet %r referenced by file %r not in manifest' % (path, item.href)) continue + if not hasattr(sitem.data, 'cssRules'): + self.logger.warn( + 'Stylesheet %r referenced by file %r is not CSS'%(path, + item.href)) + continue stylesheets.append(sitem.data) for x in (extra_css, user_css): if x: @@ -220,6 +225,7 @@ class Stylizer(object): if 'font-size' in style: size = style['font-size'] if size == 'normal': size = 'medium' + if size == 'smallest': size = 'xx-small' if size in FONT_SIZE_NAMES: style['font-size'] = "%dpt" % self.profile.fnames[size] return style diff --git a/src/calibre/ebooks/oeb/transforms/flatcss.py b/src/calibre/ebooks/oeb/transforms/flatcss.py index 7114c9736f..8ef5c42ea1 100644 --- a/src/calibre/ebooks/oeb/transforms/flatcss.py +++ b/src/calibre/ebooks/oeb/transforms/flatcss.py @@ -213,7 +213,10 @@ class CSSFlattener(object): esize = 7 cssdict['font-size'] = fnums[esize] else: - cssdict['font-size'] = fnums[force_int(size)] + try: + cssdict['font-size'] = fnums[force_int(size)] + except: + cssdict['font-size'] = fnums[3] del node.attrib['size'] if 'color' in node.attrib: cssdict['color'] = node.attrib['color'] diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index d477389875..6e04f835b9 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1678,8 +1678,11 @@ books_series_link feeds au = self.authors(id, index_is_id=True) if not au: au = _('Unknown') - fname = '%s - %s.%s'%(title, au, format.lower()) + fname = '%s - %s'%(title, au) + while fname.endswith('.'): + fname = fname[:-1] fname = ascii_filename(fname) + fname = fname + '.' + format.lower() dir = os.path.abspath(dir) fname = shorten_components_to(plen - len(dir), (fname,))[0] if not os.path.exists(dir): diff --git a/src/calibre/library/server.py b/src/calibre/library/server.py index d0ea9e962e..c935b9a0a0 100644 --- a/src/calibre/library/server.py +++ b/src/calibre/library/server.py @@ -23,7 +23,7 @@ except ImportError: from calibre.constants import __version__, __appname__ from calibre.utils.genshi.template import MarkupTemplate -from calibre import fit_image, guess_type +from calibre import fit_image, guess_type, prepare_string_for_xml from calibre.resources import jquery, server_resources, build_time from calibre.library import server_config as config from calibre.library.database2 import LibraryDatabase2, FIELD_MAP @@ -100,6 +100,7 @@ class LibraryServer(object): calibre Library $id ${updated.strftime('%Y-%m-%dT%H:%M:%S+00:00')} + calibre http://calibre.kovidgoyal.net @@ -283,10 +284,12 @@ class LibraryServer(object): @expose - def stanza(self): + def stanza(self, search=None): 'Feeds to read calibre books on a ipod with stanza.' books = [] + ids = self.db.data.parse(search) if search and search.strip() else self.db.data.universal_set() for record in iter(self.db): + if record[0] not in ids: continue r = record[FIELD_MAP['formats']] r = r.upper() if r else '' if 'EPUB' in r or 'PDB' in r: @@ -302,11 +305,13 @@ class LibraryServer(object): extra.append('RATING: %s
'%rating) tags = record[FIELD_MAP['tags']] if tags: - extra.append('TAGS: %s
'%', '.join(tags.split(','))) + extra.append('TAGS: %s
'%\ + prepare_string_for_xml(', '.join(tags.split(',')))) series = record[FIELD_MAP['series']] if series: - extra.append('SERIES: %s [%s]
'%(series, - fmt_sidx(float(record[FIELD_MAP['series_index']])))) + extra.append('SERIES: %s [%s]
'%\ + (prepare_string_for_xml(series), + fmt_sidx(float(record[FIELD_MAP['series_index']])))) fmt = 'epub' if 'EPUB' in r else 'pdb' mimetype = guess_type('dummy.'+fmt)[0] books.append(self.STANZA_ENTRY.generate( @@ -369,7 +374,7 @@ class LibraryServer(object): 'The / URL' want_opds = cherrypy.request.headers.get('Stanza-Device-Name', 919) != \ 919 or cherrypy.request.headers.get('Want-OPDS-Catalog', 919) != 919 - return self.stanza() if want_opds else self.static('index.html') + return self.stanza(search=kwargs.get('search', None)) if want_opds else self.static('index.html') @expose diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py index acb1d967b0..c27e51583f 100644 --- a/src/calibre/web/feeds/recipes/__init__.py +++ b/src/calibre/web/feeds/recipes/__init__.py @@ -48,7 +48,7 @@ recipe_modules = ['recipe_' + r for r in ( 'the_budget_fashionista', 'elperiodico_catalan', 'elperiodico_spanish', 'expansion_spanish', 'lavanguardia', 'marca', 'kellog_faculty', 'kellog_insight', 'noaa', - 'theeconomictimes_india', '7dias', 'buenosaireseconomico', + '7dias', 'buenosaireseconomico', 'diagonales', 'miradasalsur', 'newsweek_argentina', 'veintitres', 'gva_be', 'hln', 'tijd', 'degentenaar', 'inquirer_net', 'uncrate', 'fastcompany', 'accountancyage', 'laprensa_hn', 'latribuna', diff --git a/src/calibre/web/feeds/recipes/recipe_economist.py b/src/calibre/web/feeds/recipes/recipe_economist.py index 9997c5fce9..c88554ad27 100644 --- a/src/calibre/web/feeds/recipes/recipe_economist.py +++ b/src/calibre/web/feeds/recipes/recipe_economist.py @@ -20,6 +20,7 @@ class Economist(BasicNewsRecipe): oldest_article = 7.0 needs_subscription = False # Strange but true INDEX = 'http://www.economist.com/printedition' + cover_url = 'http://www.economist.com/images/covers/currentcovereu_large.jpg' remove_tags = [dict(name=['script', 'noscript', 'title'])] remove_tags_before = dict(name=lambda tag: tag.name=='title' and tag.parent.name=='body')