diff --git a/epydoc-pdf.conf b/epydoc-pdf.conf index 2285935ed0..f251c7b5cc 100644 --- a/epydoc-pdf.conf +++ b/epydoc-pdf.conf @@ -7,7 +7,7 @@ url: http://libprs500.kovidgoyal.net # The list of modules to document. Modules can be named using # dotted names, module filenames, or package directory names. # This option may be repeated. -modules: src/libprs500/*.py, libprs500.ebooks.lrf, struct +modules: src/libprs500/*.py, struct output: pdf target: docs/pdf diff --git a/epydoc.conf b/epydoc.conf index 546556b6d5..904004aff1 100644 --- a/epydoc.conf +++ b/epydoc.conf @@ -7,7 +7,7 @@ url: http://libprs500.kovidgoyal.net # The list of modules to document. Modules can be named using # dotted names, module filenames, or package directory names. # This option may be repeated. -modules: src/libprs500/*.py, libprs500.ebooks.lrf, struct +modules: src/libprs500/*.py, struct # Write html output to the directory "docs" output: html diff --git a/ez_setup.py b/ez_setup.py deleted file mode 100644 index 3031ad0d11..0000000000 --- a/ez_setup.py +++ /dev/null @@ -1,222 +0,0 @@ -#!python -"""Bootstrap setuptools installation - -If you want to use setuptools in your package's setup.py, just include this -file in the same directory with it, and add this to the top of your setup.py:: - - from ez_setup import use_setuptools - use_setuptools() - -If you want to require a specific version of setuptools, set a download -mirror, or use an alternate download directory, you can do so by supplying -the appropriate options to ``use_setuptools()``. - -This file can also be run as a script to install or upgrade setuptools. -""" -import sys -DEFAULT_VERSION = "0.6c3" -DEFAULT_URL = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3] - -md5_data = { - 'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca', - 'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb', - 'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b', - 'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a', - 'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618', - 'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac', - 'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5', - 'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4', - 'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c', - 'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b', - 'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27', - 'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277', - 'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa', - 'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e', - 'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e', -} - -import sys, os - -def _validate_md5(egg_name, data): - if egg_name in md5_data: - from md5 import md5 - digest = md5(data).hexdigest() - if digest != md5_data[egg_name]: - print >>sys.stderr, ( - "md5 validation of %s failed! (Possible download problem?)" - % egg_name - ) - sys.exit(2) - return data - - -def use_setuptools( - version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, - download_delay=15 -): - """Automatically find/download setuptools and make it available on sys.path - - `version` should be a valid setuptools version number that is available - as an egg for download under the `download_base` URL (which should end with - a '/'). `to_dir` is the directory where setuptools will be downloaded, if - it is not already available. If `download_delay` is specified, it should - be the number of seconds that will be paused before initiating a download, - should one be required. If an older version of setuptools is installed, - this routine will print a message to ``sys.stderr`` and raise SystemExit in - an attempt to abort the calling script. - """ - try: - import setuptools - if setuptools.__version__ == '0.0.1': - print >>sys.stderr, ( - "You have an obsolete version of setuptools installed. Please\n" - "remove it from your system entirely before rerunning this script." - ) - sys.exit(2) - except ImportError: - egg = download_setuptools(version, download_base, to_dir, download_delay) - sys.path.insert(0, egg) - import setuptools; setuptools.bootstrap_install_from = egg - - import pkg_resources - try: - pkg_resources.require("setuptools>="+version) - - except pkg_resources.VersionConflict, e: - # XXX could we install in a subprocess here? - print >>sys.stderr, ( - "The required version of setuptools (>=%s) is not available, and\n" - "can't be installed while this script is running. Please install\n" - " a more recent version first.\n\n(Currently using %r)" - ) % (version, e.args[0]) - sys.exit(2) - -def download_setuptools( - version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, - delay = 15 -): - """Download setuptools from a specified location and return its filename - - `version` should be a valid setuptools version number that is available - as an egg for download under the `download_base` URL (which should end - with a '/'). `to_dir` is the directory where the egg will be downloaded. - `delay` is the number of seconds to pause before an actual download attempt. - """ - import urllib2, shutil - egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3]) - url = download_base + egg_name - saveto = os.path.join(to_dir, egg_name) - src = dst = None - if not os.path.exists(saveto): # Avoid repeated downloads - try: - from distutils import log - if delay: - log.warn(""" ---------------------------------------------------------------------------- -This script requires setuptools version %s to run (even to display -help). I will attempt to download it for you (from -%s), but -you may need to enable firewall access for this script first. -I will start the download in %d seconds. - -(Note: if this machine does not have network access, please obtain the file - - %s - -and place it in this directory before rerunning this script.) ----------------------------------------------------------------------------""", - version, download_base, delay, url - ); from time import sleep; sleep(delay) - log.warn("Downloading %s", url) - src = urllib2.urlopen(url) - # Read/write all in one block, so we don't create a corrupt file - # if the download is interrupted. - data = _validate_md5(egg_name, src.read()) - dst = open(saveto,"wb"); dst.write(data) - finally: - if src: src.close() - if dst: dst.close() - return os.path.realpath(saveto) - -def main(argv, version=DEFAULT_VERSION): - """Install or upgrade setuptools and EasyInstall""" - - try: - import setuptools - except ImportError: - egg = None - try: - egg = download_setuptools(version, delay=0) - sys.path.insert(0,egg) - from setuptools.command.easy_install import main - return main(list(argv)+[egg]) # we're done here - finally: - if egg and os.path.exists(egg): - os.unlink(egg) - else: - if setuptools.__version__ == '0.0.1': - # tell the user to uninstall obsolete version - use_setuptools(version) - - req = "setuptools>="+version - import pkg_resources - try: - pkg_resources.require(req) - except pkg_resources.VersionConflict: - try: - from setuptools.command.easy_install import main - except ImportError: - from easy_install import main - main(list(argv)+[download_setuptools(delay=0)]) - sys.exit(0) # try to force an exit - else: - if argv: - from setuptools.command.easy_install import main - main(argv) - else: - print "Setuptools version",version,"or greater has been installed." - print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)' - - - -def update_md5(filenames): - """Update our built-in md5 registry""" - - import re - from md5 import md5 - - for name in filenames: - base = os.path.basename(name) - f = open(name,'rb') - md5_data[base] = md5(f.read()).hexdigest() - f.close() - - data = [" %r: %r,\n" % it for it in md5_data.items()] - data.sort() - repl = "".join(data) - - import inspect - srcfile = inspect.getsourcefile(sys.modules[__name__]) - f = open(srcfile, 'rb'); src = f.read(); f.close() - - match = re.search("\nmd5_data = {\n([^}]+)}", src) - if not match: - print >>sys.stderr, "Internal error!" - sys.exit(2) - - src = src[:match.start(1)] + repl + src[match.end(1):] - f = open(srcfile,'w') - f.write(src) - f.close() - - -if __name__=='__main__': - if len(sys.argv)>2 and sys.argv[1]=='--md5update': - update_md5(sys.argv[2:]) - else: - main(sys.argv[1:]) - - - - - diff --git a/icons/library.icns b/icons/library.icns new file mode 100644 index 0000000000..60ed1beda7 Binary files /dev/null and b/icons/library.icns differ diff --git a/osx_installer.py b/osx_installer.py new file mode 100644 index 0000000000..71e8289d01 --- /dev/null +++ b/osx_installer.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python +## 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. +''' Create an OSX installer ''' + +import sys, re, os, shutil, subprocess, stat +from setup import VERSION, APPNAME, scripts, main_modules, basenames, main_functions +from setuptools import setup +sys.argv[1:2] = ['py2app'] +from py2app.build_app import py2app +from modulegraph.find_modules import find_modules + +class BuildAPP(py2app): + QT_PREFIX = '/Users/kovid/qt' + LOADER_TEMPLATE = \ +r'''#!/usr/bin/env python +import os, sys, glob +path = os.path.abspath(os.path.realpath(__file__)) +dirpath = os.path.dirname(path) +name = os.path.basename(path) +base_dir = os.path.dirname(dirpath) +frameworks_dir = os.path.join(base_dir, 'Frameworks') +base_name = os.path.splitext(name)[0] +python = os.path.join(base_dir, 'MacOS', 'python') +loader_path = os.path.join(dirpath, base_name+'.py') +loader = open(loader_path, 'w') +site_packages = glob.glob(dirpath+'/*/*/site-packages.zip')[0] +print >>loader, '#!'+python +print >>loader, 'import sys' +print >>loader, 'sys.path.append(', repr(site_packages), ')' +print >>loader, 'sys.frozen = "macosx_app"' +print >>loader, 'sys.frameworks_dir =', repr(frameworks_dir) +print >>loader, 'import os' +print >>loader, 'base =', repr(dirpath) +print >>loader, 'from %(module)s import %(function)s' +print >>loader, '%(function)s()' +loader.close() +os.chmod(loader_path, 0700) +os.environ['PYTHONHOME'] = dirpath +os.execv(loader_path, sys.argv) + ''' + CHECK_SYMLINKS_PRESCRIPT = \ +r''' +def _check_symlinks_prescript(): + import os, tempfile, traceback, sys + from Authorization import Authorization, kAuthorizationFlagDestroyRights + + AUTHTOOL="""#!%s +import os +scripts = %(sp)s +links = %(sp)s +os.setuid(0) +for s, l in zip(scripts, links): + if os.path.lexists(l): + os.remove(l) + print 'Creating link:', l, '->', s + os.symlink(s, l) +""" + + dest_path = %(dest_path)s + resources_path = os.environ['RESOURCEPATH'] + scripts = %(scripts)s + links = [os.path.join(dest_path, i) for i in scripts] + scripts = [os.path.join(resources_path, i) for i in scripts] + + bad = False + for s, l in zip(scripts, links): + if os.path.exists(l) and os.path.exists(os.path.realpath(l)): + continue + bad = True + break + if bad: + auth = Authorization(destroyflags=(kAuthorizationFlagDestroyRights,)) + fd, name = tempfile.mkstemp('.py') + os.write(fd, AUTHTOOL %(pp)s (sys.executable, repr(scripts), repr(links))) + os.close(fd) + os.chmod(name, 0700) + try: + pipe = auth.executeWithPrivileges(name) + sys.stdout.write(pipe.read()) + pipe.close() + except: + traceback.print_exc() + finally: + os.unlink(name) +_check_symlinks_prescript() +''' + def get_modulefinder(self): + if self.debug_modulegraph: + debug = 4 + else: + debug = 0 + return find_modules( + scripts=scripts['console'] + scripts['gui'], + includes=list(self.includes) + main_modules['console'], + packages=self.packages, + excludes=self.excludes, + debug=debug, + ) + + @classmethod + def makedmg(cls, d, volname, + destdir='dist', + internet_enable=True, + format='UDBZ'): + ''' Copy a directory d into a dmg named volname ''' + dmg = os.path.join(destdir, volname+'.dmg') + if os.path.exists(dmg): + os.unlink(dmg) + subprocess.check_call(['hdiutil', 'create', '-srcfolder', os.path.abspath(d), + '-volname', volname, '-format', format, dmg]) + if internet_enable: + subprocess.check_call(['hdiutil', 'internet-enable', '-yes', dmg]) + return dmg + + @classmethod + def qt_dependencies(cls, path): + pipe = subprocess.Popen('otool -L '+path, shell=True, stdout=subprocess.PIPE).stdout + deps = [] + for l in pipe.readlines(): + match = re.search(r'(.*)\(', l) + if not match: + continue + lib = match.group(1).strip() + if lib.startswith(BuildAPP.QT_PREFIX): + deps.append(lib) + return deps + + @classmethod + def fix_qt_dependencies(cls, path, deps): + fp = '@executable_path/../Frameworks/' + print 'Fixing qt dependencies for:', os.path.basename(path) + for dep in deps: + module = re.search(r'(Qt\w+?)\.framework', dep).group(1) + newpath = fp + '%s.framework/Versions/Current/%s'%(module, module) + cmd = ' '.join(['install_name_tool', '-change', dep, newpath, path]) + subprocess.check_call(cmd, shell=True) + + + def add_qt_plugins(self): + macos_dir = os.path.join(self.dist_dir, APPNAME + '.app', 'Contents', 'MacOS') + for root, dirs, files in os.walk(BuildAPP.QT_PREFIX+'/plugins'): + for name in files: + if name.endswith('.dylib'): + path = os.path.join(root, name) + dir = os.path.basename(root) + dest_dir = os.path.join(macos_dir, dir) + if not os.path.exists(dest_dir): + os.mkdir(dest_dir) + target = os.path.join(dest_dir, name) + shutil.copyfile(path, target) + shutil.copymode(path, target) + deps = BuildAPP.qt_dependencies(target) + BuildAPP.fix_qt_dependencies(target, deps) + + + #deps = BuildAPP.qt_dependencies(path) + + + def run(self): + py2app.run(self) + self.add_qt_plugins() + resource_dir = os.path.join(self.dist_dir, + APPNAME + '.app', 'Contents', 'Resources') + all_scripts = scripts['console'] + scripts['gui'] + all_names = basenames['console'] + basenames['gui'] + all_modules = main_modules['console'] + main_modules['gui'] + all_functions = main_functions['console'] + main_functions['gui'] + print + for name, module, function in zip(all_names, all_modules, all_functions): + path = os.path.join(resource_dir, name) + print 'Creating loader:', path + f = open(path, 'w') + f.write(BuildAPP.LOADER_TEMPLATE % dict(module=module, + function=function)) + f.close() + os.chmod(path, stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH|stat.S_IREAD\ + |stat.S_IWUSR|stat.S_IROTH|stat.S_IRGRP) + + print + print 'Installing prescipt' + sf = [os.path.basename(s) for s in all_names] + cs = BuildAPP.CHECK_SYMLINKS_PRESCRIPT % dict(dest_path=repr('/usr/bin'), + scripts=repr(sf), + sp='%s', pp='%') + launcher_path = os.path.join(resource_dir, '__boot__.py') + f = open(launcher_path, 'r') + src = f.read() + f.close() + src = re.sub('(_run\s*\(.*?.py.*?\))', cs+'%s'%( +''' +sys.frameworks_dir = os.path.join(os.path.dirname(os.environ['RESOURCEPATH']), 'Frameworks') +''') + r'\n\1', src) + f = open(launcher_path, 'w') + print >>f, 'import sys, os' + f.write(src) + f.close() + print + print 'Building disk image' + BuildAPP.makedmg(os.path.join(self.dist_dir, APPNAME+'.app'), APPNAME+'-'+VERSION) + + +setup( + name = APPNAME, + app = [scripts['gui'][0]], + cmdclass = { 'py2app' : BuildAPP }, + options = { 'py2app' : + { + 'optimize' : 2, + 'dist_dir' : 'build/py2app', + 'argv_emulation' : True, + 'iconfile' : 'icons/library.icns', + 'frameworks': ['libusb.dylib', 'libunrar.dylib'], + 'includes' : ['sip', 'pkg_resources', 'PyQt4.QtSvg'], + 'packages' : ['PIL', 'Authorization',], + 'excludes' : ['pydoc'], + 'plist' : { 'CFBundleGetInfoString' : '''libprs500, an E-book management application.''' + ''' Visit http://libprs500.kovidgoyal.net for details.''', + 'CFBundleIdentifier':'net.kovidgoyal.librs500', + 'CFBundleShortVersionString':VERSION, + 'CFBundleVersion':APPNAME + ' ' + VERSION, + 'LSMinimumSystemVersion':'10.4.3', + 'LSMultipleInstancesProhibited':'true', + 'NSHumanReadableCopyright':'Copyright 2006, Kovid Goyal', + }, + }, + }, + setup_requires = ['py2app'], + ) diff --git a/setup.py b/setup.py index 2f0f55eab2..fd50aa9550 100644 --- a/setup.py +++ b/setup.py @@ -16,38 +16,10 @@ import sys, re, os, shutil sys.path.append('src') from libprs500 import __version__ as VERSION - -import ez_setup -ez_setup.use_setuptools() -from setuptools import setup, find_packages +from libprs500 import __appname__ as APPNAME -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" - sys.exit(1) - -try: - from PIL import Image -except ImportError: - import Image - print >>sys.stderr, "You do not have the Python Imaging Library correctly installed." - sys.exit(1) - -setup( - name='libprs500', - packages = find_packages('src'), - package_dir = { '' : 'src' }, - version=VERSION, - author='Kovid Goyal', - author_email='kovid@kovidgoyal.net', - url = 'http://libprs500.kovidgoyal.net', - package_data = { - 'libprs500.ebooks' : ['*.jpg', '*.pl'], - 'libpre500.ebooks.lrf.fonts' : ['*.ttf'], - }, - include_package_data = True, - entry_points = { +entry_points = { 'console_scripts': [ \ 'prs500 = libprs500.devices.prs500.cli.main:main', \ 'lrf-meta = libprs500.ebooks.lrf.meta:main', \ @@ -55,222 +27,279 @@ setup( 'txt2lrf = libprs500.ebooks.lrf.txt.convert_from:main', \ 'html2lrf = libprs500.ebooks.lrf.html.convert_from:main',\ ], - 'gui_scripts' : [ 'libprs500 = libprs500.gui.main:main'] - }, - zip_safe = True, - description = - """ - Ebook management application. - """, - long_description = - """ - 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`_. - - 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 - - .. _SONY Portable Reader: http://Sony.com/reader - .. _USB: http://www.usb.org - """, - license = 'GPL', - classifiers = [ - 'Development Status :: 3 - Alpha', - 'Environment :: Console', - 'Environment :: X11 Applications :: Qt', - 'Intended Audience :: Developers', - 'Intended Audience :: End Users/Desktop', - 'License :: OSI Approved :: GNU General Public License (GPL)', - 'Natural Language :: English', - 'Operating System :: POSIX :: Linux', - 'Programming Language :: Python', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Topic :: System :: Hardware :: Hardware Drivers' - ] - ) + 'gui_scripts' : [ APPNAME+' = libprs500.gui.main:main'] + } -if '--uninstall' in ' '.join(sys.argv[1:]): - sys.exit(0) - -try: - import PyQt4 -except ImportError: - print "You do not have PyQt4 installed. The GUI will not work.", \ - "You can obtain PyQt4 from http://www.riverbankcomputing.co.uk/pyqt/download.php" -else: - import PyQt4.QtCore - if PyQt4.QtCore.PYQT_VERSION < 0x40101: - print "WARNING: The GUI needs PyQt >= 4.1.1" - -import os -def options(parse_options): - options, args, parser = parse_options(['dummy'], cli=False) - options = parser.option_list - for group in parser.option_groups: - options += group.option_list - opts = [] - for opt in options: - opts.extend(opt._short_opts) - opts.extend(opt._long_opts) - return opts - -def opts_and_exts(name, op, exts): - opts = ' '.join(options(op)) - exts.extend([i.upper() for i in exts]) - exts='|'.join(exts) - return '_'+name+'()'+\ -''' -{ - local cur prev opts - COMPREPLY=() - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - opts="%s" - pics="@(jpg|jpeg|png|gif|bmp|JPG|JPEG|PNG|GIF|BMP)" - - case "${prev}" in - --cover ) - _filedir "${pics}" - return 0 - ;; - esac - - case "${cur}" in - --cover ) - _filedir "${pics}" - return 0 - ;; - -* ) - COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) - return 0 - ;; - * ) - _filedir '@(%s)' - return 0 - ;; - esac - -} -complete -o filenames -F _'''%(opts,exts) + name + ' ' + name +"\n\n" +def _ep_to_script(ep, base='src'): + return (base+os.path.sep+re.search(r'.*=\s*(.*?):', ep).group(1).replace('.', '/')+'.py').strip() +scripts = { + 'console' : [_ep_to_script(i) for i in entry_points['console_scripts']], + 'gui' : [_ep_to_script(i) for i in entry_points['gui_scripts']], + } -if os.access('/etc/bash_completion.d', os.W_OK): +def _ep_to_basename(ep): + return re.search(r'\s*(.*?)\s*=', ep).group(1).strip() +basenames = { + 'console' : [_ep_to_basename(i) for i in entry_points['console_scripts']], + 'gui' : [_ep_to_basename(i) for i in entry_points['gui_scripts']], + } + +def _ep_to_module(ep): + return re.search(r'.*=\s*(.*?)\s*:', ep).group(1).strip() +main_modules = { + 'console' : [_ep_to_module(i) for i in entry_points['console_scripts']], + 'gui' : [_ep_to_module(i) for i in entry_points['gui_scripts']], + } + +def _ep_to_function(ep): + return ep[ep.rindex(':')+1:].strip() +main_functions = { + 'console' : [_ep_to_function(i) for i in entry_points['console_scripts']], + 'gui' : [_ep_to_function(i) for i in entry_points['gui_scripts']], + } + +if __name__ == '__main__': + from setuptools import setup, find_packages + + 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" + sys.exit(1) + try: - print 'Setting up bash completion...', - sys.stdout.flush() - from libprs500.ebooks.lrf.html.convert_from import parse_options as htmlop - from libprs500.ebooks.lrf.txt.convert_from import parse_options as txtop - from libprs500.ebooks.lrf.meta import parse_options as metaop - f = open('/etc/bash_completion.d/libprs500', 'wb') - f.write('# libprs500 Bash Shell Completion\n') - f.write(opts_and_exts('html2lrf', htmlop, - ['htm', 'html', 'xhtml', 'xhtm', 'rar', 'zip'])) - f.write(opts_and_exts('txt2lrf', txtop, ['txt'])) - f.write(opts_and_exts('lrf-meta', metaop, ['lrf'])) - f.write(''' -_prs500_ls() -{ - local pattern search listing prefix - pattern="$1" - search="$1" - if [[ -n "{$pattern}" ]]; then - if [[ "${pattern:(-1)}" == "/" ]]; then - pattern="" - else - pattern="$(basename ${pattern} 2> /dev/null)" - search="$(dirname ${search} 2> /dev/null)" - fi - fi + from PIL import Image + except ImportError: + import Image + print >>sys.stderr, "You do not have the Python Imaging Library correctly installed." + sys.exit(1) - if [[ "x${search}" == "x" || "x${search}" == "x." ]]; then - search="/" - fi - listing="$(prs500 ls ${search} 2>/dev/null)" - - prefix="${search}" - if [[ "x${prefix:(-1)}" != "x/" ]]; then - prefix="${prefix}/" - fi - - echo $(compgen -P "${prefix}" -W "${listing}" "${pattern}") -} - -_prs500() -{ - local cur prev - cur="${COMP_WORDS[COMP_CWORD]}" - prev="${COMP_WORDS[COMP_CWORD-1]}" - COMPREPLY=() - case "${prev}" in - ls|rm|mkdir|touch|cat ) - COMPREPLY=( $(_prs500_ls "${cur}") ) - return 0 - ;; - cp ) - if [[ ${cur} == prs500:* ]]; then - COMPREPLY=( $(_prs500_ls "${cur:7}") ) - return 0 - else - _filedir - return 0 - fi - ;; - prs500 ) - COMPREPLY=( $(compgen -W "cp ls rm mkdir touch cat info books df" "${cur}") ) - return 0 - ;; - * ) - if [[ ${cur} == prs500:* ]]; then - COMPREPLY=( $(_prs500_ls "${cur:7}") ) - return 0 - else - if [[ ${prev} == prs500:* ]]; then - _filedir + setup( + name='libprs500', + packages = find_packages('src'), + package_dir = { '' : 'src' }, + version=VERSION, + author='Kovid Goyal', + author_email='kovid@kovidgoyal.net', + url = 'http://libprs500.kovidgoyal.net', + include_package_data = True, + entry_points = entry_points, + zip_safe = True, + description = + """ + Ebook management application. + """, + long_description = + """ + 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`_. + + 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 + + .. _SONY Portable Reader: http://Sony.com/reader + .. _USB: http://www.usb.org + """, + license = 'GPL', + classifiers = [ + 'Development Status :: 3 - Alpha', + 'Environment :: Console', + 'Environment :: X11 Applications :: Qt', + 'Intended Audience :: Developers', + 'Intended Audience :: End Users/Desktop', + 'License :: OSI Approved :: GNU General Public License (GPL)', + 'Natural Language :: English', + 'Operating System :: POSIX :: Linux', + 'Programming Language :: Python', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Topic :: System :: Hardware :: Hardware Drivers' + ] + ) + + if '--uninstall' in ' '.join(sys.argv[1:]): + sys.exit(0) + + try: + import PyQt4 + except ImportError: + print "You do not have PyQt4 installed. The GUI will not work.", \ + "You can obtain PyQt4 from http://www.riverbankcomputing.co.uk/pyqt/download.php" + else: + import PyQt4.QtCore + if PyQt4.QtCore.PYQT_VERSION < 0x40101: + print "WARNING: The GUI needs PyQt >= 4.1.1" + + import os + def options(parse_options): + options, args, parser = parse_options(['dummy'], cli=False) + options = parser.option_list + for group in parser.option_groups: + options += group.option_list + opts = [] + for opt in options: + opts.extend(opt._short_opts) + opts.extend(opt._long_opts) + return opts + + def opts_and_exts(name, op, exts): + opts = ' '.join(options(op)) + exts.extend([i.upper() for i in exts]) + exts='|'.join(exts) + return '_'+name+'()'+\ + ''' + { + local cur prev opts + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + opts="%s" + pics="@(jpg|jpeg|png|gif|bmp|JPG|JPEG|PNG|GIF|BMP)" + + case "${prev}" in + --cover ) + _filedir "${pics}" + return 0 + ;; + esac + + case "${cur}" in + --cover ) + _filedir "${pics}" + return 0 + ;; + -* ) + COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) ) + return 0 + ;; + * ) + _filedir '@(%s)' return 0 - else - COMPREPLY=( $(compgen -W "prs500:" "${cur}") ) - return 0 - fi - return 0 + ;; + esac + + } + complete -o filenames -F _'''%(opts,exts) + name + ' ' + name +"\n\n" + + + + if os.access('/etc/bash_completion.d', os.W_OK): + try: + print 'Setting up bash completion...', + sys.stdout.flush() + from libprs500.ebooks.lrf.html.convert_from import parse_options as htmlop + from libprs500.ebooks.lrf.txt.convert_from import parse_options as txtop + from libprs500.ebooks.lrf.meta import parse_options as metaop + f = open('/etc/bash_completion.d/libprs500', 'wb') + f.write('# libprs500 Bash Shell Completion\n') + f.write(opts_and_exts('html2lrf', htmlop, + ['htm', 'html', 'xhtml', 'xhtm', 'rar', 'zip'])) + f.write(opts_and_exts('txt2lrf', txtop, ['txt'])) + f.write(opts_and_exts('lrf-meta', metaop, ['lrf'])) + f.write(''' + _prs500_ls() + { + local pattern search listing prefix + pattern="$1" + search="$1" + if [[ -n "{$pattern}" ]]; then + if [[ "${pattern:(-1)}" == "/" ]]; then + pattern="" + else + pattern="$(basename ${pattern} 2> /dev/null)" + search="$(dirname ${search} 2> /dev/null)" fi - ;; - esac -} -complete -o nospace -F _prs500 prs500 - -''') - f.close() - print 'done' - except: - print 'failed' - - -if os.access('/etc/udev/rules.d', os.W_OK): - from subprocess import check_call - print 'Trying to setup udev rules...', - sys.stdout.flush() - udev = open('/etc/udev/rules.d/95-libprs500.rules', 'w') - udev.write('''# Sony Reader PRS-500\n''' - '''BUS=="usb", SYSFS{idProduct}=="029b", SYSFS{idVendor}=="054c", MODE="660", GROUP="plugdev"\n''' - ) - udev.close() - try: - check_call('udevstart', shell=True) - print 'success' - except: + fi + + if [[ "x${search}" == "x" || "x${search}" == "x." ]]; then + search="/" + fi + + listing="$(prs500 ls ${search} 2>/dev/null)" + + prefix="${search}" + if [[ "x${prefix:(-1)}" != "x/" ]]; then + prefix="${prefix}/" + fi + + echo $(compgen -P "${prefix}" -W "${listing}" "${pattern}") + } + + _prs500() + { + local cur prev + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + COMPREPLY=() + case "${prev}" in + ls|rm|mkdir|touch|cat ) + COMPREPLY=( $(_prs500_ls "${cur}") ) + return 0 + ;; + cp ) + if [[ ${cur} == prs500:* ]]; then + COMPREPLY=( $(_prs500_ls "${cur:7}") ) + return 0 + else + _filedir + return 0 + fi + ;; + prs500 ) + COMPREPLY=( $(compgen -W "cp ls rm mkdir touch cat info books df" "${cur}") ) + return 0 + ;; + * ) + if [[ ${cur} == prs500:* ]]; then + COMPREPLY=( $(_prs500_ls "${cur:7}") ) + return 0 + else + if [[ ${prev} == prs500:* ]]; then + _filedir + return 0 + else + COMPREPLY=( $(compgen -W "prs500:" "${cur}") ) + return 0 + fi + return 0 + fi + ;; + esac + } + complete -o nospace -F _prs500 prs500 + + ''') + f.close() + print 'done' + except: + print 'failed' + + + if os.access('/etc/udev/rules.d', os.W_OK): + from subprocess import check_call + print 'Trying to setup udev rules...', + sys.stdout.flush() + udev = open('/etc/udev/rules.d/95-libprs500.rules', 'w') + udev.write('''# Sony Reader PRS-500\n''' + '''BUS=="usb", SYSFS{idProduct}=="029b", SYSFS{idVendor}=="054c", MODE="660", GROUP="plugdev"\n''' + ) + udev.close() try: - check_call('/etc/init.d/udev reload', shell=True) + check_call('udevstart', shell=True) print 'success' except: - print >>sys.stderr, "Couldn't reload udev, you may have to reboot" - + try: + check_call('/etc/init.d/udev reload', shell=True) + print 'success' + except: + print >>sys.stderr, "Couldn't reload udev, you may have to reboot" + diff --git a/src/libprs500/__init__.py b/src/libprs500/__init__.py index 2b6b300fa3..689794455b 100644 --- a/src/libprs500/__init__.py +++ b/src/libprs500/__init__.py @@ -13,15 +13,25 @@ ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ''' E-book management software''' -__version__ = "0.3.48" +__version__ = "0.3.49" __docformat__ = "epytext" __author__ = "Kovid Goyal " __appname__ = 'libprs500' -import sys +import sys, os iswindows = 'win32' in sys.platform.lower() isosx = 'darwin' in sys.platform.lower() +def load_library(name, cdll): + if iswindows: + return cdll.LoadLibrary(name) + if isosx: + name += '.dylib' + if hasattr(sys, 'frameworks_dir'): + return cdll.LoadLibrary(os.path.join(sys.frameworks_dir, name)) + return cdll.LoadLibrary(name) + return cdll.LoadLibrary(name+'.so') + def filename_to_utf8(name): '''Return C{name} encoded in utf8. Unhandled characters are replaced. ''' codec = 'cp1252' if iswindows else 'utf8' diff --git a/src/libprs500/devices/libusb.py b/src/libprs500/devices/libusb.py index c01e5708ad..4cf4c7e718 100644 --- a/src/libprs500/devices/libusb.py +++ b/src/libprs500/devices/libusb.py @@ -20,20 +20,16 @@ from ctypes import cdll, POINTER, byref, pointer, Structure, \ c_ubyte, c_ushort, c_int, c_char, c_void_p, c_byte, c_uint from errno import EBUSY, ENOMEM -from libprs500 import iswindows, isosx +from libprs500 import iswindows, isosx, load_library -_libusb_name = 'libusb.so' -PATH_MAX = 4096 +_libusb_name = 'libusb' +PATH_MAX = 511 if iswindows else 1024 if isosx else 4096 if iswindows: - PATH_MAX = 511 Structure._pack_ = 1 _libusb_name = 'libusb0' -if isosx: - PATH_MAX = 1024 - _libusb_name = 'libusb.dylib' try: - _libusb = cdll.LoadLibrary(_libusb_name) + _libusb = load_library(_libusb_name, cdll) except OSError: if iswindows or isosx: raise diff --git a/src/libprs500/devices/prs500/books.py b/src/libprs500/devices/prs500/books.py index 7826ca0208..2b5c222b6a 100644 --- a/src/libprs500/devices/prs500/books.py +++ b/src/libprs500/devices/prs500/books.py @@ -185,8 +185,8 @@ class BookList(list): cid = self.max_id()+1 sourceid = str(self[0].sourceid) if len(self) else "1" attrs = { - "title":info["title"], - "author":info["authors"] if info['authors'] else 'Unknown', \ + "title" : info["title"], + "author" : info["authors"] if info['authors'] else 'Unknown', \ "page":"0", "part":"0", "scale":"0", \ "sourceid":sourceid, "id":str(cid), "date":"", \ "mime":mime, "path":name, "size":str(size) diff --git a/src/libprs500/ebooks/lrf/html/convert_from.py b/src/libprs500/ebooks/lrf/html/convert_from.py index 1a6a03b48a..4cf107baee 100644 --- a/src/libprs500/ebooks/lrf/html/convert_from.py +++ b/src/libprs500/ebooks/lrf/html/convert_from.py @@ -1090,15 +1090,7 @@ def process_file(path, options): try: dirpath, path = get_path(path) cpath, tpath = '', '' - isbn = try_opf(path, options) - if not options.cover and isbn: - for item in isbn: - matches = glob.glob(re.sub('-', '', item[1])+'.*') - for match in matches: - if match.lower().endswith('.jpeg') or match.lower().endswith('.jpg') or \ - match.lower().endswith('.gif') or match.lower().endswith('.png'): - options.cover = match - break + try_opf(path, options) if options.cover: options.cover = os.path.abspath(os.path.expanduser(options.cover)) cpath = options.cover @@ -1204,7 +1196,23 @@ def try_opf(path, options): if not scheme: scheme = item.get('opf:scheme') isbn.append((scheme, item.string)) - return isbn + if not options.cover: + for item in isbn: + matches = glob.glob(re.sub('-', '', item[1])+'.*') + for match in matches: + if match.lower().endswith('.jpeg') or match.lower().endswith('.jpg') or \ + match.lower().endswith('.gif') or match.lower().endswith('.png'): + options.cover = match + if not options.cover: + ref = soup.package.find('reference', {'type':'other.ms-coverimage-standard'}) + if ref: + try: + options.cover = ref.get('href') + if not os.access(options.cover, os.R_OK): + options.cover = None + except: + if options.verbose: + traceback.print_exc() except Exception, err: if options.verbose: print >>sys.stderr, 'Failed to process opf file', err diff --git a/src/libprs500/libunrar.py b/src/libprs500/libunrar.py index 6f16b0046d..ae67d8f539 100644 --- a/src/libprs500/libunrar.py +++ b/src/libprs500/libunrar.py @@ -17,22 +17,20 @@ This module provides a thin ctypes based wrapper around libunrar. See ftp://ftp.rarlabs.com/rar/unrarsrc-3.7.5.tar.gz """ -import os +import os, ctypes 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 -from libprs500 import iswindows +from libprs500 import iswindows, isosx, load_library -_librar_name = 'libunrar.so' +_librar_name = 'libunrar' +cdll = ctypes.cdll if iswindows: Structure._pack_ = 1 _librar_name = 'unrar' - from ctypes import windll - _libunrar = windll.LoadLibrary('unrar') -else: - from ctypes import cdll - _libunrar = cdll.LoadLibrary(_librar_name) + cdll = ctypes.windll +_libunrar = load_library(_librar_name, cdll) RAR_OM_LIST = 0 RAR_OM_EXTRACT = 1 diff --git a/upload b/upload deleted file mode 100644 index 666fb0b443..0000000000 --- a/upload +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/python -import sys, glob, os, subprocess -from subprocess import check_call as _check_call -from functools import partial -from pyvix.vix import * - -check_call = partial(_check_call, shell=True) - -check_call("sudo python setup.py develop", shell=True) - -files = glob.glob('dist/*.exe') -for file in files: - os.unlink(file) - - -h = Host(hostType=VIX_SERVICEPROVIDER_VMWARE_WORKSTATION) -vm = h.openVM('/mnt/extra/vmware/Windows Vista/Windows Vista.vmx') -vm.powerOn() -if not vm.waitForToolsInGuest(): - print >>sys.stderr, 'Windows is not booting up' - sys.exit(1) - - - -vm.loginInGuest('kovid', 'et tu brutus') -vm.loginInGuest(VIX_CONSOLE_USER_NAME, '') -vm.runProgramInGuest('C:\\Users\kovid\Desktop\libprs500.bat', '') -vm.runProgramInGuest('C:\Windows\system32\shutdown.exe', '/s') - -if not glob.glob('dist/*.exe'): - raise Exception('Windows build has failed') - - -PREFIX = "/var/www/vhosts/kovidgoyal.net/subdomains/libprs500" -DOWNLOADS = PREFIX+"/httpdocs/downloads" -DOCS = PREFIX+"/httpdocs/apidocs" -exe = os.path.basename(glob.glob('dist/*.exe')[0]) -HTML2LRF = "src/libprs500/ebooks/lrf/html/demo" - -f = open(os.path.join(HTML2LRF, 'demo_ext.html'), 'w') -f.write("

