From 0bdca2d21c91b241230a93ee59f408915ab833a8 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 Aug 2009 20:01:46 -0600 Subject: [PATCH 01/15] Fix #3132 (Calibre Zip is 0.00KB) --- src/calibre/ebooks/html/input.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/ebooks/html/input.py b/src/calibre/ebooks/html/input.py index 6d3f5cde85..92c2df9690 100644 --- a/src/calibre/ebooks/html/input.py +++ b/src/calibre/ebooks/html/input.py @@ -110,7 +110,7 @@ class HTMLFile(object): raise IOError(msg) raise IgnoreFile(msg, err.errno) - self.is_binary = not bool(self.HTML_PAT.search(src[:1024])) + self.is_binary = not bool(self.HTML_PAT.search(src[:4096])) if not self.is_binary: if encoding is None: encoding = xml_to_unicode(src[:4096], verbose=verbose)[-1] From 49ab3466190c93025d9f6cce7f50100b7ee25bea Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 Aug 2009 20:20:28 -0600 Subject: [PATCH 02/15] Fix detection of non-US PRS-700 readers in OS X and Windows --- src/calibre/devices/prs700/driver.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/calibre/devices/prs700/driver.py b/src/calibre/devices/prs700/driver.py index 1354685431..7856ef0b34 100644 --- a/src/calibre/devices/prs700/driver.py +++ b/src/calibre/devices/prs700/driver.py @@ -9,6 +9,7 @@ Device driver for the SONY PRS-700 ''' from calibre.devices.prs505.driver import PRS505 +import re class PRS700(PRS505): @@ -20,9 +21,10 @@ class PRS700(PRS505): BCD = [0x31a] WINDOWS_MAIN_MEM = 'PRS-700' - WINDOWS_CARD_A_MEM = 'PRS-700/UC:MS' - WINDOWS_CARD_B_MEM = 'PRS-700/UC:SD' + WINDOWS_CARD_A_MEM = re.compile(r'PRS-700/\S+:MS') + WINDOWS_CARD_B_MEM = re.compile(r'PRS-700/\S+:SD') + + OSX_MAIN_MEM = re.compile(r'Sony PRS-700/[^:]+ Media') + OSX_CARD_A_MEM = re.compile(r'Sony PRS-700/[^:]+:MS Media') + OSX_CARD_B_MEM = re.compile(r'Sony PRS-700/[^:]+:SD Media') - OSX_MAIN_MEM = 'Sony PRS-700/UC Media' - OSX_CARD_A_MEM = 'Sony PRS-700/UC:MS Media' - OSX_CARD_B_MEM = 'Sony PRS-700/UC:SD' From c30fb96ebfa673663276273d25f5f07fa3a59af3 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 12 Aug 2009 11:45:30 -0600 Subject: [PATCH 03/15] FB2 Metadata Reader: Fix cover extraction, author_sort extraction, support multiple authors. Improved Irish Times recipe --- src/calibre/ebooks/metadata/fb2.py | 88 +++++++++++++------ .../web/feeds/recipes/recipe_irish_times.py | 76 ++++++++-------- 2 files changed, 99 insertions(+), 65 deletions(-) diff --git a/src/calibre/ebooks/metadata/fb2.py b/src/calibre/ebooks/metadata/fb2.py index eded2dc056..03e3117d3e 100644 --- a/src/calibre/ebooks/metadata/fb2.py +++ b/src/calibre/ebooks/metadata/fb2.py @@ -5,50 +5,82 @@ __copyright__ = '2008, Anatoly Shipitsin ' '''Read meta information from fb2 files''' -import mimetypes +import mimetypes, os from base64 import b64decode - -from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup +from lxml import etree from calibre.ebooks.metadata import MetaInformation +XLINK_NS = 'http://www.w3.org/1999/xlink' +def XLINK(name): + return '{%s}%s' % (XLINK_NS, name) + + def get_metadata(stream): """ Return metadata as a L{MetaInfo} object """ - soup = BeautifulStoneSoup(stream.read()) - firstname = soup.find("first-name").contents[0] - lastname = soup.find("last-name").contents[0] - author= [firstname+" "+lastname] - title = soup.find("book-title").string - comments = soup.find("annotation") - tags = soup.findAll('genre') - tags = [t.contents[0] for t in tags] - cp = soup.find('coverpage') + XPath = lambda x : etree.XPath(x, + namespaces={'fb2':'http://www.gribuser.ru/xml/fictionbook/2.0', + 'xlink':XLINK_NS}) + tostring = lambda x : etree.tostring(x, method='text', + encoding=unicode).strip() + root = etree.fromstring(stream.read()) + authors, author_sort = [], None + for au in XPath('//fb2:author')(root): + fname = lname = author = None + fe = XPath('descendant::fb2:first-name')(au) + if fe: + fname = tostring(fe[0]) + author = fname + le = XPath('descendant::fb2:last-name')(au) + if le: + lname = tostring(le[0]) + author += ' '+lname + if author: + authors.append(author) + if len(authors) == 1 and author is not None: + if lname: + author_sort = lname + if fname: + if author_sort: author_sort += ', '+fname + else: author_sort = fname + title = os.path.splitext(os.path.basename(getattr(stream, 'name', + _('Unknown'))))[0] + for x in XPath('//fb2:book-title')(root): + title = tostring(x) + comments = '' + for x in XPath('//fb2:annotation')(root): + comments += tostring(x) + if not comments: + comments = None + tags = list(map(tostring, XPath('//fb2:genre')(root))) + + cp = XPath('//fb2:coverpage')(root) cdata = None if cp: - cimage = cp.find('image', attrs={'l:href':True}) + cimage = XPath('descendant::fb2:image[@xlink:href]')(cp[0]) if cimage: - id = cimage['l:href'].replace('#', '') - binary = soup.find('binary', id=id, attrs={'content-type':True}) + id = cimage[0].get(XLINK('href')).replace('#', '') + binary = XPath('//fb2:binary[@id="%s"]'%id)(root) if binary: - mt = binary['content-type'] + mt = binary[0].get('content-type', 'image/jpeg') exts = mimetypes.guess_all_extensions(mt) if not exts: exts = ['.jpg'] - cdata = (exts[0][1:], b64decode(binary.string.strip())) + cdata = (exts[0][1:], b64decode(tostring(binary[0]))) - if comments: - comments = u''.join(comments.findAll(text=True)) - series = soup.find("sequence") - mi = MetaInformation(title, author) + series = None + series_index = 1.0 + for x in XPath('//fb2:sequence')(root): + series = x.get('name', None) + if series is not None: + series_index = x.get('number', 1.0) + break + mi = MetaInformation(title, authors) mi.comments = comments - mi.author_sort = lastname+'; '+firstname + mi.author_sort = author_sort if tags: mi.tags = tags - if series: - mi.series = series.get('name', None) - try: - mi.series_index = float(series.get('number', None)) - except (TypeError, ValueError): - pass + mi.series = series + mi.series_index = series_index if cdata: mi.cover_data = cdata return mi diff --git a/src/calibre/web/feeds/recipes/recipe_irish_times.py b/src/calibre/web/feeds/recipes/recipe_irish_times.py index 089e8d974c..807af6baf5 100644 --- a/src/calibre/web/feeds/recipes/recipe_irish_times.py +++ b/src/calibre/web/feeds/recipes/recipe_irish_times.py @@ -1,37 +1,39 @@ -__license__ = 'GPL v3' -__copyright__ = '2008, Derry FitzGerald' -''' -irishtimes.com -''' - -from calibre.web.feeds.news import BasicNewsRecipe - -class IrishTimes(BasicNewsRecipe): - title = u'The Irish Times' - __author__ = 'Derry FitzGerald' - language = _('English') - no_stylesheets = True - - remove_tags = [dict(name='div', attrs={'class':'footer'})] - extra_css = '.headline {font-size: x-large;} \n .fact { padding-top: 10pt }' - - feeds = [ - ('Frontpage', 'http://www.irishtimes.com/feeds/rss/newspaper/index.rss'), - ('Ireland', 'http://www.irishtimes.com/feeds/rss/newspaper/ireland.rss'), - ('World', 'http://www.irishtimes.com/feeds/rss/newspaper/world.rss'), - ('Finance', 'http://www.irishtimes.com/feeds/rss/newspaper/finance.rss'), - ('Features', 'http://www.irishtimes.com/feeds/rss/newspaper/features.rss'), - ('Sport', 'http://www.irishtimes.com/feeds/rss/newspaper/sport.rss'), - ('Opinion', 'http://www.irishtimes.com/feeds/rss/newspaper/opinion.rss'), - ('Letters', 'http://www.irishtimes.com/feeds/rss/newspaper/letters.rss'), - ('Health', 'http://www.irishtimes.com/feeds/rss/newspaper/health.rss'), - ('Education and Parenting', 'http://www.irishtimes.com/feeds/rss/newspaper/education.rss'), - ('Science Today', 'http://www.irishtimes.com/feeds/rss/newspaper/sciencetoday.rss'), - ('The Ticket', 'http://www.irishtimes.com/feeds/rss/newspaper/theticket.rss'), - ('Weekend', 'http://www.irishtimes.com/feeds/rss/newspaper/weekend.rss'), - ('News Features', 'http://www.irishtimes.com/feeds/rss/newspaper/newsfeatures.rss'), - ('Magazine', 'http://www.irishtimes.com/feeds/rss/newspaper/magazine.rss'), - ] - - def print_version(self, url): - return url.replace('.html', '_pf.html') \ No newline at end of file +__license__ = 'GPL v3' +__copyright__ = '2008, Derry FitzGerald. 2009 Modified by Ray Kinsella' +''' +irishtimes.com +''' +import re + +from calibre.web.feeds.news import BasicNewsRecipe + +class IrishTimes(BasicNewsRecipe): + title = u'The Irish Times' + __author__ = 'Derry FitzGerald and Ray Kinsella' + language = _('English') + no_stylesheets = True + simultaneous_downloads= 1 + + r = re.compile('.*(?Phttp:\/\/www.irishtimes.com\/.*\.html).*') + remove_tags = [dict(name='div', attrs={'class':'footer'})] + extra_css = '.headline {font-size: x-large;} \n .fact { padding-top: 10pt }' + + feeds = [ + ('Frontpage', 'http://www.irishtimes.com/feeds/rss/newspaper/index.rss'), + ('Ireland', 'http://www.irishtimes.com/feeds/rss/newspaper/ireland.rss'), + ('World', 'http://www.irishtimes.com/feeds/rss/newspaper/world.rss'), + ('Finance', 'http://www.irishtimes.com/feeds/rss/newspaper/finance.rss'), + ('Features', 'http://www.irishtimes.com/feeds/rss/newspaper/features.rss'), + ('Sport', 'http://www.irishtimes.com/feeds/rss/newspaper/sport.rss'), + ('Opinion', 'http://www.irishtimes.com/feeds/rss/newspaper/opinion.rss'), + ('Letters', 'http://www.irishtimes.com/feeds/rss/newspaper/letters.rss'), + ] + + + def print_version(self, url): + return url.replace('.html', '_pf.html') + + def get_article_url(self, article): + m = self.r.match(article.get('description', None)) + print m.group('url') + return m.group('url') \ No newline at end of file From c01b8454f59e3d9016952540616cfb5789a1739f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 12 Aug 2009 11:50:09 -0600 Subject: [PATCH 04/15] IGN:PRS500 driver: Fix card function to not raise an exception when no card is present --- src/calibre/devices/prs500/driver.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/calibre/devices/prs500/driver.py b/src/calibre/devices/prs500/driver.py index 73dd5b543d..4273101273 100644 --- a/src/calibre/devices/prs500/driver.py +++ b/src/calibre/devices/prs500/driver.py @@ -794,10 +794,16 @@ class PRS500(DeviceConfig, DevicePlugin): def card(self, end_session=True): """ Return path prefix to installed card or None """ card = None - if self._exists("a:/")[0]: - card = "a:" - if self._exists("b:/")[0]: - card = "b:" + try: + if self._exists("a:/")[0]: + card = "a:" + except: + pass + try: + if self._exists("b:/")[0]: + card = "b:" + except: + pass return card @safe From 1f349f330ee4d6827bce7d8ec4841af359429ceb Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 12 Aug 2009 14:06:52 -0600 Subject: [PATCH 05/15] IGN:Improve X server detection --- src/calibre/gui2/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 0fd4054763..586424dc4c 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -538,7 +538,7 @@ class Application(QApplication): def is_ok_to_use_qt(): global gui_thread - if islinux and os.environ.get('DISPLAY', None) is None: + if islinux and ':' in os.environ.get('DISPLAY', ''): return False if QApplication.instance() is None: QApplication([]) From 30735c58854d16bbe055c7b996142af29f0131d4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 13 Aug 2009 11:16:27 -0600 Subject: [PATCH 06/15] New recipe for De Volksrant by acidzebra, updated recipe for The Chicago Tribune. Add the the CyBook Opus to the welcome wizard. Fix #3146 (More formats for Bebook/lBook etc) --- src/calibre/customize/profiles.py | 3 +- src/calibre/devices/bebook/driver.py | 2 +- src/calibre/gui2/__init__.py | 2 +- src/calibre/gui2/wizard/__init__.py | 1 + src/calibre/web/feeds/recipes/__init__.py | 1 + .../feeds/recipes/recipe_chicago_tribune.py | 76 +++++++++++-------- .../web/feeds/recipes/recipe_volksrant.py | 34 +++++++++ 7 files changed, 83 insertions(+), 36 deletions(-) create mode 100644 src/calibre/web/feeds/recipes/recipe_volksrant.py diff --git a/src/calibre/customize/profiles.py b/src/calibre/customize/profiles.py index 757cd09b19..df774bcb55 100644 --- a/src/calibre/customize/profiles.py +++ b/src/calibre/customize/profiles.py @@ -270,7 +270,7 @@ class CybookG3Output(OutputProfile): fbase = 16 fsizes = [12, 12, 14, 16, 18, 20, 22, 24] -class CybookOpusOutput(OutputProfile): +class CybookOpusOutput(SonyReaderOutput): author = 'John Schember' name = 'Cybook Opus' @@ -278,7 +278,6 @@ class CybookOpusOutput(OutputProfile): description = _('This profile is intended for the Cybook Opus.') # Screen size is a best guess - screen_size = (600, 800) dpi = 200 fbase = 16 fsizes = [12, 12, 14, 16, 18, 20, 22, 24] diff --git a/src/calibre/devices/bebook/driver.py b/src/calibre/devices/bebook/driver.py index 1542346955..4f5423a93d 100644 --- a/src/calibre/devices/bebook/driver.py +++ b/src/calibre/devices/bebook/driver.py @@ -20,7 +20,7 @@ class BEBOOK(USBMS): supported_platforms = ['windows', 'osx', 'linux'] # Ordered list of supported formats - FORMATS = ['mobi', 'epub', 'pdf', 'rtf', 'txt'] + FORMATS = ['mobi', 'epub', 'fb2', 'lit', 'prc', 'pdf', 'rtf', 'txt'] VENDOR_ID = [0x0525] PRODUCT_ID = [0x8803, 0x6803] diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 586424dc4c..a00431460e 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -181,7 +181,7 @@ def question_dialog(parent, title, msg, det_msg=''): return d.exec_() == QMessageBox.Yes def info_dialog(parent, title, msg, det_msg='', show=False): - d = MessageBox(QMessageBox.Information, title, msg, QMessageBox.NoButton, + d = MessageBox(QMessageBox.Information, title, msg, QMessageBox.Ok, parent, det_msg) d.setIconPixmap(QPixmap(':/images/dialog_information.svg')) if show: diff --git a/src/calibre/gui2/wizard/__init__.py b/src/calibre/gui2/wizard/__init__.py index 8610d8bba7..68e866e7e1 100644 --- a/src/calibre/gui2/wizard/__init__.py +++ b/src/calibre/gui2/wizard/__init__.py @@ -104,6 +104,7 @@ class CybookOpus(CybookG3): name = 'Cybook Opus' output_format = 'EPUB' + output_profile = 'cybook_opus' id = 'cybook_opus' class BeBook(Device): diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py index 6e94a3bef8..2dcc48b240 100644 --- a/src/calibre/web/feeds/recipes/__init__.py +++ b/src/calibre/web/feeds/recipes/__init__.py @@ -53,6 +53,7 @@ recipe_modules = ['recipe_' + r for r in ( 'gva_be', 'hln', 'tijd', 'degentenaar', 'inquirer_net', 'uncrate', 'fastcompany', 'accountancyage', 'laprensa_hn', 'latribuna', 'eltiempo_hn', 'slate', 'tnxm', 'bbcvietnamese', 'vnexpress', + 'volksrant', 'theeconomictimes_india', )] diff --git a/src/calibre/web/feeds/recipes/recipe_chicago_tribune.py b/src/calibre/web/feeds/recipes/recipe_chicago_tribune.py index 17608f9ca5..7c747003d2 100644 --- a/src/calibre/web/feeds/recipes/recipe_chicago_tribune.py +++ b/src/calibre/web/feeds/recipes/recipe_chicago_tribune.py @@ -12,14 +12,35 @@ from threading import RLock class ChicagoTribune(BasicNewsRecipe): title = 'Chicago Tribune' - __author__ = 'Kovid Goyal' + __author__ = 'Kovid Goyal and Sujata Raman' description = 'Politics, local and business news from Chicago' language = _('English') use_embedded_content = False - articles_are_obfuscated = True - remove_tags_before = dict(name='h1') - obfuctation_lock = RLock() + no_stylesheets = True + remove_javascript = True + keep_only_tags = [dict(name='div', attrs={'class':["story","entry-asset asset hentry"]}), + dict(name='div', attrs={'id':["pagebody","story","maincontentcontainer"]}), + ] + remove_tags_after = [ {'class':['photo_article',]} ] + + remove_tags = [{'id':["moduleArticleTools","content-bottom","rail","articleRelates module","toolSet","relatedrailcontent","div-wrapper","beta","atp-comments","footer"]}, + {'class':["clearfix","relatedTitle","articleRelates module","asset-footer","tools","comments","featurePromo","featurePromo fp-topjobs brownBackground","clearfix fullSpan brownBackground","curvedContent"]}, + dict(name='font',attrs={'id':["cr-other-headlines"]})] + extra_css = ''' + h1{font-family:Arial,Helvetica,sans-serif; font-weight:bold;font-size:large;} + h2{font-family:Arial,Helvetica,sans-serif; font-weight:normal;font-size:small;} + .byline {font-family:Arial,Helvetica,sans-serif; font-size:xx-small;} + .date {font-family:Arial,Helvetica,sans-serif; font-size:xx-small;} + p{font-family:Arial,Helvetica,sans-serif;font-size:small;} + .copyright {font-family:Arial,Helvetica,sans-serif;font-size:xx-small;text-align:center} + .story{font-family:Arial,Helvetica,sans-serif;font-size:small;} + .entry-asset asset hentry{font-family:Arial,Helvetica,sans-serif;font-size:small;} + .pagebody{font-family:Arial,Helvetica,sans-serif;font-size:small;} + .maincontentcontainer{font-family:Arial,Helvetica,sans-serif;font-size:small;} + .story-body{font-family:Arial,Helvetica,sans-serif;font-size:small;} + body{font-family:Helvetica,Arial,sans-serif;font-size:small;} + ''' feeds = [ ('Latest news', 'http://feeds.chicagotribune.com/chicagotribune/news/'), ('Local news', 'http://feeds.chicagotribune.com/chicagotribune/news/local/'), @@ -28,14 +49,14 @@ class ChicagoTribune(BasicNewsRecipe): ('Most E-mailed stories', 'http://feeds.chicagotribune.com/chicagotribune/email/'), ('Opinion', 'http://feeds.chicagotribune.com/chicagotribune/opinion/'), ('Off Topic', 'http://feeds.chicagotribune.com/chicagotribune/offtopic/'), - ('Politics', 'http://feeds.chicagotribune.com/chicagotribune/politics/'), - ('Special Reports', 'http://feeds.chicagotribune.com/chicagotribune/special/'), - ('Religion News', 'http://feeds.chicagotribune.com/chicagotribune/religion/'), + #('Politics', 'http://feeds.chicagotribune.com/chicagotribune/politics/'), + #('Special Reports', 'http://feeds.chicagotribune.com/chicagotribune/special/'), + #('Religion News', 'http://feeds.chicagotribune.com/chicagotribune/religion/'), ('Business news', 'http://feeds.chicagotribune.com/chicagotribune/business/'), ('Jobs and Careers', 'http://feeds.chicagotribune.com/chicagotribune/career/'), ('Local scene', 'http://feeds.chicagotribune.com/chicagohomes/localscene/'), ('Phil Rosenthal', 'http://feeds.chicagotribune.com/chicagotribune/rosenthal/'), - ('Tech Buzz', 'http://feeds.chicagotribune.com/chicagotribune/techbuzz/'), + #('Tech Buzz', 'http://feeds.chicagotribune.com/chicagotribune/techbuzz/'), ('Your Money', 'http://feeds.chicagotribune.com/chicagotribune/yourmoney/'), ('Jon Hilkevitch - Getting around', 'http://feeds.chicagotribune.com/chicagotribune/gettingaround/'), ('Jon Yates - What\'s your problem?', 'http://feeds.chicagotribune.com/chicagotribune/problem/'), @@ -44,39 +65,30 @@ class ChicagoTribune(BasicNewsRecipe): ('Sports', 'http://feeds.chicagotribune.com/chicagotribune/sports/'), ('Arts and Architecture', 'http://feeds.chicagotribune.com/chicagotribune/arts/'), ('Books', 'http://feeds.chicagotribune.com/chicagotribune/books/'), - ('Magazine', 'http://feeds.chicagotribune.com/chicagotribune/magazine/'), + #('Magazine', 'http://feeds.chicagotribune.com/chicagotribune/magazine/'), ('Movies', 'http://feeds.chicagotribune.com/chicagotribune/movies/'), - ('Music', 'http://feeds.chicagotribune.com/chicagotribune/movies/'), + ('Music', 'http://feeds.chicagotribune.com/chicagotribune/music/'), ('TV', 'http://feeds.chicagotribune.com/chicagotribune/tv/'), ('Hypertext', 'http://feeds.chicagotribune.com/chicagotribune/hypertext/'), ('iPhone Blog', 'http://feeds.feedburner.com/redeye/iphoneblog'), ('Julie\'s Health Club', 'http://feeds.chicagotribune.com/chicagotribune_julieshealthclub/'), ] - temp_files = [] def get_article_url(self, article): + print article.get('feedburner_origlink', article.get('guid', article.get('link'))) return article.get('feedburner_origlink', article.get('guid', article.get('link'))) - def get_obfuscated_article(self, url): - with self.obfuctation_lock: - soup = self.index_to_soup(url) - img = soup.find('img', alt='Print') - if img is not None: - a = img.parent.find('a', href=True) - purl = urlparse(url) - xurl = urlunparse(purl[:2] + (a['href'], '', '', '')) - soup = self.index_to_soup(xurl) - for img in soup.findAll('img', src=True): - if img['src'].startswith('/'): - img['src'] = urlunparse(purl[:2]+(img['src'], '', '', '')) - html = unicode(soup) - else: - h1 = soup.find(id='page-title') - body = soup.find(attrs={'class':re.compile('asset-content')}) - html = u'%s'%(unicode(h1)+unicode(body)) - self.temp_files.append(PersistentTemporaryFile('_chicago_tribune.xhtml')) - self.temp_files[-1].write(html.encode('utf-8')) - self.temp_files[-1].close() - return self.temp_files[-1].name + + def postprocess_html(self, soup, first_fetch): + for t in soup.findAll(['table', 'tr', 'td']): + t.name = 'div' + + for tag in soup.findAll('form', dict(attrs={'name':["comments_form"]})): + tag.extract() + for tag in soup.findAll('font', dict(attrs={'id':["cr-other-headlines"]})): + tag.extract() + + return soup + diff --git a/src/calibre/web/feeds/recipes/recipe_volksrant.py b/src/calibre/web/feeds/recipes/recipe_volksrant.py new file mode 100644 index 0000000000..d95cbdb1c7 --- /dev/null +++ b/src/calibre/web/feeds/recipes/recipe_volksrant.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import with_statement + +__license__ = 'GPL v3' +__copyright__ = '2009, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from calibre.web.feeds.news import BasicNewsRecipe + +class AdvancedUserRecipe1249039563(BasicNewsRecipe): + title = u'De Volkskrant' + __author__ = 'acidzebra' + oldest_article = 7 + max_articles_per_feed = 100 + no_stylesheets = True + language = _('Dutch') + keep_only_tags = [dict(name='div', attrs={'id':'leftColumnArticle'}) ] + remove_tags = [ + dict(name='div',attrs={'class':'article_tools'}), + dict(name='div',attrs={'id':'article_tools'}), + dict(name='div',attrs={'class':'articletools'}), + dict(name='div',attrs={'id':'articletools'}), + dict(name='div',attrs={'id':'myOverlay'}), + dict(name='div',attrs={'id':'trackback'}), + dict(name='div',attrs={'id':'googleBanner'}), + dict(name='div',attrs={'id':'article_headlines'}), + ] + extra_css = ''' + body{font-family:Arial,Helvetica,sans-serif; font-size:small;} + h1{font-size:large;} + ''' + + feeds = [(u'Laatste Nieuws', u'http://volkskrant.nl/rss/laatstenieuws.rss'), (u'Binnenlands nieuws', u'http://volkskrant.nl/rss/nederland.rss'), (u'Buitenlands nieuws', u'http://volkskrant.nl/rss/internationaal.rss'), (u'Economisch nieuws', u'http://volkskrant.nl/rss/economie.rss'), (u'Sportnieuws', u'http://volkskrant.nl/rss/sport.rss'), (u'Kunstnieuws', u'http://volkskrant.nl/rss/kunst.rss'), (u'Wetenschapsnieuws', u'http://feeds.feedburner.com/DeVolkskrantWetenschap'), (u'Technologienieuws', u'http://feeds.feedburner.com/vkmedia')] From 34b238a3a35d32dd2d78d4cd036f82bab26b9b31 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 13 Aug 2009 12:07:26 -0600 Subject: [PATCH 07/15] Fix #3144 ("Comments" string showing spurious & in the preview box) --- src/calibre/gui2/dialogs/metadata_single.ui | 2 +- src/calibre/translations/calibre.pot | 159 +++++++++++++------- 2 files changed, 106 insertions(+), 55 deletions(-) diff --git a/src/calibre/gui2/dialogs/metadata_single.ui b/src/calibre/gui2/dialogs/metadata_single.ui index 15ac6b201d..f7cd6738d0 100644 --- a/src/calibre/gui2/dialogs/metadata_single.ui +++ b/src/calibre/gui2/dialogs/metadata_single.ui @@ -381,7 +381,7 @@ - Comments + &Comments diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot index 3e19a726f6..5f9f802249 100644 --- a/src/calibre/translations/calibre.pot +++ b/src/calibre/translations/calibre.pot @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: calibre 0.6.6\n" -"POT-Creation-Date: 2009-08-11 11:45+MDT\n" -"PO-Revision-Date: 2009-08-11 11:45+MDT\n" +"POT-Creation-Date: 2009-08-13 12:06+MDT\n" +"PO-Revision-Date: 2009-08-13 12:06+MDT\n" "Last-Translator: Automatically generated\n" "Language-Team: LANGUAGE\n" "MIME-Version: 1.0\n" @@ -24,8 +24,8 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/devices/kindle/driver.py:52 #: /home/kovid/work/calibre/src/calibre/devices/prs505/books.py:58 #: /home/kovid/work/calibre/src/calibre/devices/prs505/books.py:199 -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:697 #: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:701 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:705 #: /home/kovid/work/calibre/src/calibre/ebooks/comic/input.py:403 #: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:66 #: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:68 @@ -40,6 +40,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/__init__.py:350 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/ereader.py:23 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/ereader.py:45 +#: /home/kovid/work/calibre/src/calibre/ebooks/metadata/fb2.py:46 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/meta.py:36 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/meta.py:61 #: /home/kovid/work/calibre/src/calibre/ebooks/metadata/meta.py:63 @@ -266,17 +267,17 @@ msgid "This profile is intended for the Cybook Opus." msgstr "" #: /home/kovid/work/calibre/src/calibre/customize/profiles.py:130 -#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:290 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:289 msgid "This profile is intended for the Amazon Kindle." msgstr "" #: /home/kovid/work/calibre/src/calibre/customize/profiles.py:142 -#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:323 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:322 msgid "This profile is intended for the Irex Illiad." msgstr "" #: /home/kovid/work/calibre/src/calibre/customize/profiles.py:154 -#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:336 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:335 msgid "This profile is intended for the IRex Digital Reader 1000." msgstr "" @@ -296,7 +297,7 @@ msgstr "" msgid "This profile is intended for the SONY PRS line. The 500/505/700 etc, in landscape mode. Mainly useful for comics." msgstr "" -#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:307 +#: /home/kovid/work/calibre/src/calibre/customize/profiles.py:306 msgid "This profile is intended for the Amazon Kindle DX." msgstr "" @@ -465,7 +466,7 @@ msgid "Communicate with the Sony PRS-505 eBook reader." msgstr "" #: /home/kovid/work/calibre/src/calibre/devices/prs505/driver.py:26 -#: /home/kovid/work/calibre/src/calibre/devices/prs700/driver.py:17 +#: /home/kovid/work/calibre/src/calibre/devices/prs700/driver.py:18 msgid "Kovid Goyal and John Schember" msgstr "" @@ -481,47 +482,47 @@ msgstr "" msgid "Sending metadata to device..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/prs700/driver.py:16 +#: /home/kovid/work/calibre/src/calibre/devices/prs700/driver.py:17 msgid "Communicate with the Sony PRS-700 eBook reader." msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:278 -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:350 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:282 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:354 msgid "Unable to detect the %s disk drive. Try rebooting." msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:418 -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:523 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:422 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:527 msgid "Unable to detect the %s disk drive." msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:511 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:515 msgid "Could not find mount helper: %s." msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:530 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:534 msgid "Unable to mount main memory (Error code: %d)" msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:635 -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:637 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:639 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:641 msgid "The reader has no storage card in this slot." msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:639 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:643 msgid "Selected slot: %s is not supported." msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:663 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:667 msgid "There is insufficient free space in main memory" msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:665 -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:667 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:669 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:671 msgid "There is insufficient free space on the storage card" msgstr "" -#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:677 +#: /home/kovid/work/calibre/src/calibre/devices/usbms/device.py:681 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/scheduler.py:467 #: /home/kovid/work/calibre/src/calibre/gui2/tag_view.py:83 #: /home/kovid/work/calibre/src/calibre/library/database2.py:1006 @@ -939,10 +940,25 @@ msgstr "" msgid "Normally, if the input file ahs no cover and you don't specify one, a default cover is generated with the title, authors, etc. This option disables the generation of this cover." msgstr "" +#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/fb2ml.py:123 +#: /home/kovid/work/calibre/src/calibre/ebooks/pml/pmlml.py:111 +#: /home/kovid/work/calibre/src/calibre/ebooks/rb/rbml.py:98 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/txtml.py:70 +msgid "Table of Contents:" +msgstr "" + #: /home/kovid/work/calibre/src/calibre/ebooks/fb2/input.py:32 msgid "Do not insert a Table of Contents at the beginning of the book." msgstr "" +#: /home/kovid/work/calibre/src/calibre/ebooks/fb2/output.py:21 +#: /home/kovid/work/calibre/src/calibre/ebooks/pdb/output.py:32 +#: /home/kovid/work/calibre/src/calibre/ebooks/pml/output.py:37 +#: /home/kovid/work/calibre/src/calibre/ebooks/rb/output.py:21 +#: /home/kovid/work/calibre/src/calibre/ebooks/txt/output.py:35 +msgid "Add Table of Contents to begenning of the book." +msgstr "" + #: /home/kovid/work/calibre/src/calibre/ebooks/html/input.py:242 msgid "Traverse links in HTML files breadth first. Normally, they are traversed depth first." msgstr "" @@ -1244,7 +1260,6 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:183 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info.py:71 #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/book_info_ui.py:64 -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:363 #: /home/kovid/work/calibre/src/calibre/gui2/library.py:349 #: /home/kovid/work/calibre/src/calibre/gui2/status.py:58 msgid "Comments" @@ -1580,7 +1595,6 @@ msgid "Format to use inside the pdb container. Choices are:" msgstr "" #: /home/kovid/work/calibre/src/calibre/ebooks/pdb/output.py:27 -#: /home/kovid/work/calibre/src/calibre/ebooks/pml/output.py:33 msgid "Specify the character encoding of the output document. The default is cp1252. Note: This option is not honored by all formats." msgstr "" @@ -1782,6 +1796,10 @@ msgstr "" msgid "Could not find pdftohtml, check it is in your PATH" msgstr "" +#: /home/kovid/work/calibre/src/calibre/ebooks/pml/output.py:33 +msgid "Specify the character encoding of the output document. The default is cp1252." +msgstr "" + #: /home/kovid/work/calibre/src/calibre/ebooks/rtf/input.py:108 msgid "This RTF file has a feature calibre does not support. Convert it to HTML first and then try it." msgstr "" @@ -1888,7 +1906,7 @@ msgid "Default action to perform when send to device button is clicked" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/__init__.py:113 -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:396 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:397 msgid "Copied" msgstr "" @@ -1956,11 +1974,13 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input.py:16 #: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16 #: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input.py:13 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output.py:15 #: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:20 #: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:16 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:17 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input.py:13 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output.py:18 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output.py:15 #: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input.py:13 #: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:17 msgid "Options specific to" @@ -1976,18 +1996,20 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/comic_input_ui.py:76 #: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output_ui.py:41 #: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_input_ui.py:28 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output_ui.py:28 #: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel_ui.py:88 #: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output_ui.py:115 #: /home/kovid/work/calibre/src/calibre/gui2/convert/metadata_ui.py:165 #: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output_ui.py:44 #: /home/kovid/work/calibre/src/calibre/gui2/convert/page_setup_ui.py:110 -#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:31 -#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:37 -#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:37 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:35 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:38 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:39 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output_ui.py:28 #: /home/kovid/work/calibre/src/calibre/gui2/convert/structure_detection_ui.py:71 #: /home/kovid/work/calibre/src/calibre/gui2/convert/toc_ui.py:61 #: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_input_ui.py:28 -#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:31 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:35 #: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_edit_ui.py:41 #: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_wizard_ui.py:67 #: /home/kovid/work/calibre/src/calibre/gui2/device_drivers/configwidget_ui.py:59 @@ -2056,10 +2078,12 @@ msgid "EPUB Output" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/epub_output.py:16 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output.py:15 #: /home/kovid/work/calibre/src/calibre/gui2/convert/lrf_output.py:20 #: /home/kovid/work/calibre/src/calibre/gui2/convert/mobi_output.py:16 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output.py:17 #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output.py:18 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output.py:15 #: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output.py:17 msgid "output" msgstr "" @@ -2088,6 +2112,17 @@ msgstr "" msgid "Do not insert a &Table of Contents at the beginning of the book." msgstr "" +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output.py:14 +msgid "FB2 Output" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/convert/fb2_output_ui.py:29 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:37 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output_ui.py:29 +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:37 +msgid "&Inline TOC" +msgstr "" + #: /home/kovid/work/calibre/src/calibre/gui2/convert/look_and_feel.py:15 msgid "Look & Feel" msgstr "" @@ -2421,32 +2456,36 @@ msgstr "" msgid "PDB Output" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:32 -msgid "Format:" +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdb_output_ui.py:36 +msgid "&Format:" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input.py:12 msgid "PDF Input" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:38 -msgid "Line Un-Wrapping Factor:" +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:39 +msgid "Line &Un-Wrapping Factor:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:39 -msgid "No Images" +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_input_ui.py:40 +msgid "No &Images" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output.py:17 msgid "PDF Output" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:38 -msgid "Paper Size:" +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:40 +msgid "&Paper Size:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:39 -msgid "Orientation:" +#: /home/kovid/work/calibre/src/calibre/gui2/convert/pdf_output_ui.py:41 +msgid "&Orientation:" +msgstr "" + +#: /home/kovid/work/calibre/src/calibre/gui2/convert/rb_output.py:14 +msgid "RB Output" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/single.py:137 @@ -2625,8 +2664,8 @@ msgstr "" msgid "TXT Output" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:32 -msgid "Line ending style:" +#: /home/kovid/work/calibre/src/calibre/gui2/convert/txt_output_ui.py:36 +msgid "&Line ending style:" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/convert/xpath_edit_ui.py:42 @@ -3084,7 +3123,7 @@ msgid "Failed to start content server" msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/config.py:662 -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:468 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:469 msgid "Select location for books" msgstr "" @@ -3653,6 +3692,10 @@ msgstr "" msgid "MMM yyyy" msgstr "" +#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:363 +msgid "&Comments" +msgstr "" + #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:364 msgid "&Fetch metadata from server" msgstr "" @@ -5408,45 +5451,45 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:36 #: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:37 -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:148 #: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:149 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:150 msgid "Default" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:287 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:288 msgid "If you use the WordPlayer e-book app on your Android phone, you can access your calibre book collection directly on the device. To do this you have to turn on the content server." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:291 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:292 msgid "Remember to leave calibre running as the server only runs as long as calibre is running." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:293 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:294 msgid "You have to add the URL http://myhostname:8080 as your calibre library in WordPlayer. Here myhostname should be the fully qualified hostname or the IP address of the computer calibre is running on." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:370 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:371 msgid "Moving library..." msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:386 #: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:387 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:388 msgid "Failed to move library" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:440 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:441 msgid "Invalid database" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:441 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:442 msgid "

