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/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/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 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' 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/devices/usbms/device.py b/src/calibre/devices/usbms/device.py index 5504136e0c..13085c5c70 100644 --- a/src/calibre/devices/usbms/device.py +++ b/src/calibre/devices/usbms/device.py @@ -42,6 +42,7 @@ class Device(DeviceConfig, DevicePlugin): WINDOWS_MAIN_MEM = None WINDOWS_CARD_A_MEM = None WINDOWS_CARD_B_MEM = None + ALLOW_NO_MAIN_MEMORY = False # The following are used by the check_ioreg_line method and can be either: # None, a string, a list of strings or a compiled regular expression @@ -266,6 +267,9 @@ class Device(DeviceConfig, DevicePlugin): drives['cardb'] = self.windows_get_drive_prefix(drive) elif self.windows_match_device(drive, 'WINDOWS_MAIN_MEM') and not drives.get('main', None): drives['main'] = self.windows_get_drive_prefix(drive) + if not self.ALLOW_NO_MAIN_MEMORY: + raise DeviceError('Failed to find the drive corresponding' + ' to the main memory') if 'main' in drives.keys() and 'carda' in drives.keys() and \ 'cardb' in drives.keys(): 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/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] 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/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/ebooks/oeb/base.py b/src/calibre/ebooks/oeb/base.py index 6ef95f62d7..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') @@ -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/__init__.py b/src/calibre/gui2/__init__.py index 0fd4054763..e09a54501c 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: @@ -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 ':' not in os.environ.get('DISPLAY', ''): return False if QApplication.instance() is None: QApplication([]) 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/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: 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/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..149e92ddf9 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) @@ -1762,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 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/translations/calibre.pot b/src/calibre/translations/calibre.pot index 3e19a726f6..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-11 11:45+MDT\n" -"PO-Revision-Date: 2009-08-11 11:45+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" @@ -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 "" @@ -3649,8 +3688,8 @@ msgstr "" msgid "Publishe&d:" msgstr "" -#: /home/kovid/work/calibre/src/calibre/gui2/dialogs/metadata_single_ui.py:362 -msgid "MMM yyyy" +#: /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 @@ -5408,45 +5447,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 +6230,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 +6273,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 +6312,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 +6359,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 "" 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() 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' diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py index 6e94a3bef8..1588a4c8ab 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', 'ourdailybread', )] 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_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 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) 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')] 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+"(.+?)(?