mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Created OS X installer. Added automatic detection of cover page for conversion of HTML generated by CLIT.
This commit is contained in:
parent
d243ebecda
commit
aaa6bc4c3f
@ -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
|
||||
|
@ -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
|
||||
|
222
ez_setup.py
222
ez_setup.py
@ -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:])
|
||||
|
||||
|
||||
|
||||
|
||||
|
BIN
icons/library.icns
Normal file
BIN
icons/library.icns
Normal file
Binary file not shown.
241
osx_installer.py
Normal file
241
osx_installer.py
Normal file
@ -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'],
|
||||
)
|
489
setup.py
489
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`_.
|
||||
'gui_scripts' : [ APPNAME+' = libprs500.gui.main:main']
|
||||
}
|
||||
|
||||
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
|
||||
;;
|
||||
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']],
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
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)"
|
||||
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`_.
|
||||
|
||||
prefix="${search}"
|
||||
if [[ "x${prefix:(-1)}" != "x/" ]]; then
|
||||
prefix="${prefix}/"
|
||||
fi
|
||||
It can also convert various popular ebook formats into LRF, the native
|
||||
ebook format of the SONY Reader.
|
||||
|
||||
echo $(compgen -P "${prefix}" -W "${listing}" "${pattern}")
|
||||
}
|
||||
For screenshots: https://libprs500.kovidgoyal.net/wiki/Screenshots
|
||||
|
||||
_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
|
||||
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
|
||||
fi
|
||||
|
||||
''')
|
||||
f.close()
|
||||
print 'done'
|
||||
except:
|
||||
print 'failed'
|
||||
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('udevstart', shell=True)
|
||||
print 'success'
|
||||
except:
|
||||
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"
|
||||
|
||||
|
@ -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 <kovid@kovidgoyal.net>"
|
||||
__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'
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
61
upload
61
upload
@ -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("<h2>The HTML</h2><pre>\n")
|
||||
f.write(open(os.path.join(HTML2LRF, 'demo.html')).read())
|
||||
f.write('\n</pre>')
|
||||
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/*''')
|
108
upload.py
Normal file
108
upload.py
Normal file
@ -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("<h2>The HTML</h2><pre>\n")
|
||||
f.write(open(os.path.join(HTML2LRF, 'demo.html')).read())
|
||||
f.write('\n</pre>')
|
||||
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()
|
@ -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 = '''
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
@ -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',
|
||||
@ -300,4 +298,3 @@ setup(
|
||||
},
|
||||
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user