The HTML

\n")
-f.write(open(os.path.join(HTML2LRF, 'demo.html')).read())
-f.write('\n
') -f.close() - - -check_call('''html2lrf --title='Demonstration of html2lrf' --author='Kovid Goyal' --header --output=/tmp/html2lrf.lrf %s/demo.html'''%(HTML2LRF,)) -check_call('''scp /tmp/html2lrf.lrf castalia:%s/'''%(DOWNLOADS,)) - -check_call('''ssh castalia rm -f %s/libprs500\*.exe'''%(DOWNLOADS,)) -check_call('''scp dist/%s castalia:%s/'''%(exe, DOWNLOADS)) -check_call('''ssh castalia chmod a+r %s/\*'''%(DOWNLOADS,)) -check_call('''ssh castalia /root/bin/update-installer-link %s'''%(exe,)) -check_call('''python setup.py register sdist bdist_egg upload''') - -check_call('''epydoc --config epydoc.conf''') -check_call('''scp -r docs/html castalia:%s/'''%(DOCS,)) -check_call('''epydoc -v --config epydoc-pdf.conf''') -check_call('''scp docs/pdf/api.pdf castalia:%s/'''%(DOCS,)) - -check_call('''rm -rf dist/* build/*''') diff --git a/upload.py b/upload.py new file mode 100644 index 0000000000..13d5049773 --- /dev/null +++ b/upload.py @@ -0,0 +1,108 @@ +#!/usr/bin/python +import sys, glob, os, subprocess, time, shutil +sys.path.append('src') +from subprocess import check_call as _check_call +from functools import partial +from pyvix.vix import * + +PREFIX = "/var/www/vhosts/kovidgoyal.net/subdomains/libprs500" +DOWNLOADS = PREFIX+"/httpdocs/downloads" +DOCS = PREFIX+"/httpdocs/apidocs" +HTML2LRF = "src/libprs500/ebooks/lrf/html/demo" +check_call = partial(_check_call, shell=True) +h = Host(hostType=VIX_SERVICEPROVIDER_VMWARE_WORKSTATION) + +def build_windows(): + files = glob.glob('dist/*.exe') + for file in files: + os.unlink(file) + + + + vm = h.openVM('/mnt/extra/vmware/Windows Vista/Windows Vista.vmx') + vm.powerOn() + if not vm.waitForToolsInGuest(): + print >>sys.stderr, 'Windows is not booting up' + sys.exit(1) + + + + vm.loginInGuest('kovid', 'et tu brutus') + vm.loginInGuest(VIX_CONSOLE_USER_NAME, '') + vm.runProgramInGuest('C:\\Users\kovid\Desktop\libprs500.bat', '') + vm.runProgramInGuest('C:\Windows\system32\shutdown.exe', '/s') + + if not glob.glob('dist/*.exe'): + raise Exception('Windows build has failed') + return os.path.basename(glob.glob('dist/*.exe')[-1]) + +def build_osx(): + files = glob.glob('dist/*.dmg') + for file in files: + os.unlink(file) + + vm = h.openVM('/mnt/extra/vmware/Mac OSX/Mac OSX.vmx') + vm.powerOn() + c = 20 * 60 + print 'Waiting (minutes):', + while c > 0: + if glob.glob('dist/*.dmg'): + break + time.sleep(10) + c -= 10 + if c%60==0: + print c, ',', + print + + if not glob.glob('dist/*.dmg'): + raise Exception('OSX build has failed') + vm.powerOff() + return os.path.basename(glob.glob('dist/*.dmg')[-1]) + + + +def upload_demo(): + f = open(os.path.join(HTML2LRF, 'demo_ext.html'), 'w') + f.write("

The HTML

\n")
+    f.write(open(os.path.join(HTML2LRF, 'demo.html')).read())
+    f.write('\n
') + f.close() + check_call('''html2lrf --title='Demonstration of html2lrf' --author='Kovid Goyal' --header --output=/tmp/html2lrf.lrf %s/demo.html'''%(HTML2LRF,)) + check_call('''scp /tmp/html2lrf.lrf castalia:%s/'''%(DOWNLOADS,)) + +def upload_installers(exe, dmg): + check_call('''ssh castalia rm -f %s/libprs500\*.exe'''%(DOWNLOADS,)) + check_call('''scp dist/%s castalia:%s/'''%(exe, DOWNLOADS)) + check_call('''ssh castalia rm -f %s/libprs500\*.dmg'''%(DOWNLOADS,)) + check_call('''scp dist/%s castalia:%s/'''%(dmg, DOWNLOADS)) + check_call('''ssh castalia chmod a+r %s/\*'''%(DOWNLOADS,)) + check_call('''ssh castalia /root/bin/update-installer-links %s %s'''%(exe, dmg)) + +def upload_docs(): + check_call('''epydoc --config epydoc.conf''') + check_call('''scp -r docs/html castalia:%s/'''%(DOCS,)) + check_call('''epydoc -v --config epydoc-pdf.conf''') + check_call('''scp docs/pdf/api.pdf castalia:%s/'''%(DOCS,)) + + + +def main(): + shutil.rmtree('build') + os.mkdir('build') + shutil.rmtree('docs') + os.mkdir('docs') + check_call("sudo python setup.py develop", shell=True) + upload_demo() + print 'Building OSX installer...' + dmg = build_osx() + print 'Building Windows installer...' + exe = build_windows() + print 'Uploading installers...' + upload_installers(exe, dmg) + print 'Uploading to PyPI' + check_call('''python setup.py register sdist bdist_egg upload''') + upload_docs() + check_call('''rm -rf dist/* build/*''') + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/windows_installer.py b/windows_installer.py index c1630fb7c7..1de133dc53 100644 --- a/windows_installer.py +++ b/windows_installer.py @@ -1,6 +1,20 @@ +## 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. ''' Create a windows installer ''' import sys, re, os, shutil, subprocess -sys.path.append('src') +from setup import VERSION, APPNAME, entry_points, scripts, basenames sys.argv[1:2] = ['py2exe'] if '--verbose' not in ' '.join(sys.argv): sys.argv.append('--quiet') #py2exe produces too much output by default @@ -210,7 +224,7 @@ SectionEnd os.remove(path) -class BuildInstaller(build_exe): +class BuildEXE(build_exe): manifest_resource_id = 0 MANIFEST_TEMPLATE = ''' @@ -249,20 +263,7 @@ class BuildInstaller(build_exe): print 'Adding', qtxmldll shutil.copyfile(qtxmldll, os.path.join(self.dist_dir, os.path.basename(qtxmldll))) - print 'Copying fonts' - dest_dir = os.path.join(self.dist_dir, 'fonts') - if os.path.exists(dest_dir): - shutil.rmtree(dest_dir, True) - fl = FileList() - fl.include_pattern('^src.*\.ttf$', is_regex=True) - fl.findall() - for file in fl.files: - dir = os.path.join(dest_dir, os.path.basename(os.path.dirname(file))) - if not os.path.exists(dir): - os.makedirs(dir) - print file - shutil.copy(file, dir) print print 'Building Installer' installer = NSISInstaller(APPNAME, self.dist_dir, 'dist') @@ -274,20 +275,17 @@ class BuildInstaller(build_exe): return (24, cls.manifest_resource_id, cls.MANIFEST_TEMPLATE % dict(prog=prog, version=VERSION+'.0')) +console = [dict(dest_base=basenames['console'][i], script=scripts['console'][i]) + for i in range(len(scripts['console']))] + setup( - cmdclass = {'py2exe': BuildInstaller}, - windows = [{'script' : 'src/libprs500/gui/main.py', + cmdclass = {'py2exe': BuildEXE}, + windows = [{'script' : scripts['gui'][0], 'dest_base' : APPNAME, 'icon_resources' : [(1, 'icons/library.ico')], - 'other_resources' : [BuildInstaller.manifest(APPNAME)], + 'other_resources' : [BuildEXE.manifest(APPNAME)], },], - console = [ - {'script' : 'src/libprs500/devices/prs500/cli/main.py', 'dest_base':'prs500'}, - {'script' : 'src/libprs500/ebooks/lrf/html/convert_from.py', 'dest_base':'html2lrf'}, - {'script' : 'src/libprs500/ebooks/lrf/txt/convert_from.py', 'dest_base':'txt2lrf'}, - {'script' : 'src/libprs500/ebooks/lrf/meta.py', 'dest_base':'lrf-meta'}, - {'script' : 'src/libprs500/ebooks/metadata/rtf.py', 'dest_base':'rtf-meta'}, - ], + console = console, options = { 'py2exe' : {'compressed': 1, 'optimize' : 2, 'dist_dir' : r'build\py2exe', @@ -299,5 +297,4 @@ setup( }, }, - ) - + ) \ No newline at end of file