diff --git a/src/calibre/ebooks/epub/__init__.py b/src/calibre/ebooks/epub/__init__.py index 7bd6eeab50..f1a60ab646 100644 --- a/src/calibre/ebooks/epub/__init__.py +++ b/src/calibre/ebooks/epub/__init__.py @@ -88,10 +88,10 @@ def initialize_container(path_to_container, opf_name='metadata.opf'): zf.writestr('META-INF/container.xml', CONTAINER) return zf -def config(defaults=None): +def config(defaults=None, name='epub'): desc = _('Options to control the conversion to EPUB') if defaults is None: - c = Config('epub', desc) + c = Config(name, desc) else: c = StringConfig(defaults, desc) diff --git a/src/calibre/ebooks/epub/from_any.py b/src/calibre/ebooks/epub/from_any.py index b5c1f48937..6340180562 100644 --- a/src/calibre/ebooks/epub/from_any.py +++ b/src/calibre/ebooks/epub/from_any.py @@ -148,14 +148,14 @@ def config(defaults=None): def formats(): return ['html', 'rar', 'zip', 'oebzip']+list(MAP.keys()) -def option_parser(): - - return config().option_parser(usage=_('''\ +USAGE = _('''\ %%prog [options] filename -Convert any of a large number of ebook formats to an epub file. Supported formats are: %s -''')%formats() -) +Convert any of a large number of ebook formats to a %s file. Supported formats are: %s +''') + +def option_parser(usage=USAGE): + return config().option_parser(usage=usage%('EPUB', formats())) def main(args=sys.argv): parser = option_parser() diff --git a/src/calibre/ebooks/epub/from_html.py b/src/calibre/ebooks/epub/from_html.py index 66a3cebbae..3552a1bf70 100644 --- a/src/calibre/ebooks/epub/from_html.py +++ b/src/calibre/ebooks/epub/from_html.py @@ -64,7 +64,8 @@ def check(opf_path, pretty_print): ''' Find a remove all invalid links in the HTML files ''' - print '\tChecking files for bad links...' + logger = logging.getLogger('html2epub') + logger.info('\tChecking files for bad links...') pathtoopf = os.path.abspath(opf_path) with CurrentDir(os.path.dirname(pathtoopf)): opf = OPF(open(pathtoopf, 'rb'), os.path.dirname(pathtoopf)) diff --git a/src/calibre/ebooks/lit/from_any.py b/src/calibre/ebooks/lit/from_any.py new file mode 100644 index 0000000000..75cfc01bc2 --- /dev/null +++ b/src/calibre/ebooks/lit/from_any.py @@ -0,0 +1,59 @@ +from __future__ import with_statement +__license__ = 'GPL v3' +__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net' +__docformat__ = 'restructuredtext en' + +''' +Convert any ebook format to LIT. +''' + +import sys, os, glob, logging + +from calibre.ebooks.epub.from_any import any2epub, formats, USAGE +from calibre.ebooks.epub import config as common_config +from calibre.ptempfile import TemporaryDirectory +from calibre.ebooks.lit.writer import oeb2lit + +def config(defaults=None): + c = common_config(defaults=defaults, name='lit') + return c + +def option_parser(usage=USAGE): + return config().option_parser(usage=usage%('LIT', formats())) + +def any2lit(opts, path): + ext = os.path.splitext(path)[1] + if not ext: + raise ValueError('Unknown file type: '+path) + ext = ext.lower()[1:] + + if opts.output is None: + opts.output = os.path.splitext(os.path.basename(path))[0]+'.lit' + + opts.output = os.path.abspath(opts.output) + orig_output = opts.output + + with TemporaryDirectory('_any2lit') as tdir: + oebdir = os.path.join(tdir, 'oeb') + os.mkdir(oebdir) + opts.output = os.path.join(tdir, 'dummy.epub') + opts.extract_to = oebdir + any2epub(opts, path) + opf = glob.glob(os.path.join(oebdir, '*.opf'))[0] + opts.output = orig_output + logging.getLogger('html2epub').info(_('Creating LIT file from EPUB...')) + oeb2lit(opts, opf) + + +def main(args=sys.argv): + parser = option_parser() + opts, args = parser.parse_args(args) + if len(args) < 2: + parser.print_help() + print 'No input file specified.' + return 1 + any2lit(opts, args[1]) + return 0 + +if __name__ == '__main__': + sys.exit(main()) \ No newline at end of file diff --git a/src/calibre/ebooks/lit/writer.py b/src/calibre/ebooks/lit/writer.py index 75e6c68adc..12e0d8b718 100644 --- a/src/calibre/ebooks/lit/writer.py +++ b/src/calibre/ebooks/lit/writer.py @@ -9,7 +9,7 @@ __copyright__ = '2008, Marshall T. Vandegrift ' import sys import os from cStringIO import StringIO -from struct import pack, unpack +from struct import pack from itertools import izip, count, chain import time import random @@ -17,14 +17,14 @@ import re import copy import uuid import functools +import logging from urlparse import urldefrag from urllib import unquote as urlunquote from lxml import etree -from calibre.ebooks.lit import LitError -from calibre.ebooks.lit.reader import msguid, DirectoryEntry +from calibre.ebooks.lit.reader import DirectoryEntry import calibre.ebooks.lit.maps as maps from calibre.ebooks.lit.oeb import OEB_DOCS, OEB_STYLES, OEB_CSS_MIME, \ - CSS_MIME, XHTML_MIME, OPF_MIME, XML_NS, XML + CSS_MIME, OPF_MIME, XML_NS, XML from calibre.ebooks.lit.oeb import namespace, barename, urlnormalize, xpath from calibre.ebooks.lit.oeb import OEBBook from calibre.ebooks.lit.stylizer import Stylizer @@ -135,11 +135,15 @@ def decint(value): def randbytes(n): return ''.join(chr(random.randint(0, 255)) for x in xrange(n)) +def warn(x): + print x + class ReBinary(object): NSRMAP = {'': None, XML_NS: 'xml'} - def __init__(self, root, path, oeb, map=HTML_MAP): + def __init__(self, root, path, oeb, map=HTML_MAP, warn=warn): self.path = path + self.log_warn = warn self.dir = os.path.dirname(path) self.manifest = oeb.manifest self.tags, self.tattrs = map @@ -268,8 +272,8 @@ class ReBinary(object): def build_ahc(self): if len(self.anchors) > 6: - print "calibre: warning: More than six anchors in file %r. " \ - "Some links may not work properly." % self.path + self.log_warn("More than six anchors in file %r. " \ + "Some links may not work properly." % self.path) data = StringIO() data.write(unichr(len(self.anchors)).encode('utf-8')) for anchor, offset in self.anchors: @@ -292,8 +296,10 @@ def preserve(function): functools.update_wrapper(wrapper, function) return wrapper -class LitWriter(object): - def __init__(self, oeb): +class LitWriter(object, calibre.LoggingInterface): + def __init__(self, oeb, verbose=0): + calibre.LoggingInterface.__init__(self, logging.getLogger('oeb2lit')) + self.setup_cli_handler(verbose) self._oeb = oeb self._litize_oeb() @@ -319,7 +325,7 @@ class LitWriter(object): if type not in oeb.guide: oeb.guide.add(type, title, cover.href) else: - print "calibre: warning: No suitable cover image found." + self.log_warn('No suitable cover image found.') def dump(self, stream): self._stream = stream @@ -461,15 +467,15 @@ class LitWriter(object): self._add_folder('/data') for item in self._oeb.manifest.values(): if item.media_type not in LIT_MIMES: - print "calibre: warning: File %r of unknown media-type %r " \ - "excluded from output." % (item.href, item.media_type) + self.log_warn("File %r of unknown media-type %r " \ + "excluded from output." % (item.href, item.media_type)) continue name = '/data/' + item.id data = item.data secnum = 0 if not isinstance(data, basestring): self._add_folder(name) - rebin = ReBinary(data, item.href, self._oeb) + rebin = ReBinary(data, item.href, self._oeb, warn=self.log_warn) self._add_file(name + '/ahc', rebin.ahc, 0) self._add_file(name + '/aht', rebin.aht, 0) item.page_breaks = rebin.page_breaks @@ -548,7 +554,7 @@ class LitWriter(object): meta.attrib['ms--minimum_level'] = '0' meta.attrib['ms--attr5'] = '1' meta.attrib['ms--guid'] = '{%s}' % str(uuid.uuid4()).upper() - rebin = ReBinary(meta, 'content.opf', self._oeb, OPF_MAP) + rebin = ReBinary(meta, 'content.opf', self._oeb, map=OPF_MAP, warn=self.log_warn) meta = rebin.content self._meta = meta self._add_file('/meta', meta) @@ -709,6 +715,19 @@ def option_parser(): help=_('Output file. Default is derived from input filename.')) return parser +def oeb2lit(opts, opfpath): + litpath = opts.output + if litpath is None: + litpath = os.path.basename(opfpath) + litpath = os.path.splitext(litpath)[0] + '.lit' + litpath = os.path.abspath(litpath) + lit = LitWriter(OEBBook(opfpath), opts.verbose) + with open(litpath, 'wb') as f: + lit.dump(f) + logger = logging.getLogger('oeb2lit') + logger.info(_('Output written to ')+litpath) + + def main(argv=sys.argv): parser = option_parser() opts, args = parser.parse_args(argv[1:]) @@ -716,14 +735,7 @@ def main(argv=sys.argv): parser.print_help() return 1 opfpath = args[0] - litpath = opts.output - if litpath is None: - litpath = os.path.basename(opfpath) - litpath = os.path.splitext(litpath)[0] + '.lit' - lit = LitWriter(OEBBook(opfpath)) - with open(litpath, 'wb') as f: - lit.dump(f) - print _('LIT ebook created at'), litpath + oeb2lit(opts, opfpath) return 0 if __name__ == '__main__': diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index b090b37882..e2ac7d2bd6 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -473,9 +473,12 @@ class EbookViewer(MainWindow, Ui_EbookViewer): return current_page def save_current_position(self): - pos = self.view.bookmark() - bookmark = '%d#%s'%(self.current_index, pos) - self.iterator.add_bookmark(('calibre_current_page_bookmark', bookmark)) + try: + pos = self.view.bookmark() + bookmark = '%d#%s'%(self.current_index, pos) + self.iterator.add_bookmark(('calibre_current_page_bookmark', bookmark)) + except: + traceback.print_exc() def load_ebook(self, pathtoebook): if self.iterator is not None: diff --git a/src/calibre/linux.py b/src/calibre/linux.py index 58a35909ab..9e8dea355c 100644 --- a/src/calibre/linux.py +++ b/src/calibre/linux.py @@ -47,6 +47,7 @@ entry_points = { 'fb2-meta = calibre.ebooks.metadata.fb2:main', 'any2lrf = calibre.ebooks.lrf.any.convert_from:main', 'any2epub = calibre.ebooks.epub.from_any:main', + 'any2lit = calibre.ebooks.lit.from_any:main', 'lrf2lrs = calibre.ebooks.lrf.lrfparser:main', 'lrs2lrf = calibre.ebooks.lrf.lrs.convert_from:main', 'pdfreflow = calibre.ebooks.lrf.pdf.reflow:main', @@ -184,6 +185,7 @@ def setup_completion(fatal_errors): from calibre.ebooks.odt.to_oeb import option_parser as odt2oeb from calibre.ebooks.epub.from_feeds import option_parser as feeds2epub from calibre.ebooks.epub.from_any import option_parser as any2epub + from calibre.ebooks.lit.from_any import option_parser as any2lit from calibre.ebooks.epub.from_comic import option_parser as comic2epub from calibre.gui2.main import option_parser as guiop any_formats = ['epub', 'htm', 'html', 'xhtml', 'xhtm', 'rar', 'zip', @@ -207,7 +209,8 @@ def setup_completion(fatal_errors): f.write(opts_and_exts('pdf2lrf', htmlop, ['pdf'])) f.write(opts_and_exts('any2lrf', htmlop, any_formats)) f.write(opts_and_exts('calibre', guiop, any_formats)) - f.write(opts_and_exts('any2lrf', any2epub, any_formats)) + f.write(opts_and_exts('any2epub', any2epub, any_formats)) + f.write(opts_and_exts('any2lit', any2lit, any_formats)) f.write(opts_and_exts('lrf2lrs', lrf2lrsop, ['lrf'])) f.write(opts_and_exts('lrf-meta', metaop, ['lrf'])) f.write(opts_and_exts('rtf-meta', metaop, ['rtf']))