From b1a02af907deb43a17b23854fb3ab8936229f5e5 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 21 Apr 2007 18:44:04 +0000 Subject: [PATCH] Added rar,zip support to html2lrf and squashed a few more html processing bugs. Version bump. --- Makefile | 14 -- installer.nsi | 4 +- setup.py | 58 +++----- src/libprs500/__init__.py | 16 ++- src/libprs500/libunrar.py | 16 ++- src/libprs500/libunzip.py | 52 +++++++ src/libprs500/lrf/__init__.py | 3 +- src/libprs500/lrf/html/convert_from.py | 190 +++++++++++++++++-------- src/libprs500/lrf/makelrf.py | 123 ---------------- upload | 21 +++ 10 files changed, 253 insertions(+), 244 deletions(-) delete mode 100644 Makefile create mode 100644 src/libprs500/libunzip.py delete mode 100755 src/libprs500/lrf/makelrf.py create mode 100644 upload diff --git a/Makefile b/Makefile deleted file mode 100644 index 85d2df0038..0000000000 --- a/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -APIDOCS=/var/www/libprs500.kovidgoyal.net/htdocs/apidocs -targets: - @echo Targets are: installer doc - -installer: - @scp dist/libprs500-*.exe castalia:/var/www/vhosts/kovidgoyal.net/subdomains/libprs500/httpdocs/downloads/ - @ssh castalia chmod a+r /var/www/vhosts/kovidgoyal.net/subdomains/libprs500/httpdocs/downloads/\* - @echo Update link on the libprs500 wiki - -doc: - epydoc --config epydoc.conf - cp -r docs/html ${APIDOCS}/ - epydoc -v --config epydoc-pdf.conf - cp docs/pdf/api.pdf ${APIDOCS}/ diff --git a/installer.nsi b/installer.nsi index 34d076f0dc..bf86931353 100644 --- a/installer.nsi +++ b/installer.nsi @@ -15,10 +15,11 @@ Var MUI_TEMP !define PRODUCT_NAME "libprs500" !define XPUI_BRANDINGTEXT "${PRODUCT_NAME} created by Kovid Goyal" -!define PRODUCT_VERSION "0.3.12" +!define PRODUCT_VERSION "0.3.13" !define WEBSITE "https://libprs500.kovidgoyal.net" !define PY2EXE_DIR "C:\libprs500" !define LIBUSB_DIR "C:\libusb-prs500" +!define LIBUNRAR_DIR "C:\Program Files\UnrarDLL" !define QT_DIR "C:\Qt\4.2.3\bin" ;------------------------------------------------------------------------------------------------------ @@ -98,6 +99,7 @@ Section "libprs500" Seclibprs500 SetOutPath "$SYSDIR" File "${LIBUSB_DIR}\libusb0.dll" + File "${LIBUNRAR_DIR}\unrar.dll" DetailPrint " " DetailPrint "Installing USB driver (this may take a few seconds) ..." diff --git a/setup.py b/setup.py index bb15d6ad30..d7b07c33a2 100644 --- a/setup.py +++ b/setup.py @@ -21,6 +21,8 @@ import ez_setup ez_setup.use_setuptools() from setuptools import setup, find_packages + +################################# py2exe ####################################### py2exe_options = {} if sys.argv[1] == 'py2exe': py2exe_dir = 'C:\libprs500' @@ -33,10 +35,13 @@ if sys.argv[1] == 'py2exe': f.close() try: import py2exe - console = [{ - 'script' : 'src/libprs500/cli/main.py', 'dest_base':'prs500', - 'script' : 'src/libprs500/lrf/html/convert_from.py', 'dest_base':'html2lrf' - }] + console = [ + {'script' : 'src/libprs500/cli/main.py', 'dest_base':'prs500'}, + {'script' : 'src/libprs500/lrf/html/convert_from.py', 'dest_base':'html2lrf'}, + {'script' : 'src/libprs500/lrf/txt/convert_from.py', 'dest_base':'txt2lrf'}, + {'script' : 'src/libprs500/lrf/meta.py', 'dest_base':'lrf-meta'}, + {'script' : 'src/libprs500/metadata/rtf.py', 'dest_base':'rtf-meta'}, + ] windows = [{'script' : 'src/libprs500/gui/main.py', 'dest_base':'prs500-gui', 'icon_resources':[(1,'icons/library.ico')]}] excludes = ["Tkconstants", "Tkinter", "tcl", "_imagingtk", @@ -50,29 +55,9 @@ if sys.argv[1] == 'py2exe': except ImportError: print >>sys.stderr, 'Must be in Windows to run py2exe' sys.exit(1) - +################################################################################ -# Try to install the Python imaging library as the package name (PIL) doesn't -# match the distribution file name, thus declaring itas a dependency is useless -from setuptools.command.easy_install import main as easy_install -try: - try: - import Image - except ImportError: - if sys.platform.lower()[:5] not in ['win32', 'darwin']: - print "Trying to install the Python Imaging Library" - easy_install(["-f", "http://www.pythonware.com/products/pil/", "Imaging"]) - else: - raise Exception('Please install the Python Imaging library manually from '\ - 'http://www.pythonware.com/products/pil/') -except Exception, e: - print >> sys.stderr, e - print >> sys.stderr, \ - "WARNING: Could not install the Python Imaging Library.", \ - "Some functionality will be unavailable" - - if sys.hexversion < 0x2050000: print >> sys.stderr, "You must use python >= 2.5 Try invoking this script as python2.5 setup.py." print >> sys.stderr, "If you are using easy_install, try easy_install-2.5" @@ -110,20 +95,17 @@ setup( """, long_description = """ - libprs500 is library to interface with the - `SONY Portable Reader`_ over USB_. - It provides methods to list the contents of the file system on the device, - as well as copy files from and to the device. - It also provides a command line and a graphical user interface via - the commands prs500 and - prs500-gui. The graphical user interface is designed to - manage an ebook library and allows for easy - syncing between the library and the ebook reader. - In addition libprs500 has a utility to read/write the metadata - from LRF files (unencrypted books in the SONY BBeB format). A command line - interface to this is provided via the command lrf-meta. + libprs500 is a ebook management application. It maintains an ebook library + and allows for easy transfer of books from the library to an ebook reader. + At the moment, it supports the `SONY Portable Reader`_. - A windows installer is available from https://libprs500.kovidgoyal.net + It can also convert various popular ebook formats into LRF, the native + ebook format of the SONY Reader. + + For screenshots: https://libprs500.kovidgoyal.net/wiki/Screenshots + + For installation/usage instructions please see + https://libprs500.kovidgoyal.net/wiki/WikiStart#Installation For SVN access: svn co https://svn.kovidgoyal.net/code/libprs500 diff --git a/src/libprs500/__init__.py b/src/libprs500/__init__.py index 47bdfc025c..f7e2463863 100644 --- a/src/libprs500/__init__.py +++ b/src/libprs500/__init__.py @@ -33,10 +33,24 @@ You may have to adjust the GROUP and the location of the rules file to suit your distribution. """ -__version__ = "0.3.12" +__version__ = "0.3.13" __docformat__ = "epytext" __author__ = "Kovid Goyal " import sys iswindows = 'win32' in sys.platform.lower() isosx = 'darwin' in sys.platform.lower() + +def extract(path, dir): + import os + ext = os.path.splitext(path)[1][1:].lower() + extractor = None + if ext == 'zip': + from libprs500.libunzip import extract + extractor = extract + elif ext == 'rar': + from libprs500.libunrar import extract + extractor = extract + if not extract: + raise Exception('Unknown archive type') + extractor(path, dir) diff --git a/src/libprs500/libunrar.py b/src/libprs500/libunrar.py index 26140d0d1e..6f16b0046d 100644 --- a/src/libprs500/libunrar.py +++ b/src/libprs500/libunrar.py @@ -17,6 +17,7 @@ This module provides a thin ctypes based wrapper around libunrar. See ftp://ftp.rarlabs.com/rar/unrarsrc-3.7.5.tar.gz """ +import os from ctypes import Structure, c_char_p, c_uint, c_void_p, POINTER, \ byref, c_wchar_p, CFUNCTYPE, c_int, c_long, c_char, c_wchar from StringIO import StringIO @@ -164,14 +165,21 @@ def get_archive_info(flags): print >>ios, 'First Volume:\t', 'yes' if (flags & 256) else 'no or older than 3.0' return ios.getvalue() -def extract(path): +def extract(path, dir): + """ + Extract archive C{filename} into directory C{dir} + """ open_archive_data = RAROpenArchiveDataEx(ArcName=path, OpenMode=RAR_OM_EXTRACT, CmtBuf=None) arc_data = _libunrar.RAROpenArchiveEx(byref(open_archive_data)) + cwd = os.getcwd() + if not os.path.isdir( dir ): + os.mkdir( dir ) + os.chdir( dir ) try: if open_archive_data.OpenResult != 0: raise UnRARException(_interpret_open_error(open_archive_data.OpenResult, path)) print 'Archive:', path - print get_archive_info(open_archive_data.Flags) + #print get_archive_info(open_archive_data.Flags) header_data = RARHeaderDataEx(CmtBuf=None) #_libunrar.RARSetCallback(arc_data, callback_func, mode) while True: @@ -184,7 +192,5 @@ def extract(path): if RHCode == ERAR_BAD_DATA: raise UnRARException('File header broken') finally: + os.chdir(cwd) _libunrar.RARCloseArchive(arc_data) - -extract(r'z:\home\test.rar') -#extract('/home/kovid/ero/Fansadox Collections/C21 Ponygirl Inferno.rar') \ No newline at end of file diff --git a/src/libprs500/libunzip.py b/src/libprs500/libunzip.py new file mode 100644 index 0000000000..e506204749 --- /dev/null +++ b/src/libprs500/libunzip.py @@ -0,0 +1,52 @@ +## Copyright (C) 2006 Kovid Goyal kovid@kovidgoyal.net +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License along +## with this program; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import os, zipfile +from cStringIO import StringIO + +def extract(filename, dir): + """ + Extract archive C{filename} into directory C{dir} + """ + zf = zipfile.ZipFile( filename ) + namelist = zf.namelist() + dirlist = filter( lambda x: x.endswith( '/' ), namelist ) + filelist = filter( lambda x: not x.endswith( '/' ), namelist ) + # make base + pushd = os.getcwd() + if not os.path.isdir( dir ): + os.mkdir( dir ) + os.chdir( dir ) + # create directory structure + dirlist.sort() + for dirs in dirlist: + dirs = dirs.split( '/' ) + prefix = '' + for dir in dirs: + dirname = os.path.join( prefix, dir ) + if dir and not os.path.isdir( dirname ): + os.mkdir( dirname ) + prefix = dirname + # extract files + for fn in filelist: + out = open( fn, 'wb' ) + buffer = StringIO( zf.read( fn )) + buflen = 2 ** 20 + datum = buffer.read( buflen ) + while datum: + out.write( datum ) + datum = buffer.read( buflen ) + out.close() + os.chdir( pushd ) \ No newline at end of file diff --git a/src/libprs500/lrf/__init__.py b/src/libprs500/lrf/__init__.py index 0ca506001d..a460e364cb 100644 --- a/src/libprs500/lrf/__init__.py +++ b/src/libprs500/lrf/__init__.py @@ -20,6 +20,7 @@ At the time fo writing, this package only supports reading and writing LRF meat from optparse import OptionParser from libprs500.lrf.pylrs.pylrs import Book as _Book +from libprs500 import __version__ as VERSION __docformat__ = "epytext" __author__ = "Kovid Goyal " @@ -28,7 +29,7 @@ class ConversionError(Exception): pass def option_parser(usage): - parser = OptionParser(usage=usage) + parser = OptionParser(usage=usage, version='libprs500 '+VERSION) parser.add_option("-t", "--title", action="store", type="string", \ dest="title", help="Set the title") parser.add_option("-a", "--author", action="store", type="string", \ diff --git a/src/libprs500/lrf/html/convert_from.py b/src/libprs500/lrf/html/convert_from.py index 9e2867bfe3..1a1e679732 100644 --- a/src/libprs500/lrf/html/convert_from.py +++ b/src/libprs500/lrf/html/convert_from.py @@ -21,16 +21,20 @@ Code to convert HTML ebooks into LRF ebooks. I am indebted to esperanc for the CSS->Xylog Style conversion routines and to Falstaff for pylrs. """ -import os, re, sys +import os, re, sys, shutil from htmlentitydefs import name2codepoint from urllib import urlopen from urlparse import urlparse +from tempfile import mkdtemp +from operator import itemgetter -from libprs500.lrf.html.BeautifulSoup import BeautifulSoup, Comment, Tag, NavigableString +from libprs500.lrf.html.BeautifulSoup import BeautifulSoup, Comment, Tag, \ + NavigableString, Declaration from libprs500.lrf.pylrs.pylrs import Paragraph, CR, Italic, ImageStream, TextBlock, \ ImageBlock, JumpButton, CharButton, Page from libprs500.lrf.pylrs.pylrs import Span as _Span from libprs500.lrf import ConversionError, option_parser, Book +from libprs500 import extract def ImagePage(): return Page(evensidemargin=0, oddsidemargin=0, topmargin=0, \ @@ -150,7 +154,7 @@ class Span(_Span): elif key == 'font-weight': ans = font_weight(val) if ans: - t['fontweight'] = val + t['fontweight'] = ans elif key.startswith("margin"): if key == "margin": u = [] @@ -186,8 +190,6 @@ class Span(_Span): t["align"] = "head" else: print >>sys.stderr, 'Unhandled/malformed CSS key:', key, d[key] - if 'small' in t.values(): - print d, 'font-size' in d.keys() return t def __init__(self, ns, css, font_delta=0): @@ -252,7 +254,7 @@ class HTMLConverter(object): self.current_page = None self.current_para = None self.current_style = {} - self.parse_file(self.soup.html) + self.parse_file() HTMLConverter.processed_files[path] = self print 'done' @@ -318,14 +320,15 @@ class HTMLConverter(object): prop.update(self.parse_style_properties(tag["style"])) return prop - def parse_file(self, html): + def parse_file(self): self.current_page = Page() self.current_block = TextBlock() self.current_para = Paragraph() if self.cover: self.add_image_block(self.cover) - self.top = self.current_block - self.parse_tag(html, {}) + self.top = self.current_block + + self.process_children(self.soup, {}) if self.current_para: self.current_block.append(self.current_para) if self.current_block: @@ -409,12 +412,12 @@ class HTMLConverter(object): """ if self.current_para.contents: self.current_block.append(self.current_para) + self.current_para = Paragraph() if self.current_block.contents: self.current_page.append(self.current_block) + self.current_block = TextBlock() if self.current_page.contents: self.book.append(self.current_page) - self.current_para = Paragraph() - self.current_block = TextBlock() self.current_page = Page() @@ -423,40 +426,42 @@ class HTMLConverter(object): self.end_page() page = ImagePage() if not self.images.has_key(path): - self.images[path] = ImageBlock(ImageStream(path)) - page.append(self.images[path]) + self.images[path] = ImageStream(path) + page.append(ImageBlock(self.images[path])) self.book.append(page) - def parse_tag(self, tag, parent_css): - def sanctify_css(css): - """ Make css safe for use in a SPAM Xylog tag """ - for key in css.keys(): - test = key.lower() - if test.startswith('margin') or 'indent' in test or \ - 'padding' in test or 'border' in test or 'page-break' in test \ - or test.startswith('mso') \ - or test in ['color', 'display', 'text-decoration', \ - 'letter-spacing', 'text-autospace', 'text-transform']: - css.pop(key) - return css + def process_children(self, ptag, pcss): + """ Process the children of ptag """ + for c in ptag.contents: + if isinstance(c, (Comment, Declaration)): + continue + elif isinstance(c, Tag): + self.parse_tag(c, pcss) + elif isinstance(c, NavigableString): + self.add_text(c, pcss) - def add_text(tag, css): - try: - self.current_para.append(Span(tag, sanctify_css(css), \ - font_delta=self.font_delta)) - except ConversionError, err: - if self.verbose: - print >>sys.stderr, err + def add_text(self, tag, css): + try: + self.current_para.append(Span(tag, self.sanctify_css(css), \ + font_delta=self.font_delta)) + except ConversionError, err: + if self.verbose: + print >>sys.stderr, err - def process_children(ptag, pcss): - """ Process the children of ptag """ - for c in ptag.contents: - if isinstance(c, Comment): - continue - elif isinstance(c, Tag): - self.parse_tag(c, pcss) - elif isinstance(c, NavigableString): - add_text(c, pcss) + def sanctify_css(self, css): + """ Make css safe for use in a SPAM Xylog tag """ + for key in css.keys(): + test = key.lower() + if test.startswith('margin') or 'indent' in test or \ + 'padding' in test or 'border' in test or 'page-break' in test \ + or test.startswith('mso') \ + or test in ['color', 'display', 'text-decoration', \ + 'letter-spacing', 'text-autospace', 'text-transform']: + css.pop(key) + return css + + + def parse_tag(self, tag, parent_css): def process_text_tag(tag, tag_css): if 'page-break-before' in tag_css.keys(): @@ -467,16 +472,14 @@ class HTMLConverter(object): if 'page-break-after' in tag_css.keys(): end_page = True tag_css.pop('page-break-after') - process_children(tag, tag_css) + self.process_children(tag, tag_css) if end_page: self.end_page() - - try: tagname = tag.name.lower() except AttributeError: - add_text(tag, parent_css) + self.add_text(tag, parent_css) return tag_css = self.tag_css(tag, parent_css=parent_css) try: # Skip element if its display attribute is set to none @@ -494,7 +497,7 @@ class HTMLConverter(object): self.current_block = tb self.current_para = Paragraph() self.targets[tag['name']] = tb - process_children(tag, tag_css) + self.process_children(tag, tag_css) elif tag.has_key('href'): purl = urlparse(tag['href']) path = purl[2] @@ -516,12 +519,15 @@ class HTMLConverter(object): elif tag.has_key('type') and tag['type'] == "text/css" \ and tag.has_key('href'): url = tag['href'] - if url.startswith('http://'): - f = urlopen(url) - else: - f = open(url) - self.parse_css(f.read()) - f.close() + try: + if url.startswith('http://'): + f = urlopen(url) + else: + f = open(url) + self.parse_css(f.read()) + f.close() + except IOError: + pass elif tagname in ['p', 'div', 'ul', 'ol', 'tr', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']: # TODO: Implement ol indent = tag_css.pop('text-indent', '') @@ -536,34 +542,33 @@ class HTMLConverter(object): elif tagname in ['b', 'strong', 'i', 'em', 'span']: process_text_tag(tag, tag_css) elif tagname == 'font': - pass - elif tagname == 'link': - pass - elif tagname == 'style': - pass + if tag.has_key('face'): + tag_css['font-family'] = tag['face'] + process_text_tag(tag, tag_css) elif tagname == 'br': self.current_para.append(CR()) elif tagname == 'hr': self.current_para.append(CR()) # TODO: Horizontal line? else: - process_children(tag, tag_css) + self.process_children(tag, tag_css) def writeto(self, path, lrs=False): self.book.renderLrs(path) if lrs else self.book.renderLrf(path) def process_file(path, options): - cwd = os.getcwd() + cwd = os.getcwd() + dirpath = None try: - path = os.path.abspath(path) + dirpath, path = get_path(path) cpath, tpath = options.cover, '' if options.cover and os.access(options.cover, os.R_OK): try: from PIL import Image from libprs500.prs500 import PRS500 from libprs500.ptempfile import PersistentTemporaryFile - im = Image.open(cpath) + im = Image.open(os.path.join(cwd, cpath)) cim = im.resize((600, 800), Image.BICUBIC) cf = PersistentTemporaryFile(prefix="html2lrf_", suffix=".jpg") cf.close() @@ -596,6 +601,8 @@ def process_file(path, options): print 'Output written to', oname finally: os.chdir(cwd) + if dirpath: + shutil.rmtree(dirpath, True) def main(): """ CLI for html -> lrf conversions """ @@ -618,6 +625,67 @@ def main(): options.title = os.path.splitext(os.path.basename(src))[0] process_file(src, options) +def console_query(dirpath, candidate, docs): + if len(docs) == 1: + return 0 + try: + import readline + except ImportError: + pass + i = 0 + for doc in docs: + prefix = '>' if i == candidate else '' + print prefix+str(i)+'.\t', doc[0] + i += 1 + print + while True: + try: + choice = raw_input('Choose file to convert (0-'+str(i-1) + \ + '). Current choice is ['+ str(candidate) + ']:') + if not choice: + return candidate + choice = int(choice) + if choice < 0 or choice >= i: + continue + candidate = choice + except EOFError, KeyboardInterrupt: + sys.exit() + except: + continue + break + return candidate + + +def get_path(path, query=console_query): + path = os.path.abspath(path) + ext = os.path.splitext(path)[1][1:].lower() + if ext in ['htm', 'html', 'xhtml']: + return None, path + dirpath = mkdtemp('','html2lrf') + extract(path, dirpath) + candidate, docs = None, [] + for root, dirs, files in os.walk(dirpath): + for name in files: + ext = os.path.splitext(name)[1][1:].lower() + if ext not in ['html', 'xhtml', 'htm', 'xhtm']: + continue + docs.append((name, root, os.stat(os.path.join(root, name)).st_size)) + if 'toc' in name.lower(): + candidate = name + docs.sort(key=itemgetter(2)) + if candidate: + for i in range(len(docs)): + if docs[i][0] == candidate: + candidate = i + break + else: + candidate = len(docs) - 1 + if len(docs) == 0: + raise ConversionError('No suitable files found in archive') + if len(docs) > 0: + candidate = query(dirpath, candidate, docs) + return dirpath, os.path.join(docs[candidate][1], docs[candidate][0]) + if __name__ == '__main__': main() \ No newline at end of file diff --git a/src/libprs500/lrf/makelrf.py b/src/libprs500/lrf/makelrf.py deleted file mode 100755 index 0b9db5544b..0000000000 --- a/src/libprs500/lrf/makelrf.py +++ /dev/null @@ -1,123 +0,0 @@ -## Copyright (C) 2006 Kovid Goyal kovid@kovidgoyal.net -## This program is free software; you can redistribute it and/or modify -## it under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 2 of the License, or -## (at your option) any later version. -## -## This program is distributed in the hope that it will be useful, -## but WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -## GNU General Public License for more details. -## -## You should have received a copy of the GNU General Public License along -## with this program; if not, write to the Free Software Foundation, Inc., -## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -import os -import shutil -import sys -import hashlib -import re -import pkg_resources -import subprocess -from tempfile import mkdtemp -from optparse import OptionParser -from libprs500.lrf import ConversionError -from libprs500.lrf.meta import LRFException, LRFMetaFile -from libprs500.ptempfile import PersistentTemporaryFile - -def generate_thumbnail(path): - """ Generate a JPEG thumbnail of size ~ 128x128 (aspect ratio preserved)""" - try: - from PIL import Image - except ImportError: - raise LRFException("Unable to initialize Python Imaging Library." \ - "Thumbnail generation is disabled") - im = Image.open(path) - im.thumbnail((128, 128), Image.ANTIALIAS) - thumb = PersistentTemporaryFile(prefix="makelrf_", suffix=".jpeg") - thumb.close() - im = im.convert() - im.save(thumb.name) - return thumb - - -def makelrf(author=None, title=None, \ - thumbnail=None, src=None, odir=".",\ - rasterize=True, cover=None): - src = os.path.normpath(os.path.abspath(src)) - bbebook = pkg_resources.resource_filename(__name__, _bbebook) - if not os.access(src, os.R_OK): - raise LRFException("Unable to read from file: " + src) - if thumbnail: - thumb = os.path.abspath(thumbnail) - if not os.access(thumb, os.R_OK): - raise LRFException("Unable to read from " + thumb) - else: - thumb = pkg_resources.resource_filename(__name__, 'cover.jpg') - - if not author: - author = "Unknown" - if not title: - title = os.path.basename(src) - label = os.path.basename(src) - id = 'FB' + hashlib.md5(os.path.basename(label)).hexdigest()[:14] - name, ext = os.path.splitext(label) - cwd = os.path.dirname(src) - dirpath = None - try: - if ext == ".rar": - dirpath = mkdtemp('','makelrf') - cwd = dirpath - cmd = " ".join(["unrar", "e", '"'+src+'"']) - proc = subprocess.Popen(cmd, cwd=cwd, shell=True, stderr=subprocess.PIPE) - if proc.wait(): - raise LRFException("unrar failed with error:\n\n" + \ - proc.stderr.read()) - path, msize = None, 0 - for root, dirs, files in os.walk(dirpath): - for name in files: - if os.path.splitext(name)[1] == ".html": - size = os.stat(os.path.join(root, name)).st_size - if size > msize: - msize, path = size, os.path.join(root, name) - if not path: - raise LRFException("Could not find .html file in rar archive") - src = path - - name = re.sub("\s", "_", name) - name = os.path.abspath(os.path.join(odir, name)) + ".lrf" - cfg = { 'File' : src, 'Output' : name, 'Label' : label, 'BookID' : id, \ - 'Author' : author, 'Title' : title, 'Publisher' : 'Unknown' \ - } - - - if cover: - cover = os.path.normpath(os.path.abspath(cover)) - try: - thumbf = generate_thumbnail(cover) - thumb = thumbf.name - except Exception, e: - print >> sys.stderr, "WARNING: Unable to generate thumbnail:\n", \ - str(e) - thumb = cover - cfg['Cover'] = cover - cfg['Icon'] = thumb - config = PersistentTemporaryFile(prefix='makelrf_', suffix='.xml') - config.write(create_xml(cfg)) - config.close() - jar = '-jar "' + bbebook + '"' - cmd = " ".join(["java", jar, "-r" if rasterize else "", '"'+config.name+'"']) - proc = subprocess.Popen(cmd, \ - cwd=cwd, shell=True, stderr=subprocess.PIPE) - if proc.wait(): - raise LRFException("BBeBook failed with error:\n\n" + \ - proc.stderr.read()) - # Needed as BBeBook-0.2 doesn't handle non GIF thumbnails correctly. - lrf = open(name, "r+b") - LRFMetaFile(lrf).fix_thumbnail_type() - lrf.close() - return name - finally: - if dirpath: - shutil.rmtree(dirpath, True) - diff --git a/upload b/upload new file mode 100644 index 0000000000..12a5ea1796 --- /dev/null +++ b/upload @@ -0,0 +1,21 @@ +#!/bin/bash + +# Script to upload libprs500 to pypi, the installer to libprs500.kovidgoyal.net and update the api documentation + +PREFIX=/var/www/vhosts/kovidgoyal.net/subdomains/libprs500 +DOWNLOADS=$PREFIX/httpdocs/downloads +DOCS=$PREFIX/httpdocs/apidocs +exe=`cd dist && ls -1 libprs500-*.exe | tail -n1 && cd ..` + +ssh castalia rm -f $DOWNLOADS/libprs500\*.exe +scp dist/$exe castalia:$DOWNLOADS/ +ssh castalia chmod a+r $DOWNLOADS/\* +ssh castalia /root/bin/update-installer-link $exe + +epydoc --config epydoc.conf +scp -r docs/html castalia:$DOCS/ +epydoc -v --config epydoc-pdf.conf +scp docs/pdf/api.pdf castalia:$DOCS/ + +python setup.py register sdist bdist_egg upload +rm -rf dist/* build/*