def create_book(mi, path, fmt='epub', opf_name='metadata.opf', html_name='start.xhtml', toc_name='toc.ncx'): ''' Create an empty book in the specified format at the specified location. ''' path = os.path.abspath(path) lang = 'und' opf = metadata_to_opf(mi, as_string=False) for l in opf.xpath('//*[local-name()="language"]'): if l.text: lang = l.text break lang = lang_as_iso639_1(lang) or lang opfns = OPF_NAMESPACES['opf'] m = opf.makeelement('{%s}manifest' % opfns) opf.insert(1, m) i = m.makeelement('{%s}item' % opfns, href=html_name, id='start') i.set('media-type', guess_type('a.xhtml')) m.append(i) i = m.makeelement('{%s}item' % opfns, href=toc_name, id='ncx') i.set('media-type', guess_type(toc_name)) m.append(i) s = opf.makeelement('{%s}spine' % opfns, toc="ncx") opf.insert(2, s) i = s.makeelement('{%s}itemref' % opfns, idref='start') s.append(i) CONTAINER = '''\ <?xml version="1.0"?> <container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"> <rootfiles> <rootfile full-path="{0}" media-type="application/oebps-package+xml"/> </rootfiles> </container> '''.format(prepare_string_for_xml(opf_name, True)).encode('utf-8') HTML = P('templates/new_book.html', data=True).decode('utf-8').replace( '_LANGUAGE_', prepare_string_for_xml(lang, True) ).replace( '_TITLE_', prepare_string_for_xml(mi.title) ).replace( '_AUTHORS_', prepare_string_for_xml(authors_to_string(mi.authors)) ).encode('utf-8') h = parse(HTML) pretty_html_tree(None, h) HTML = serialize(h, 'text/html') ncx = etree.tostring(create_toc(mi, opf, html_name, lang), encoding='utf-8', xml_declaration=True, pretty_print=True) pretty_xml_tree(opf) opf = etree.tostring(opf, encoding='utf-8', xml_declaration=True, pretty_print=True) if fmt == 'azw3': with TemporaryDirectory('create-azw3') as tdir, CurrentDir(tdir): for name, data in ((opf_name, opf), (html_name, HTML), (toc_name, ncx)): with open(name, 'wb') as f: f.write(data) c = Container(os.path.dirname(os.path.abspath(opf_name)), opf_name, DevNull()) opf_to_azw3(opf_name, path, c) else: with ZipFile(path, 'w', compression=ZIP_STORED) as zf: zf.writestr('mimetype', b'application/epub+zip', compression=ZIP_STORED) zf.writestr('META-INF/', b'', 0755) zf.writestr('META-INF/container.xml', CONTAINER) zf.writestr(opf_name, opf) zf.writestr(html_name, HTML) zf.writestr(toc_name, ncx)
def get_preprocess_html(path_to_ebook, output=None): from calibre.ebooks.conversion.plumber import set_regex_wizard_callback, Plumber from calibre.utils.logging import DevNull from calibre.ptempfile import TemporaryDirectory raw = {} set_regex_wizard_callback(raw.__setitem__) with TemporaryDirectory('_regex_wiz') as tdir: pl = Plumber(path_to_ebook, os.path.join(tdir, 'a.epub'), DevNull(), for_regex_wizard=True) pl.run() items = [raw[item.href] for item in pl.oeb.spine if item.href in raw] with (sys.stdout if output is None else open(output, 'wb')) as out: for html in items: out.write(html.encode('utf-8')) out.write(b'\n\n' + b'-' * 80 + b'\n\n')
def create_book(mi, path, fmt='epub', opf_name='metadata.opf', html_name='start.xhtml', toc_name='toc.ncx'): ''' Create an empty book in the specified format at the specified location. ''' if fmt not in valid_empty_formats: raise ValueError('Cannot create empty book in the %s format' % fmt) if fmt == 'txt': with open(path, 'wb') as f: if not mi.is_null('title'): f.write(as_bytes(mi.title)) return if fmt == 'docx': from calibre.ebooks.conversion.plumber import Plumber from calibre.ebooks.docx.writer.container import DOCX from calibre.utils.logging import default_log p = Plumber('a.docx', 'b.docx', default_log) p.setup_options() # Use the word default of one inch page margins for x in 'left right top bottom'.split(): setattr(p.opts, 'margin_' + x, 72) DOCX(p.opts, default_log).write(path, mi, create_empty_document=True) return path = os.path.abspath(path) lang = 'und' opf = metadata_to_opf(mi, as_string=False) for l in opf.xpath('//*[local-name()="language"]'): if l.text: lang = l.text break lang = lang_as_iso639_1(lang) or lang opfns = OPF_NAMESPACES['opf'] m = opf.makeelement('{%s}manifest' % opfns) opf.insert(1, m) i = m.makeelement('{%s}item' % opfns, href=html_name, id='start') i.set('media-type', guess_type('a.xhtml')) m.append(i) i = m.makeelement('{%s}item' % opfns, href=toc_name, id='ncx') i.set('media-type', guess_type(toc_name)) m.append(i) s = opf.makeelement('{%s}spine' % opfns, toc="ncx") opf.insert(2, s) i = s.makeelement('{%s}itemref' % opfns, idref='start') s.append(i) CONTAINER = '''\ <?xml version="1.0"?> <container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"> <rootfiles> <rootfile full-path="{0}" media-type="application/oebps-package+xml"/> </rootfiles> </container> '''.format(prepare_string_for_xml(opf_name, True)).encode('utf-8') HTML = P('templates/new_book.html', data=True).decode('utf-8').replace( '_LANGUAGE_', prepare_string_for_xml(lang, True)).replace( '_TITLE_', prepare_string_for_xml(mi.title)).replace( '_AUTHORS_', prepare_string_for_xml(authors_to_string( mi.authors))).encode('utf-8') h = parse(HTML) pretty_html_tree(None, h) HTML = serialize(h, 'text/html') ncx = etree.tostring(create_toc(mi, opf, html_name, lang), encoding='utf-8', xml_declaration=True, pretty_print=True) pretty_xml_tree(opf) opf = etree.tostring(opf, encoding='utf-8', xml_declaration=True, pretty_print=True) if fmt == 'azw3': with TemporaryDirectory('create-azw3') as tdir, CurrentDir(tdir): for name, data in ((opf_name, opf), (html_name, HTML), (toc_name, ncx)): with open(name, 'wb') as f: f.write(data) c = Container(os.path.dirname(os.path.abspath(opf_name)), opf_name, DevNull()) opf_to_azw3(opf_name, path, c) else: with ZipFile(path, 'w', compression=ZIP_STORED) as zf: zf.writestr('mimetype', b'application/epub+zip', compression=ZIP_STORED) zf.writestr('META-INF/', b'', 0o755) zf.writestr('META-INF/container.xml', CONTAINER) zf.writestr(opf_name, opf) zf.writestr(html_name, HTML) zf.writestr(toc_name, ncx)
def do_ebook_convert(self, f): from calibre.ebooks.conversion.plumber import supported_input_formats from calibre.web.feeds.recipes.collection import get_builtin_recipe_titles from calibre.customize.ui import available_output_formats from calibre.ebooks.conversion.cli import create_option_parser, group_titles from calibre.utils.logging import DevNull input_fmts = set(supported_input_formats()) output_fmts = set(available_output_formats()) iexts = {x.upper() for x in input_fmts}.union(input_fmts) oexts = {x.upper() for x in output_fmts}.union(output_fmts) w = polyglot_write(f) # Arg 1 w('\n_ebc_input_args() {') w('\n local extras; extras=(') w('\n {-h,--help}":Show Help"') w('\n "--version:Show program version"') w('\n "--list-recipes:List builtin recipe names"') for recipe in sorted(set(get_builtin_recipe_titles())): recipe = recipe.replace(':', '\\:').replace('"', '\\"') w(u'\n "%s.recipe"' % (recipe)) w('\n ); _describe -t recipes "ebook-convert builtin recipes" extras') w('\n _files -g "%s"' % ' '.join(('*.%s' % x for x in iexts))) w('\n}\n') # Arg 2 w('\n_ebc_output_args() {') w('\n local extras; extras=(') for x in output_fmts: w('\n ".{0}:Convert to a .{0} file with the same name as the input file"' .format(x)) w('\n ); _describe -t output "ebook-convert output" extras') w('\n _files -g "%s"' % ' '.join(('*.%s' % x for x in oexts))) w('\n _path_files -/') w('\n}\n') log = DevNull() def get_parser(input_fmt='epub', output_fmt=None): of = ('dummy2.' + output_fmt) if output_fmt else 'dummy' return create_option_parser( ('ec', 'dummy1.' + input_fmt, of, '-h'), log)[0] # Common options input_group, output_group = group_titles() p = get_parser() opts = p.option_list for group in p.option_groups: if group.title not in {input_group, output_group}: opts += group.option_list opts.append(p.get_option('--pretty-print')) opts.append(p.get_option('--input-encoding')) opts = '\\\n '.join( tuple(self.get_options(opts, file_map={'--search-replace': ()}))) w('\n_ebc_common_opts() {') w('\n _arguments -s \\\n ' + opts) w('\n}\n') # Input/Output format options for fmts, group_title, func in ( (input_fmts, input_group, '_ebc_input_opts_%s'), (output_fmts, output_group, '_ebc_output_opts_%s'), ): for fmt in fmts: is_input = group_title == input_group if is_input and fmt in {'rar', 'zip', 'oebzip'}: continue p = (get_parser(input_fmt=fmt) if is_input else get_parser( output_fmt=fmt)) opts = None for group in p.option_groups: if group.title == group_title: opts = [ o for o in group.option_list if '--pretty-print' not in o._long_opts and '--input-encoding' not in o._long_opts ] if not opts: continue opts = '\\\n '.join(tuple(sorted(self.get_options(opts)))) w('\n%s() {' % (func % fmt)) w('\n _arguments -s \\\n ' + opts) w('\n}\n') w('\n_ebook_convert() {') w('\n local iarg oarg context state_descr state line\n typeset -A opt_args\n local ret=1' ) w("\n _arguments '1: :_ebc_input_args' '*::ebook-convert output:->args' && ret=0" ) w("\n case $state in \n (args)") w('\n iarg=${line[1]##*.}; ') w("\n _arguments '1: :_ebc_output_args' '*::ebook-convert options:->args' && ret=0" ) w("\n case $state in \n (args)") w('\n oarg=${line[1]##*.}') w('\n iarg="_ebc_input_opts_${(L)iarg}"; oarg="_ebc_output_opts_${(L)oarg}"' ) w('\n _call_function - $iarg; _call_function - $oarg; _ebc_common_opts; ret=0' ) w('\n ;;\n esac') w("\n ;;\n esac\n return ret") w('\n}\n')
raw = lopen(src, 'rb').read().decode('utf-8') try: with lopen(x, 'wb') as f: f.write(raw.encode('utf-8')) build_book(x, ans, args=[ '--level1-toc=//h:h2', '--language=en', '--authors=Kovid Goyal', '--cover=' + I('lt.png') ]) finally: os.remove(x) return ans devnull = DevNull() class BaseTest(unittest.TestCase): longMessage = True maxDiff = None def setUp(self): pc.default_log = devnull self.tdir = PersistentTemporaryDirectory(suffix='-polish-test') def tearDown(self): shutil.rmtree(self.tdir, ignore_errors=True) del self.tdir