An invalid library already exists at %s, delete it before trying to move the existing library.
Error: %s" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:452 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:453 msgid "Could not move library" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:514 +#: /home/kovid/work/calibre/src/calibre/gui2/wizard/__init__.py:515 msgid "welcome wizard" msgstr "" @@ -6191,7 +6234,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_iht.py:15 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_indy_star.py:6 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_inquirer_net.py:24 -#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_irish_times.py:12 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_irish_times.py:13 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_japan_times.py:15 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_joelonsoftware.py:15 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_jpost.py:8 @@ -6234,7 +6277,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_seattle_times.py:22 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_security_watch.py:15 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_shacknews.py:10 -#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_slashdot.py:15 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_slashdot.py:14 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_slate.py:29 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_smh.py:19 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_soldiers.py:26 @@ -6273,6 +6316,13 @@ msgstr "" msgid "English" msgstr "" +#: +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_bbcvietnamese.py:16 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_tnxm.py:16 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_vnexpress.py:16 +msgid "Vietnamese" +msgstr "" + #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_carta.py:24 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_der_standard.py:22 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_diepresse.py:23 @@ -6313,6 +6363,7 @@ msgstr "" #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_gva_be.py:22 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_hln.py:22 #: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_tijd.py:22 +#: /home/kovid/work/calibre/src/calibre/web/feeds/recipes/recipe_volksrant.py:17 msgid "Dutch" msgstr "" From 20468383df3d10669cb4693fc7b41360ce49d392 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 14 Aug 2009 09:52:21 -0600 Subject: [PATCH 08/15] EPUB Output: Replace all whitespace in TOC items with spaces, as desktop ADE does not support non space characters. --- src/calibre/ebooks/oeb/base.py | 5 ++++- src/calibre/gui2/viewer/main.py | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py index 6ef95f62d7..06220b8afa 100644 --- a/src/calibre/ebooks/oeb/base.py +++ b/src/calibre/ebooks/oeb/base.py @@ -1543,7 +1543,10 @@ class TOC(object): attrib['class'] = node.klass point = element(parent, NCX('navPoint'), attrib=attrib) label = etree.SubElement(point, NCX('navLabel')) - element(label, NCX('text')).text = node.title + title = node.title + if title: + title = re.sub(r'\s', ' ', title) + element(label, NCX('text')).text = title element(point, NCX('content'), src=urlunquote(node.href)) node.to_ncx(point) return parent diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index d29d4a9272..6cf9f5c19f 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -1,7 +1,7 @@ from __future__ import with_statement __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal ' -import traceback, os, sys, functools, collections +import traceback, os, sys, functools, collections, re from functools import partial from threading import Thread @@ -28,7 +28,10 @@ from calibre.customize.ui import available_input_formats class TOCItem(QStandardItem): def __init__(self, toc): - QStandardItem.__init__(self, toc.text if toc.text else '') + text = toc.text + if text: + text = re.sub(r'\s', ' ', text) + QStandardItem.__init__(self, text if text else '') self.abspath = toc.abspath self.fragment = toc.fragment for t in toc: From 6ad621a920578375d5f0d35e1285421a8ca35907 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 14 Aug 2009 09:57:27 -0600 Subject: [PATCH 09/15] New recipe for Our Daily Bread by Darko Miletic --- src/calibre/web/feeds/recipes/__init__.py | 2 +- .../web/feeds/recipes/recipe_ourdailybread.py | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/calibre/web/feeds/recipes/recipe_ourdailybread.py diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py index 2dcc48b240..1588a4c8ab 100644 --- a/src/calibre/web/feeds/recipes/__init__.py +++ b/src/calibre/web/feeds/recipes/__init__.py @@ -53,7 +53,7 @@ recipe_modules = ['recipe_' + r for r in ( 'gva_be', 'hln', 'tijd', 'degentenaar', 'inquirer_net', 'uncrate', 'fastcompany', 'accountancyage', 'laprensa_hn', 'latribuna', 'eltiempo_hn', 'slate', 'tnxm', 'bbcvietnamese', 'vnexpress', - 'volksrant', 'theeconomictimes_india', + 'volksrant', 'theeconomictimes_india', 'ourdailybread', )] diff --git a/src/calibre/web/feeds/recipes/recipe_ourdailybread.py b/src/calibre/web/feeds/recipes/recipe_ourdailybread.py new file mode 100644 index 0000000000..12e3528af8 --- /dev/null +++ b/src/calibre/web/feeds/recipes/recipe_ourdailybread.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python + +__license__ = 'GPL v3' +__copyright__ = '2009, Darko Miletic ' +''' +rbc.org +''' + +from calibre.web.feeds.news import BasicNewsRecipe + +class OurDailyBread(BasicNewsRecipe): + title = 'Our Daily Bread' + __author__ = 'Darko Miletic' + description = 'Religion' + oldest_article = 15 + language = _('English') + max_articles_per_feed = 100 + no_stylesheets = True + use_embedded_content = False + category = 'religion' + encoding = 'utf-8' + extra_css = ' #devoTitle{font-size: x-large; font-weight: bold} ' + + conversion_options = { + 'comments' : description + ,'tags' : category + ,'language' : 'en' + } + + keep_only_tags = [dict(name='div', attrs={'class':['altbg','text']})] + + feeds = [(u'Our Daily Bread', u'http://www.rbc.org/rss.ashx?id=50398')] + + def preprocess_html(self, soup): + return self.adeify_images(soup) From 5c2ca385b5df1aea502d0ef6d4dc9af7101ebbbe Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 14 Aug 2009 10:04:44 -0600 Subject: [PATCH 10/15] calibredb:Don't error out when listing books that have missing formats --- src/calibre/library/cli.py | 3 ++- src/calibre/library/database2.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index 75f72297a4..1ac82b2edb 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -126,7 +126,8 @@ def do_list(db, fields, sort_by, ascending, search_text, line_width, separator, fields = ['id'] + fields if output_format == 'text': for f in data: - f['formats'] = u'[%s]'%u','.join(f['formats']) + fmts = [x for x in f['formats'] if x is not None] + f['formats'] = u'[%s]'%u','.join(fmts) widths = list(map(lambda x : 0, fields)) for record in data: for f in record.keys(): diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 194933bb3a..18765e3e3c 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1525,6 +1525,8 @@ class LibraryDatabase2(LibraryDatabase): if formats: for fmt in formats.split(','): path = self.format_abspath(x['id'], fmt, index_is_id=True) + if path is None: + continue if prefix != self.library_path: path = os.path.relpath(path, self.library_path) path = os.path.join(prefix, path) From 831ce503f4f9c840085c1389a041938d5b535bd2 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 14 Aug 2009 10:05:39 -0600 Subject: [PATCH 11/15] IGN:Fix 'MMM yyyy' should not be translated. --- src/calibre/translations/calibre.pot | 8 ++------ upload.py | 1 + 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/calibre/translations/calibre.pot b/src/calibre/translations/calibre.pot index 5f9f802249..a2ad07245c 100644 --- a/src/calibre/translations/calibre.pot +++ b/src/calibre/translations/calibre.pot @@ -5,8 +5,8 @@ msgid "" msgstr "" "Project-Id-Version: calibre 0.6.6\n" -"POT-Creation-Date: 2009-08-13 12:06+MDT\n" -"PO-Revision-Date: 2009-08-13 12:06+MDT\n" +"POT-Creation-Date: 2009-08-13 12:30+MDT\n" +"PO-Revision-Date: 2009-08-13 12:30+MDT\n" "Last-Translator: Automatically generated\n" "Language-Team: LANGUAGE\n" "MIME-Version: 1.0\n" @@ -3688,10 +3688,6 @@ msgstr "" msgid "Publishe&d:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:362 -msgid "MMM yyyy" -msgstr "" - #: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:363 msgid "&Comments" msgstr "" diff --git a/upload.py b/upload.py index 0bbe98e9fa..0ce3d1ef4c 100644 --- a/upload.py +++ b/upload.py @@ -344,6 +344,7 @@ class gui(OptionlessCommand): dat = dat.replace('from convert.xpath_wizard import', 'from calibre.gui2.convert.xpath_wizard import') dat = re.compile(r'QtGui.QApplication.translate\(.+?,\s+"(.+?)(? Date: Fri, 14 Aug 2009 10:27:47 -0600 Subject: [PATCH 12/15] IGN:Fix typo that was preventing EPUB Output from working in absence of X server --- src/calibre/ebooks/epub/output.py | 3 +-- src/calibre/gui2/__init__.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/epub/output.py b/src/calibre/ebooks/epub/output.py index ef1b9db088..986d1bff24 100644 --- a/src/calibre/ebooks/epub/output.py +++ b/src/calibre/ebooks/epub/output.py @@ -161,10 +161,8 @@ class EPUBOutput(OutputFormatPlugin): ) split(self.oeb, self.opts) - self.workaround_ade_quirks() self.workaround_webkit_quirks() - from calibre.ebooks.oeb.transforms.rescale import RescaleImages RescaleImages()(oeb, opts) self.insert_cover() @@ -194,6 +192,7 @@ class EPUBOutput(OutputFormatPlugin): ''' if self.opts.no_default_epub_cover: return None + self.log('Generating default cover') try: from calibre.gui2 import images_rc, is_ok_to_use_qt # Needed for access to logo from PyQt4.Qt import QFile, QIODevice diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index a00431460e..e09a54501c 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -538,7 +538,7 @@ class Application(QApplication): def is_ok_to_use_qt(): global gui_thread - if islinux and ':' in os.environ.get('DISPLAY', ''): + if islinux and ':' not in os.environ.get('DISPLAY', ''): return False if QApplication.instance() is None: QApplication([]) From 00c32f1a2a5e6003136775068b23472407dfc089 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 14 Aug 2009 10:32:02 -0600 Subject: [PATCH 13/15] calibredb:Fix bug when add books recursively from the command line --- src/calibre/ebooks/metadata/meta.py | 2 +- src/calibre/library/database2.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calibre/ebooks/metadata/meta.py b/src/calibre/ebooks/metadata/meta.py index 7c89a9bc0d..28dcbf5ae0 100644 --- a/src/calibre/ebooks/metadata/meta.py +++ b/src/calibre/ebooks/metadata/meta.py @@ -31,7 +31,7 @@ def metadata_from_formats(formats): try: return _metadata_from_formats(formats) except: - mi = metadata_from_filename(list(formats)[0]) + mi = metadata_from_filename(list(iter(formats))[0]) if not mi.authors: mi.authors = [_('Unknown')] diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 18765e3e3c..149e92ddf9 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -1764,7 +1764,7 @@ books_series_link feeds formats = self.find_books_in_directory(dirpath, True) if not formats: return - formats = list(formats) + formats = list(iter(formats)) mi = metadata_from_formats(formats) if mi.title is None: return From 207a9728c024ece842d0130c1e840227eafecd51 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 14 Aug 2009 11:47:05 -0600 Subject: [PATCH 14/15] IGN:Proper error messages when mimagemagick fails to load. Also workaround occasional IOError when sendingfiles to devices on linux --- src/calibre/devices/usbms/cli.py | 16 ++++++++++++++- src/calibre/utils/PythonMagickWand.py | 28 +++++++++++++-------------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/calibre/devices/usbms/cli.py b/src/calibre/devices/usbms/cli.py index 33fd9e752d..67d457efe1 100644 --- a/src/calibre/devices/usbms/cli.py +++ b/src/calibre/devices/usbms/cli.py @@ -24,6 +24,12 @@ class File(object): self.name = os.path.basename(path) +def check_transfer(infile, dest): + infile.seek(0) + dest.seek(0) + return infile.read() == dest.read() + + class CLI(object): def get_file(self, path, outfile, end_session=True): @@ -45,7 +51,15 @@ class CLI(object): if not os.path.exists(d): os.makedirs(d) with open(path, 'wb') as dest: - shutil.copyfileobj(infile, dest) + try: + shutil.copyfileobj(infile, dest) + except IOError: + print 'WARNING: First attempt to send file to device failed' + infile.seek(0) + dest.seek(0) + dest.truncate() + shutil.copyfileobj(infile, dest) + #if not check_transfer(infile, dest): raise Exception('Transfer failed') if close: infile.close() diff --git a/src/calibre/utils/PythonMagickWand.py b/src/calibre/utils/PythonMagickWand.py index 3c83ab4680..637f11da87 100644 --- a/src/calibre/utils/PythonMagickWand.py +++ b/src/calibre/utils/PythonMagickWand.py @@ -62,7 +62,7 @@ and save it to a new file. >>> MagickWriteImage(wand,"out.png") #doctest: +ELLIPSIS - >>> + >>> """ @@ -82,14 +82,15 @@ else: _lib = util.find_library('MagickWand') if _lib is None: _lib = util.find_library('Wand') - + _magick = _magick_error = None try: _magick = ctypes.CDLL(_lib) except Exception, err: - _magick_erorr = str(err) + global _magick_error + _magick_error = str(err) -_initialized = False +_initialized = False def initialize(): global _initialized if not _initialized: @@ -97,22 +98,22 @@ def initialize(): _magick.MagickWandGenesis() else: raise RuntimeError('Failed to load ImageMagick: %s'%_magick_error) - + def finalize(): global _initialized if _initialized: _magick.MagickWandTerminus() _initialized = False - + class ImageMagick(object): - + def __enter__(self): initialize() - + def __exit__(self, *args): finalize() - - + + class MetricType(ctypes.c_int): pass UndefinedMetric = MetricType(0) AbsoluteErrorMetric = MetricType(1) @@ -489,7 +490,7 @@ SetEvaluateOperator = MagickEvaluateOperator(10) SubtractEvaluateOperator = MagickEvaluateOperator(11) XorEvaluateOperator = MagickEvaluateOperator(12) -class ExceptionType(ctypes.c_int): +class ExceptionType(ctypes.c_int): pass UndefinedException = ExceptionType(0) @@ -4360,9 +4361,8 @@ try: except AttributeError,e: pass else: - PixelSetColor = _magick.PixelSetColor - - + PixelSetColor = _magick.PixelSetColor + if __name__=='__main__': import doctest doctest.testmod() From a8f065d38fdd5363142ed47232384eb7d914cb19 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 14 Aug 2009 13:55:33 -0600 Subject: [PATCH 15/15] EPUB Output: Close self closing tags explicitly as they cause problems in browser based renderers like the calibre ebook viewer. Fix #3152 (MOBI Error) --- src/calibre/__init__.py | 3 ++- src/calibre/ebooks/oeb/base.py | 2 +- src/calibre/manual/faq.rst | 9 +++++++++ src/calibre/utils/filenames.py | 11 ++++++++--- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index 5219159cef..ad8f10ae06 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -88,7 +88,8 @@ def sanitize_file_name(name, substitute='_', as_unicode=False): one = re.sub(r'^\.+$', '_', one) if as_unicode: one = one.decode(filesystem_encoding) - return one.replace('..', '_') + one = one.replace('..', substitute) + return one def prints(*args, **kwargs): diff --git a/src/calibre/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py index 06220b8afa..3f9e6a4d4a 100644 --- a/src/calibre/ebooks/oeb/base.py +++ b/src/calibre/ebooks/oeb/base.py @@ -1016,7 +1016,7 @@ class Manifest(object): if isinstance(data, etree._Element): ans = xml2str(data, pretty_print=self.oeb.pretty_print) if self.media_type in OEB_DOCS: - ans = re.sub(r'<(div|a)([^>]*)/>', r'<\1\2>', ans) + ans = re.sub(r'<(div|a|span)([^>]*)/>', r'<\1\2>', ans) return ans if isinstance(data, unicode): return data.encode('utf-8') diff --git a/src/calibre/manual/faq.rst b/src/calibre/manual/faq.rst index dc1563e579..fb8d378bd8 100644 --- a/src/calibre/manual/faq.rst +++ b/src/calibre/manual/faq.rst @@ -103,6 +103,15 @@ First install the Stanza reader on your iPhone from http://www.lexcycle.com . Th Now you should be able to access your books on your iPhone. +Why is my device not detected in linux? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +|app| uses something called SYSFS to detect devices in linux. The linux kernel can export two version of SYSFS, one of which is deprecated. Some linux distributions still ship with kernels that support the deprecated version of SYSFS, even though it was deprecated a long time ago. In this case, device detection in |app| will not work. You can check what version of SYSFS is exported by your kernel with the following command:: + + grep SYSFS_DEPRECATED /boot/config-`uname -r` + +You should see something like ``CONFIG_SYSFS_DEPRECATED_V2 is not set``. + Library Management ------------------ diff --git a/src/calibre/utils/filenames.py b/src/calibre/utils/filenames.py index ba10d6934e..0aab96522b 100644 --- a/src/calibre/utils/filenames.py +++ b/src/calibre/utils/filenames.py @@ -22,9 +22,14 @@ def ascii_text(orig): return ascii -def ascii_filename(orig): - return sanitize_file_name(ascii_text(orig).replace('?', '_')) - +def ascii_filename(orig, substitute='_'): + ans = [] + orig = ascii_text(orig).replace('?', '_') + for x in orig: + if ord(x) < 32: + x = substitute + ans.append(x) + return sanitize_file_name(''.join(ans), substitute=substitute) def supports_long_names(path): t = ('a'*300)+'.txt'