diff --git a/recipes/wsj.recipe b/recipes/wsj.recipe index a3bc041d25..7a044aa5a7 100644 --- a/recipes/wsj.recipe +++ b/recipes/wsj.recipe @@ -38,6 +38,7 @@ class WallStreetJournal(BasicNewsRecipe): dict(id=["articleTabs_tab_article", "articleTabs_tab_comments", "articleTabs_tab_interactive","articleTabs_tab_video","articleTabs_tab_map","articleTabs_tab_slideshow","articleTabs_tab_quotes","articleTabs_tab_document"]), {'class':['footer_columns','network','insetCol3wide','interactive','video','slideshow','map','insettip','insetClose','more_in', "insetContent", 'articleTools_bottom', 'aTools', "tooltip", "adSummary", "nav-inline"]}, dict(rel='shortcut icon'), + {'class':lambda x: x and 'sTools' in x}, ] remove_tags_after = [dict(id="article_story_body"), {'class':"article story"},] diff --git a/recipes/wsj_free.recipe b/recipes/wsj_free.recipe index dd42fb5540..331a393c03 100644 --- a/recipes/wsj_free.recipe +++ b/recipes/wsj_free.recipe @@ -40,6 +40,7 @@ class WallStreetJournal(BasicNewsRecipe): dict(name='div', attrs={'data-flash-settings':True}), {'class':['insetContent embedType-interactive insetCol3wide','insetCol6wide','insettipUnit']}, dict(rel='shortcut icon'), + {'class':lambda x: x and 'sTools' in x}, ] remove_tags_after = [dict(id="article_story_body"), {'class':"article story"},] diff --git a/resources/images/mimetypes/odt.png b/resources/images/mimetypes/odt.png index 8765b3eb0b..918be4d535 100644 Binary files a/resources/images/mimetypes/odt.png and b/resources/images/mimetypes/odt.png differ diff --git a/src/calibre/ebooks/metadata/meta.py b/src/calibre/ebooks/metadata/meta.py index b0c43a8182..3f3cc3e142 100644 --- a/src/calibre/ebooks/metadata/meta.py +++ b/src/calibre/ebooks/metadata/meta.py @@ -67,10 +67,6 @@ def _metadata_from_formats(formats, force_read_metadata=False, pattern=None): return mi -def is_recipe(filename): - return filename.startswith('calibre') and \ - filename.rpartition('.')[0].endswith('_recipe_out') - def get_metadata(stream, stream_type='lrf', use_libprs_metadata=False, force_read_metadata=False, pattern=None): pos = 0 @@ -106,7 +102,7 @@ def _get_metadata(stream, stream_type, use_libprs_metadata, mi = MetaInformation(None, None) name = os.path.basename(getattr(stream, 'name', '')) base = metadata_from_filename(name, pat=pattern) - if force_read_metadata or is_recipe(name) or prefs['read_file_metadata']: + if force_read_metadata or prefs['read_file_metadata']: mi = get_file_type_metadata(stream, stream_type) if base.title == os.path.splitext(name)[0] and \ base.is_null('authors') and base.is_null('isbn'): diff --git a/src/calibre/gui2/actions/save_to_disk.py b/src/calibre/gui2/actions/save_to_disk.py index 9e9cbe5f54..73f4367abc 100644 --- a/src/calibre/gui2/actions/save_to_disk.py +++ b/src/calibre/gui2/actions/save_to_disk.py @@ -50,7 +50,7 @@ class SaveToDiskAction(InterfaceAction): cm('single format', _('Save only %s format to disk')% prefs['output_format'].upper(), triggered=partial(self.save_single_format_to_disk, False)) - cm('fingle dir and format', + cm('single dir and format', _('Save only %s format to disk in a single directory')% prefs['output_format'].upper(), triggered=partial(self.save_single_fmt_to_single_dir, False)) @@ -115,10 +115,7 @@ class SaveToDiskAction(InterfaceAction): opts.save_cover = False opts.write_opf = False opts.template = opts.send_template - if single_dir: - opts.template = opts.template.split('/')[-1].strip() - if not opts.template: - opts.template = '{title} - {authors}' + opts.single_dir = single_dir self._saver = Saver(self.gui, self.gui.library_view.model().db, Dispatcher(self._books_saved), rows, path, opts, spare_server=self.gui.spare_server) diff --git a/src/calibre/gui2/ebook_download.py b/src/calibre/gui2/ebook_download.py index 2fea67b9f0..d39ea47e52 100644 --- a/src/calibre/gui2/ebook_download.py +++ b/src/calibre/gui2/ebook_download.py @@ -66,8 +66,8 @@ class EbookDownload(object): raise Exception(_('Not a support ebook format.')) from calibre.ebooks.metadata.meta import get_metadata - with open(filename) as f: - mi = get_metadata(f, ext) + with open(filename, 'rb') as f: + mi = get_metadata(f, ext, force_read_metadata=True) mi.tags.extend(tags) id = gui.library_view.model().db.create_book_entry(mi) diff --git a/src/calibre/gui2/store/stores/open_books_plugin.py b/src/calibre/gui2/store/stores/open_books_plugin.py index 2e6c438d9d..99b68656e9 100644 --- a/src/calibre/gui2/store/stores/open_books_plugin.py +++ b/src/calibre/gui2/store/stores/open_books_plugin.py @@ -28,7 +28,7 @@ class OpenBooksStore(BasicStoreConfig, StorePlugin): if external or self.config.get('open_external', False): open_url(QUrl(url_slash_cleaner(detail_item if detail_item else url))) else: - d = WebStoreDialog(self.gui, self.url, parent, detail_item) + d = WebStoreDialog(self.gui, url, parent, detail_item) d.setWindowTitle(self.name) d.set_tags(self.config.get('tags', '')) d.exec_() @@ -44,7 +44,7 @@ class OpenBooksStore(BasicStoreConfig, StorePlugin): for data in doc.xpath('//ul[@id="object_list"]//li'): if counter <= 0: break - + id = ''.join(data.xpath('.//div[@class="links"]/a[1]/@href')) id = id.strip() if not id: diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index fff2d2189c..3471d93332 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -3024,7 +3024,8 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns): format = os.path.splitext(path)[1][1:].lower() stream = path if hasattr(path, 'read') else lopen(path, 'rb') stream.seek(0) - mi = get_metadata(stream, format, use_libprs_metadata=False) + mi = get_metadata(stream, format, use_libprs_metadata=False, + force_read_metadata=True) stream.seek(0) if mi.series_index is None: mi.series_index = self.get_next_series_num_for(mi.series) diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py index 8fcdfc9855..2c723e0f7d 100644 --- a/src/calibre/library/save_to_disk.py +++ b/src/calibre/library/save_to_disk.py @@ -121,6 +121,9 @@ def config(defaults=None): help=_('Convert paths to lowercase.')) x('replace_whitespace', default=False, help=_('Replace whitespace with underscores.')) + x('single_dir', default=False, + help=_('Save into a single directory, ignoring the template' + ' directory structure')) return c def preprocess_template(template): @@ -165,7 +168,7 @@ class Formatter(TemplateFormatter): def get_components(template, mi, id, timefmt='%b %Y', length=250, sanitize_func=ascii_filename, replace_whitespace=False, - to_lowercase=False): + to_lowercase=False, safe_format=True): tsorder = tweaks['save_template_title_series_sorting'] format_args = FORMAT_ARGS.copy() @@ -225,7 +228,11 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250, format_args[key] = unicode(format_args[key]) else: format_args[key] = '' - components = Formatter().unsafe_format(template, format_args, mi) + if safe_format: + components = Formatter().safe_format(template, format_args, + 'G_C-EXCEPTION!', mi) + else: + components = Formatter().unsafe_format(template, format_args, mi) components = [x.strip() for x in components.split('/')] components = [sanitize_func(x) for x in components if x] if not components: @@ -282,10 +289,20 @@ def do_save_book_to_disk(id_, mi, cover, plugboards, if not formats: return True, id_, mi.title - components = get_components(opts.template, mi, id_, opts.timefmt, length, + try: + components = get_components(opts.template, mi, id_, opts.timefmt, length, ascii_filename if opts.asciiize else sanitize_file_name_unicode, to_lowercase=opts.to_lowercase, - replace_whitespace=opts.replace_whitespace) + replace_whitespace=opts.replace_whitespace, safe_format=False) + except Exception, e: + raise ValueError(_('Failed to calculate path for ' + 'save to disk. Template: %s\n' + 'Error: %s'%(opts.template, e))) + if opts.single_dir: + components = components[-1:] + if not components: + raise ValueError(_('Template evaluation resulted in no' + ' path components. Template: %s')%opts.template) base_path = os.path.join(root, *components) base_name = os.path.basename(base_path) dirpath = os.path.dirname(base_path)