diff --git a/installer/linux/freeze.py b/installer/linux/freeze.py index 32581abee2..c381041675 100644 --- a/installer/linux/freeze.py +++ b/installer/linux/freeze.py @@ -16,6 +16,7 @@ def freeze(): from calibre.linux import entry_points from calibre import walk from calibre.web.feeds.recipes import recipe_modules + from calibre.ebooks.lrf.fonts import FONT_MAP import calibre @@ -37,6 +38,7 @@ def freeze(): '/usr/lib/libxml2.so.2', '/usr/lib/libxslt.so.1', '/usr/lib/libxslt.so.1', + '/usr/lib/libexslt.so.0', '/usr/lib/libMagickWand.so', '/usr/lib/libMagickCore.so', ] @@ -72,6 +74,7 @@ def freeze(): os.makedirs(DIST_DIR) includes = [x[0] for x in executables.values()] + includes += ['calibre.ebooks.lrf.fonts.prs500.'+x for x in FONT_MAP.values()] excludes = ['matplotlib', "Tkconstants", "Tkinter", "tcl", "_imagingtk", "ImageTk", "FixTk", 'wx', 'PyQt4.QtAssistant', 'PyQt4.QtOpenGL.so', diff --git a/installer/osx/freeze.py b/installer/osx/freeze.py index 2a74d15802..de93a344c2 100644 --- a/installer/osx/freeze.py +++ b/installer/osx/freeze.py @@ -326,7 +326,7 @@ def main(): 'genshi', 'calibre.web.feeds.recipes.*', 'calibre.ebooks.lrf.any.*', 'calibre.ebooks.lrf.feeds.*', 'keyword', 'codeop', 'pydoc', 'readline', - 'BeautifulSoup' + 'BeautifulSoup', 'calibre.ebooks.lrf.fonts.prs500.*', ], 'packages' : ['PIL', 'Authorization', 'lxml'], 'excludes' : ['IPython'], diff --git a/installer/windows/freeze.py b/installer/windows/freeze.py index 73bb9cae56..064615f422 100644 --- a/installer/windows/freeze.py +++ b/installer/windows/freeze.py @@ -176,6 +176,7 @@ def main(args=sys.argv): 'BeautifulSoup', 'pyreadline', 'pydoc', 'IPython.Extensions.*', 'calibre.web.feeds.recipes.*', + 'calibre.ebooks.lrf.fonts.prs500.*', 'PyQt4.QtWebKit', 'PyQt4.QtNetwork', ], 'packages' : ['PIL', 'lxml', 'cherrypy'], diff --git a/src/calibre/constants.py b/src/calibre/constants.py index 41d89d3e85..2209f482f5 100644 --- a/src/calibre/constants.py +++ b/src/calibre/constants.py @@ -2,7 +2,7 @@ __license__ = 'GPL v3' __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' __docformat__ = 'restructuredtext en' __appname__ = 'calibre' -__version__ = '0.4.125' +__version__ = '0.4.126' __author__ = "Kovid Goyal " ''' Various run time constants. diff --git a/src/calibre/customize/ui.py b/src/calibre/customize/ui.py index 240621c51e..067185b0c3 100644 --- a/src/calibre/customize/ui.py +++ b/src/calibre/customize/ui.py @@ -105,30 +105,43 @@ def reread_metadata_plugins(): for plugin in _initialized_plugins: if isinstance(plugin, MetadataReaderPlugin): for ft in plugin.file_types: - _metadata_readers[ft] = plugin + if not _metadata_readers.has_key(ft): + _metadata_readers[ft] = [] + _metadata_readers[ft].append(plugin) elif isinstance(plugin, MetadataWriterPlugin): for ft in plugin.file_types: - _metadata_writers[ft] = plugin + if not _metadata_writers.has_key(ft): + _metadata_writers[ft] = [] + _metadata_writers[ft].append(plugin) + + def get_file_type_metadata(stream, ftype): mi = MetaInformation(None, None) - try: - plugin = _metadata_readers[ftype.lower().strip()] - if not is_disabled(plugin): - with plugin: - mi = plugin.get_metadata(stream, ftype.lower().strip()) - except: - pass + ftype = ftype.lower().strip() + if _metadata_readers.has_key(ftype): + for plugin in _metadata_readers[ftype]: + if not is_disabled(plugin): + with plugin: + try: + mi = plugin.get_metadata(stream, ftype.lower().strip()) + break + except: + continue return mi def set_file_type_metadata(stream, mi, ftype): - try: - plugin = _metadata_writers[ftype.lower().strip()] - if not is_disabled(plugin): - with plugin: - plugin.set_metadata(stream, mi, ftype.lower().strip()) - except: - traceback.print_exc() + ftype = ftype.lower().strip() + if _metadata_writers.has_key(ftype): + for plugin in _metadata_writers[ftype]: + if not is_disabled(plugin): + with plugin: + try: + plugin.set_metadata(stream, mi, ftype.lower().strip()) + break + except: + traceback.print_exc() + def _run_filetype_plugins(path_to_file, ft=None, occasion='preprocess'): occasion = {'import':_on_import, 'preprocess':_on_preprocess, diff --git a/src/calibre/devices/cybookg3/driver.py b/src/calibre/devices/cybookg3/driver.py index 83be95abe7..c689767457 100644 --- a/src/calibre/devices/cybookg3/driver.py +++ b/src/calibre/devices/cybookg3/driver.py @@ -222,11 +222,11 @@ class CYBOOKG3(Device): path = path.replace('card:', self._card_prefix[:-1]) return path - - def _windows_match_device(self, device_id): + @classmethod + def windows_match_device(cls, device_id): device_id = device_id.upper() - if 'VEN_'+self.VENDOR_NAME in device_id and \ - 'PROD_'+self.PRODUCT_NAME in device_id: + if 'VEN_'+cls.VENDOR_NAME in device_id and \ + 'PROD_'+cls.PRODUCT_NAME in device_id: return True vid, pid = hex(cls.VENDOR_ID)[2:], hex(cls.PRODUCT_ID)[2:] @@ -243,7 +243,7 @@ class CYBOOKG3(Device): wmi = __import__('wmi', globals(), locals(), [], -1) c = wmi.WMI() for drive in c.Win32_DiskDrive(): - if self._windows_match_device(str(drive.PNPDeviceID)): + if self.__class__.windows_match_device(str(drive.PNPDeviceID)): if drive.Partitions == 0: continue try: diff --git a/src/calibre/ebooks/lrf/fonts/__init__.py b/src/calibre/ebooks/lrf/fonts/__init__.py index 25ef8433b5..1f67a50f25 100644 --- a/src/calibre/ebooks/lrf/fonts/__init__.py +++ b/src/calibre/ebooks/lrf/fonts/__init__.py @@ -50,7 +50,8 @@ def get_font_path(name): try: font_mod = __import__('calibre.ebooks.lrf.fonts.prs500', {}, {}, [fname], -1) - except ImportError: + getattr(font_mod, fname) + except (ImportError, AttributeError): font_mod = __import__('calibre.ebooks.lrf.fonts.liberation', {}, {}, [LIBERATION_FONT_MAP[name]], -1) p = PersistentTemporaryFile('.ttf', 'font_') @@ -80,4 +81,4 @@ def get_font(name, size, encoding='unic'): path = get_font_path(name) return ImageFont.truetype(path, size, encoding=encoding) elif name in FONT_FILE_MAP.keys(): - return ImageFont.truetype(FONT_FILE_MAP[name], size, encoding=encoding) \ No newline at end of file + return ImageFont.truetype(FONT_FILE_MAP[name], size, encoding=encoding) diff --git a/src/calibre/ebooks/lrf/html/convert_from.py b/src/calibre/ebooks/lrf/html/convert_from.py index b3f394aac8..292ae0b50b 100644 --- a/src/calibre/ebooks/lrf/html/convert_from.py +++ b/src/calibre/ebooks/lrf/html/convert_from.py @@ -245,7 +245,6 @@ class HTMLConverter(object, LoggingInterface): self.override_css = {} self.override_pcss = {} - self.table_render_job_server = None if self._override_css is not None: if os.access(self._override_css, os.R_OK): @@ -266,41 +265,37 @@ class HTMLConverter(object, LoggingInterface): paths = [os.path.abspath(path) for path in paths] paths = [path.decode(sys.getfilesystemencoding()) if not isinstance(path, unicode) else path for path in paths] - try: - while len(paths) > 0 and self.link_level <= self.link_levels: - for path in paths: - if path in self.processed_files: - continue - try: - self.add_file(path) - except KeyboardInterrupt: + while len(paths) > 0 and self.link_level <= self.link_levels: + for path in paths: + if path in self.processed_files: + continue + try: + self.add_file(path) + except KeyboardInterrupt: + raise + except: + if self.link_level == 0: # Die on errors in the first level raise - except: - if self.link_level == 0: # Die on errors in the first level - raise - for link in self.links: - if link['path'] == path: - self.links.remove(link) - break - self.log_warn('Could not process '+path) - if self.verbose: - self.log_exception(' ') - self.links = self.process_links() - self.link_level += 1 - paths = [link['path'] for link in self.links] - - if self.current_page is not None and self.current_page.has_text(): - self.book.append(self.current_page) - - for text, tb in self.extra_toc_entries: - self.book.addTocEntry(text, tb) - - if self.base_font_size > 0: - self.log_info('\tRationalizing font sizes...') - self.book.rationalize_font_sizes(self.base_font_size) - finally: - if self.table_render_job_server is not None: - self.table_render_job_server.killall() + for link in self.links: + if link['path'] == path: + self.links.remove(link) + break + self.log_warn('Could not process '+path) + if self.verbose: + self.log_exception(' ') + self.links = self.process_links() + self.link_level += 1 + paths = [link['path'] for link in self.links] + + if self.current_page is not None and self.current_page.has_text(): + self.book.append(self.current_page) + + for text, tb in self.extra_toc_entries: + self.book.addTocEntry(text, tb) + + if self.base_font_size > 0: + self.log_info('\tRationalizing font sizes...') + self.book.rationalize_font_sizes(self.base_font_size) def is_baen(self, soup): return bool(soup.find('meta', attrs={'name':'Publisher', @@ -1732,15 +1727,11 @@ class HTMLConverter(object, LoggingInterface): self.process_children(tag, tag_css, tag_pseudo_css) elif tagname == 'table' and not self.ignore_tables and not self.in_table: if self.render_tables_as_images: - if self.table_render_job_server is None: - from calibre.parallel import Server - self.table_render_job_server = Server(number_of_workers=1) print 'Rendering table...' from calibre.ebooks.lrf.html.table_as_image import render_table pheight = int(self.current_page.pageStyle.attrs['textheight']) pwidth = int(self.current_page.pageStyle.attrs['textwidth']) - images = render_table(self.table_render_job_server, - self.soup, tag, tag_css, + images = render_table(self.soup, tag, tag_css, os.path.dirname(self.target_prefix), pwidth, pheight, self.profile.dpi, self.text_size_multiplier_for_rendered_tables) diff --git a/src/calibre/ebooks/lrf/html/table_as_image.py b/src/calibre/ebooks/lrf/html/table_as_image.py index 7211dc858e..08eaec0436 100644 --- a/src/calibre/ebooks/lrf/html/table_as_image.py +++ b/src/calibre/ebooks/lrf/html/table_as_image.py @@ -6,14 +6,11 @@ __docformat__ = 'restructuredtext en' ''' Render HTML tables as images. ''' -import os, tempfile, atexit, shutil, time -from PyQt4.Qt import QUrl, QApplication, QSize, \ +import os, tempfile, atexit, shutil +from PyQt4.Qt import QUrl, QApplication, QSize, QEventLoop, \ SIGNAL, QPainter, QImage, QObject, Qt from PyQt4.QtWebKit import QWebPage -from calibre.parallel import ParallelJob - -__app = None class HTMLTableRenderer(QObject): @@ -27,13 +24,15 @@ class HTMLTableRenderer(QObject): self.app = None self.width, self.height, self.dpi = width, height, dpi self.base_dir = base_dir + self.images = [] + self.tdir = tempfile.mkdtemp(prefix='calibre_render_table') + self.loop = QEventLoop() self.page = QWebPage() self.connect(self.page, SIGNAL('loadFinished(bool)'), self.render_html) self.page.mainFrame().setTextSizeMultiplier(factor) self.page.mainFrame().setHtml(html, QUrl('file:'+os.path.abspath(self.base_dir))) - self.images = [] - self.tdir = tempfile.mkdtemp(prefix='calibre_render_table') + def render_html(self, ok): try: @@ -63,7 +62,7 @@ class HTMLTableRenderer(QObject): finally: QApplication.quit() -def render_table(server, soup, table, css, base_dir, width, height, dpi, factor=1.0): +def render_table(soup, table, css, base_dir, width, height, dpi, factor=1.0): head = '' for e in soup.findAll(['link', 'style']): head += unicode(e)+'\n\n' @@ -83,24 +82,13 @@ def render_table(server, soup, table, css, base_dir, width, height, dpi, factor= '''%(head, width-10, style, unicode(table)) - job = ParallelJob('render_table', lambda j : j, None, - args=[html, base_dir, width, height, dpi, factor]) - server.add_job(job) - while not job.has_run: - time.sleep(2) - - if job.exception is not None: - print 'Failed to render table' - print job.exception - print job.traceback - images, tdir = job.result + images, tdir = do_render(html, base_dir, width, height, dpi, factor) atexit.register(shutil.rmtree, tdir) return images def do_render(html, base_dir, width, height, dpi, factor): - app = QApplication.instance() - if app is None: - app = QApplication([]) + if QApplication.instance() is None: + QApplication([]) tr = HTMLTableRenderer(html, base_dir, width, height, dpi, factor) - app.exec_() + tr.loop.exec_() return tr.images, tr.tdir \ No newline at end of file diff --git a/src/calibre/gui2/dialogs/metadata_single.ui b/src/calibre/gui2/dialogs/metadata_single.ui index 00215180d6..b2e2108ec3 100644 --- a/src/calibre/gui2/dialogs/metadata_single.ui +++ b/src/calibre/gui2/dialogs/metadata_single.ui @@ -600,6 +600,33 @@
widgets.h
+ + title + swap_button + authors + author_sort + auto_author_sort + rating + publisher + tags + tag_editor_button + series + remove_series_button + series_index + isbn + comments + fetch_metadata_button + fetch_cover_button + password_button + cover_button + reset_cover + cover_path + add_format_button + button_set_cover + remove_format_button + formats + button_box + diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 279dab42aa..97ad934eeb 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -1424,9 +1424,14 @@ in which you want to store your books files. Any existing books will be automati self.memory_view.write_settings() def quit(self, checked, restart=False): - if self.shutdown(): - self.restart_after_quit = restart - QApplication.instance().quit() + if not self.confirm_quit(): + return + try: + self.shutdown() + except: + pass + self.restart_after_quit = restart + QApplication.instance().quit() def donate(self): BUTTON = ''' @@ -1457,22 +1462,26 @@ in which you want to store your books files. Any existing books will be automati QDesktopServices.openUrl(QUrl.fromLocalFile(pt.name)) - def shutdown(self): - msg = _('There are active jobs. Are you sure you want to quit?') - if self.job_manager.has_device_jobs(): - msg = '

'+__appname__ + _(''' is communicating with the device!
- 'Quitting may cause corruption on the device.
- 'Are you sure you want to quit?''')+'

' + def confirm_quit(self): if self.job_manager.has_jobs(): + msg = _('There are active jobs. Are you sure you want to quit?') + if self.job_manager.has_device_jobs(): + msg = '

'+__appname__ + _(''' is communicating with the device!
+ 'Quitting may cause corruption on the device.
+ 'Are you sure you want to quit?''')+'

' + d = QMessageBox(QMessageBox.Warning, _('WARNING: Active jobs'), msg, QMessageBox.Yes|QMessageBox.No, self) d.setIconPixmap(QPixmap(':/images/dialog_warning.svg')) d.setDefaultButton(QMessageBox.No) if d.exec_() != QMessageBox.Yes: return False + return True - self.job_manager.terminate_all_jobs() + + def shutdown(self): self.write_settings() + self.job_manager.terminate_all_jobs() self.device_manager.keep_going = False self.cover_cache.stop() self.hide() @@ -1498,7 +1507,11 @@ in which you want to store your books files. Any existing books will be automati self.hide() e.ignore() else: - if self.shutdown(): + if self.confirm_quit(): + try: + self.shutdown() + except: + pass e.accept() else: e.ignore() diff --git a/src/calibre/gui2/tools.py b/src/calibre/gui2/tools.py index 76eaf0fc4b..c00fbfe8e3 100644 --- a/src/calibre/gui2/tools.py +++ b/src/calibre/gui2/tools.py @@ -13,7 +13,7 @@ from calibre.utils.config import prefs from calibre.gui2.dialogs.lrf_single import LRFSingleDialog, LRFBulkDialog from calibre.gui2.dialogs.epub import Config as EPUBConvert import calibre.gui2.dialogs.comicconf as ComicConf -from calibre.gui2 import warning_dialog, dynamic +from calibre.gui2 import warning_dialog from calibre.ptempfile import PersistentTemporaryFile from calibre.ebooks.lrf import preferred_source_formats as LRF_PREFERRED_SOURCE_FORMATS from calibre.ebooks.metadata.opf import OPFCreator @@ -22,7 +22,9 @@ from calibre.ebooks.epub.from_any import SOURCE_FORMATS as EPUB_PREFERRED_SOURCE def convert_single_epub(parent, db, comics, others): changed = False jobs = [] - for row in others: + others_ids = [db.id(row) for row in others] + comics_ids = [db.id(row) for row in comics] + for row, row_id in zip(others, others_ids): temp_files = [] d = EPUBConvert(parent, db, row) if d.source_format is not None: @@ -44,10 +46,10 @@ def convert_single_epub(parent, db, comics, others): opts.cover = d.cover_file.name temp_files.extend([d.opf_file, pt, of]) jobs.append(('any2epub', args, _('Convert book: ')+d.mi.title, - 'EPUB', db.id(row), temp_files)) + 'EPUB', row_id, temp_files)) changed = True - for row in comics: + for row, row_id in zip(comics, comics_ids): mi = db.get_metadata(row) title = author = _('Unknown') if mi.title: @@ -76,7 +78,7 @@ def convert_single_epub(parent, db, comics, others): args = [pt.name, opts] changed = True jobs.append(('comic2epub', args, _('Convert comic: ')+opts.title, - 'EPUB', db.id(row), [pt, of])) + 'EPUB', row_id, [pt, of])) return jobs, changed @@ -85,7 +87,9 @@ def convert_single_epub(parent, db, comics, others): def convert_single_lrf(parent, db, comics, others): changed = False jobs = [] - for row in others: + others_ids = [db.id(row) for row in others] + comics_ids = [db.id(row) for row in comics] + for row, row_id in zip(others, others_ids): temp_files = [] d = LRFSingleDialog(parent, db, row) if d.selected_format: @@ -104,10 +108,10 @@ def convert_single_lrf(parent, db, comics, others): temp_files.append(d.cover_file) temp_files.extend([pt, of]) jobs.append(('any2lrf', [cmdline], _('Convert book: ')+d.title(), - 'LRF', db.id(row), temp_files)) + 'LRF', row_id, temp_files)) changed = True - for row in comics: + for row, row_id in zip(comics, comics_ids): mi = db.get_metadata(row) title = author = _('Unknown') if mi.title: @@ -138,7 +142,7 @@ def convert_single_lrf(parent, db, comics, others): args = [pt.name, opts] changed = True jobs.append(('comic2lrf', args, _('Convert comic: ')+opts.title, - 'LRF', db.id(row), [pt, of])) + 'LRF', row_id, [pt, of])) return jobs, changed @@ -162,6 +166,7 @@ def convert_bulk_epub(parent, db, comics, others): parent.status_bar.showMessage(_('Starting Bulk conversion of %d books')%total, 2000) for i, row in enumerate(others+comics): + row_id = db.id(row) if row in others: data = None for fmt in EPUB_PREFERRED_SOURCE_FORMATS: @@ -198,7 +203,7 @@ def convert_bulk_epub(parent, db, comics, others): desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title)) temp_files = [cf] if cf is not None else [] temp_files.extend([opf_file, pt, of]) - jobs.append(('any2epub', args, desc, 'EPUB', db.id(row), temp_files)) + jobs.append(('any2epub', args, desc, 'EPUB', row_id, temp_files)) else: options = comic_opts.copy() mi = db.get_metadata(row) @@ -224,7 +229,7 @@ def convert_bulk_epub(parent, db, comics, others): options.verbose = 1 args = [pt.name, options] desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title)) - jobs.append(('comic2epub', args, desc, 'EPUB', db.id(row), [pt, of])) + jobs.append(('comic2epub', args, desc, 'EPUB', row_id, [pt, of])) if bad_rows: res = [] @@ -255,6 +260,7 @@ def convert_bulk_lrf(parent, db, comics, others): parent.status_bar.showMessage(_('Starting Bulk conversion of %d books')%total, 2000) for i, row in enumerate(others+comics): + row_id = db.id(row) if row in others: cmdline = list(d.cmdline) mi = db.get_metadata(row) @@ -294,7 +300,7 @@ def convert_bulk_lrf(parent, db, comics, others): desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title)) temp_files = [cf] if cf is not None else [] temp_files.extend([pt, of]) - jobs.append(('any2lrf', [cmdline], desc, 'LRF', db.id(row), temp_files)) + jobs.append(('any2lrf', [cmdline], desc, 'LRF', row_id, temp_files)) else: options = comic_opts.copy() mi = db.get_metadata(row) @@ -320,7 +326,7 @@ def convert_bulk_lrf(parent, db, comics, others): options.verbose = 1 args = [pt.name, options] desc = _('Convert book %d of %d (%s)')%(i+1, total, repr(mi.title)) - jobs.append(('comic2lrf', args, desc, 'LRF', db.id(row), [pt, of])) + jobs.append(('comic2lrf', args, desc, 'LRF', row_id, [pt, of])) if bad_rows: res = [] diff --git a/src/calibre/library/cli.py b/src/calibre/library/cli.py index a3d81156dd..e170842293 100644 --- a/src/calibre/library/cli.py +++ b/src/calibre/library/cli.py @@ -83,9 +83,11 @@ STANZA_TEMPLATE='''\
- + - ${f.capitalize()}:${unicode(', '.join(record[f]) if f=='tags' else record[f])}
+ ${f.capitalize()}:${unicode(', '.join(record[f]) if f=='tags' else record[f])} + # ${str(record['series_index'])} +
@@ -231,7 +233,7 @@ NULL = DevNull() def do_add(db, paths, one_book_per_directory, recurse, add_duplicates): orig = sys.stdout - sys.stdout = NULL + #sys.stdout = NULL try: files, dirs = [], [] for path in paths: diff --git a/src/calibre/utils/config.py b/src/calibre/utils/config.py index 7f7e47b498..44dc5d0ecb 100644 --- a/src/calibre/utils/config.py +++ b/src/calibre/utils/config.py @@ -17,7 +17,9 @@ from calibre.constants import terminal_controller, iswindows, isosx, \ from calibre.utils.lock import LockError, ExclusiveFile from collections import defaultdict -if iswindows: +if os.environ.has_key('CALIBRE_CONFIG_DIRECTORY'): + config_dir = os.path.abspath(os.environ['CALIBRE_CONFIG_DIRECTORY']) +elif iswindows: config_dir = plugins['winutil'][0].special_folder_path(plugins['winutil'][0].CSIDL_APPDATA) if not os.access(config_dir, os.W_OK|os.X_OK): config_dir = os.path.expanduser('~') diff --git a/src/calibre/utils/fontconfig.py b/src/calibre/utils/fontconfig.py index 8633cb3473..2a5207c67c 100644 --- a/src/calibre/utils/fontconfig.py +++ b/src/calibre/utils/fontconfig.py @@ -22,7 +22,7 @@ match to a given font specification. The main functions in this module are: .. autofunction:: match ''' -import sys, os, locale, codecs +import sys, os, locale, codecs, subprocess, re from ctypes import cdll, c_void_p, Structure, c_int, POINTER, c_ubyte, c_char, util, \ pointer, byref, create_string_buffer, Union, c_char_p, c_double @@ -34,6 +34,7 @@ except: iswindows = 'win32' in sys.platform or 'win64' in sys.platform isosx = 'darwin' in sys.platform +isbsd = 'bsd' in sys.platform DISABLED = False #if isosx: # libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c')) @@ -57,6 +58,13 @@ def load_library(): return cdll.LoadLibrary(lib) elif iswindows: return cdll.LoadLibrary('libfontconfig-1') + elif isbsd: + raw = subprocess.Popen('pkg-config --libs-only-L fontconfig'.split(), + stdout=subprocess.PIPE).stdout.read().strip() + match = re.search(r'-L([^\s,]+)', raw) + if not match: + return cdll.LoadLibrary('libfontconfig.so') + return cdll.LoadLibrary(match.group(1)+'/libfontconfig.so') else: try: return cdll.LoadLibrary(util.find_library('fontconfig')) diff --git a/src/calibre/web/feeds/recipes/__init__.py b/src/calibre/web/feeds/recipes/__init__.py index 644e0d2bb1..4e45175832 100644 --- a/src/calibre/web/feeds/recipes/__init__.py +++ b/src/calibre/web/feeds/recipes/__init__.py @@ -20,7 +20,7 @@ recipe_modules = ['recipe_' + r for r in ( 'science_news', 'the_nation', 'lrb', 'harpers_full', 'liberation', 'linux_magazine', 'telegraph_uk', 'utne', 'sciencedaily', 'forbes', 'time_magazine', 'endgadget', 'fudzilla', 'nspm_int', 'nspm', 'pescanik', - 'spiegel_int', 'themarketticker', 'tomshardware', 'xkcd', + 'spiegel_int', 'themarketticker', 'tomshardware', 'xkcd', 'ftd', 'zdnet', )] import re, imp, inspect, time, os diff --git a/src/calibre/web/feeds/recipes/recipe_ftd.py b/src/calibre/web/feeds/recipes/recipe_ftd.py new file mode 100644 index 0000000000..b2c0a8ef50 --- /dev/null +++ b/src/calibre/web/feeds/recipes/recipe_ftd.py @@ -0,0 +1,49 @@ +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' + +''' +Fetch FTD. +''' + +from calibre.web.feeds.news import BasicNewsRecipe + + +class FTheiseDe(BasicNewsRecipe): + + title = 'FTD' + description = 'Financial Times Deutschland' + __author__ = 'Oliver Niesner' + use_embedded_content = False + timefmt = ' [%d %b %Y]' + max_articles_per_feed = 40 + no_stylesheets = True + + remove_tags = [dict(id='navi_top'), + dict(id='topbanner'), + dict(id='seitenkopf'), + dict(id='footer'), + dict(id='rating_open'), + dict(id='ADS_Top'), + dict(id='ADS_Middle1'), + #dict(id='IDMS_ajax_chart_price_information_table'), + dict(id='ivwimg'), + dict(name='span', attrs={'class':'rsaquo'}), + dict(name='p', attrs={'class':'zwischenhead'}), + dict(name='div', attrs={'class':'chartBox'}), + dict(name='span', attrs={'class':'vote_455857'}), + dict(name='div', attrs={'class':'relatedhalb'}), + dict(name='div', attrs={'class':'bpoll'}), + dict(name='div', attrs={'class':'pollokknopf'}), + dict(name='div', attrs={'class':'videohint'}), + dict(name='div', attrs={'class':'videoshadow'}), + dict(name='div', attrs={'class':'boxresp videorahmen'}), + dict(name='div', attrs={'class':'boxresp'}), + dict(name='div', attrs={'class':'abspielen'}), + dict(name='div', attrs={'class':'wertungoben'}), + dict(name='div', attrs={'class':'artikelfuss'}), + dict(name='div', attrs={'class':'artikelsplitfaq'})] + remove_tags_after = [dict(name='div', attrs={'class':'artikelfuss'})] + + feeds = [ ('FTD', 'http://www.ftd.de/static/ticker/ftd-topnews.rdf') ] + + diff --git a/src/calibre/web/feeds/recipes/recipe_zdnet.py b/src/calibre/web/feeds/recipes/recipe_zdnet.py new file mode 100644 index 0000000000..6378f55ad8 --- /dev/null +++ b/src/calibre/web/feeds/recipes/recipe_zdnet.py @@ -0,0 +1,46 @@ +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal ' + +''' +Fetch zdnet. +''' + +from calibre.web.feeds.news import BasicNewsRecipe +import re + + +class cdnet(BasicNewsRecipe): + + title = 'zdnet' + description = 'zdnet security' + __author__ = 'Oliver Niesner' + use_embedded_content = False + timefmt = ' [%d %b %Y]' + max_articles_per_feed = 40 + no_stylesheets = True + encoding = 'iso-8859-1' + + #preprocess_regexps = \ +# [(re.compile(i[0], re.IGNORECASE | re.DOTALL), i[1]) for i in +# [ +# (r'<84>', lambda match: ''), +# (r'<93>', lambda match: ''), +# ] +# ] + + remove_tags = [dict(id='eyebrows'), + dict(id='header'), + dict(id='search'), + dict(id='nav'), + dict(id=''), + dict(name='div', attrs={'class':'banner'}), + dict(name='p', attrs={'class':'tags'}), + dict(name='div', attrs={'class':'special1'})] + remove_tags_after = [dict(name='div', attrs={'class':'bloggerDesc clear'})] + + feeds = [ ('zdnet', 'http://feeds.feedburner.com/zdnet/security') ] + + + + +