sync to trunk.

This commit is contained in:
John Schember 2009-09-02 07:00:18 -04:00
commit b6c7517f86
31 changed files with 2315 additions and 378 deletions

View File

@ -54,54 +54,7 @@ os.environ['QT_PLUGIN_PATH'] = qt_plugins
args = [path, loader_path] + sys.argv[1:]
os.execv(python, args)
'''
CHECK_SYMLINKS_PRESCRIPT = \
r'''
def _check_symlinks_prescript():
import os, tempfile, traceback, sys
from Authorization import Authorization, kAuthorizationFlagDestroyRights
AUTHTOOL="""#!%(sp)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
omask = os.umask(022)
os.symlink(s, l)
os.umask(omask)
"""
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, 'loaders', 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(sys.executable, 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
@ -286,15 +239,12 @@ _check_symlinks_prescript()
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 = src.replace('import Image', 'from PIL import Image')
src = re.sub('(_run\s*\(.*?.py.*?\))', cs+'%s'%(
src = re.sub('(_run\s*\(.*?.py.*?\))', '%s'%(
'''
sys.frameworks_dir = os.path.join(os.path.dirname(os.environ['RESOURCEPATH']), 'Frameworks')
''') + r'\n\1', src)

View File

@ -0,0 +1,10 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'

View File

@ -0,0 +1,51 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
def _disable_linecache():
import linecache
def fake_getline(*args, **kwargs):
return ''
linecache.orig_getline = linecache.getline
linecache.getline = fake_getline
_disable_linecache()
def _recipes_pil_prescript(plugins):
from PIL import Image
import sys
def init():
if Image._initialized >= 2:
return
for plugin in plugins:
try:
__import__(plugin, globals(), locals(), [])
except ImportError:
if Image.DEBUG:
print 'Image: failed to import'
print plugin, ':', sys.exc_info()[1]
if Image.OPEN or Image.SAVE:
Image._initialized = 2
Image.init = init
_recipes_pil_prescript(['Hdf5StubImagePlugin', 'FitsStubImagePlugin', 'SunImagePlugin', 'GbrImagePlugin', 'PngImagePlugin', 'MicImagePlugin', 'FpxImagePlugin', 'PcxImagePlugin', 'ImImagePlugin', 'SpiderImagePlugin', 'PsdImagePlugin', 'BufrStubImagePlugin', 'SgiImagePlugin', 'McIdasImagePlugin', 'XpmImagePlugin', 'BmpImagePlugin', 'TgaImagePlugin', 'PalmImagePlugin', 'XVThumbImagePlugin', 'GribStubImagePlugin', 'ArgImagePlugin', 'PdfImagePlugin', 'ImtImagePlugin', 'GifImagePlugin', 'CurImagePlugin', 'WmfImagePlugin', 'MpegImagePlugin', 'IcoImagePlugin', 'TiffImagePlugin', 'PpmImagePlugin', 'MspImagePlugin', 'EpsImagePlugin', 'JpegImagePlugin', 'PixarImagePlugin', 'PcdImagePlugin', 'IptcImagePlugin', 'XbmImagePlugin', 'DcxImagePlugin', 'IcnsImagePlugin', 'FliImagePlugin'])
def _run():
global __file__
import os, sys, site
sys.frozen = 'macosx_app'
base = os.environ['RESOURCEPATH']
sys.frameworks_dir = os.path.join(os.path.dirname(base, 'Frameworks'))
sys.new_app_bundle = True
site.addsitedir(base)
site.addsitedir(os.path.join(base, 'Python', 'site-packages'))
exe = os.environ.get('CALIBRE_LAUNCH_MODULE', 'calibre.gui2.main')
exe = os.path.join(base, 'Python', 'site-packages', *exe.split('.'))
sys.argv[0] = __file__ = exe
execfile(exe, globals(), globals())
_run()

View File

@ -0,0 +1,30 @@
#!/usr/bin/env python
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import os, sys
ENV = {}##ENV##
MODULE = ''##MODULE##
path = os.path.abspath(os.path.realpath(__file__))
dirpath = os.path.dirname(path)
name = os.path.basename(path)
base_dir = os.path.dirname(os.path.dirname(dirpath))
resources_dir = os.path.join(base_dir, 'Resources')
frameworks_dir = os.path.join(base_dir, 'Frameworks')
exe_dir = os.path.join(base_dir, 'MacOS')
base_name = os.path.splitext(name)[0]
python = os.path.join(base_dir, 'MacOS', 'calibre')
for key, val in ENV.items():
if val.startswith('@exec'):
ENV[key] = os.path.normpath(val.replace('@executable_path', exe_dir))
ENV['CALIBRE_LAUNCH_MODULE'] = MODULE
os.environ.update(ENV)
args = [path] + sys.argv[1:]
os.execv(python, args)

1002
installer/osx/py2app/main.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,479 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import sys, os, shutil, plistlib, subprocess, glob, zipfile, tempfile, \
py_compile, stat, operator
abspath, join, basename = os.path.abspath, os.path.join, os.path.basename
l = {}
exec open('setup.py').read() in l
VERSION = l['VERSION']
APPNAME = l['APPNAME']
scripts = l['scripts']
basenames = l['basenames']
main_functions = l['main_functions']
main_modules = l['main_modules']
LICENSE = open('LICENSE', 'rb').read()
ENV = dict(
FC_CONFIG_DIR='@executable_path/../Resources/fonts',
MAGICK_HOME='@executable_path/../Frameworks/ImageMagick',
PYTHONDONTWRITEBYTECODE='1',
PYTHONIOENCODING='utf-8:replace',
PYTHONPATH='@executable_path/../Resources/Python/site-packages',
PYTHONHOME='@executable_path/../Resources/Python',
QT_PLUGIN_PATH='@executable_path'
)
SW = os.environ.get('SW')
def flipwritable(fn, mode=None):
"""
Flip the writability of a file and return the old mode. Returns None
if the file is already writable.
"""
if os.access(fn, os.W_OK):
return None
old_mode = os.stat(fn).st_mode
os.chmod(fn, stat.S_IWRITE | old_mode)
return old_mode
STRIPCMD = ['/usr/bin/strip', '-x', '-S', '-']
def strip_files(files, argv_max=(256 * 1024)):
"""
Strip a list of files
"""
tostrip = [(fn, flipwritable(fn)) for fn in files]
while tostrip:
cmd = list(STRIPCMD)
flips = []
pathlen = reduce(operator.add, [len(s) + 1 for s in cmd])
while pathlen < argv_max:
if not tostrip:
break
added, flip = tostrip.pop()
pathlen += len(added) + 1
cmd.append(added)
flips.append((added, flip))
else:
cmd.pop()
tostrip.append(flips.pop())
os.spawnv(os.P_WAIT, cmd[0], cmd)
for args in flips:
flipwritable(*args)
class Py2App(object):
FID = '@executable_path/../Frameworks'
def __init__(self, build_dir):
self.build_dir = build_dir
self.contents_dir = join(self.build_dir, 'Contents')
self.resources_dir = join(self.contents_dir, 'Resources')
self.frameworks_dir = join(self.contents_dir, 'Frameworks')
self.to_strip = []
def run(self):
self.create_skeleton()
self.create_plist()
self.add_python_framework()
self.add_qt_frameworks()
self.add_calibre_plugins()
self.add_podofo()
self.add_poppler()
self.add_libjpeg()
self.add_libpng()
self.add_fontconfig()
self.add_imagemagick()
self.add_misc_libraries()
self.add_site_packages()
self.add_stdlib()
self.compile_py_modules()
self.create_console_app()
self.copy_launcher_and_site()
self.create_exe()
self.strip_files()
self.create_launchers()
return self.makedmg(self.build_dir, APPNAME+'-'+VERSION+'-x86_64')
def create_launchers(self):
launcher = join(os.path.dirname(__file__), 'launcher.py')
launcher = open(launcher, 'rb').read()
launcher = launcher.replace('{}##ENV##', repr(ENV))
os.mkdir(join(self.resources_dir, 'loaders'))
for module, basename in zip(main_modules, basenames):
raw = launcher.replace("''##MODULE##", repr(module))
path = join(self.resources_dir, 'loaders', basename)
open(path, 'wb').write(raw)
os.chmod(path, stat.S_IXUSR|stat.S_IXGRP|stat.S_IXOTH|stat.S_IREAD\
|stat.S_IWUSR|stat.S_IROTH|stat.S_IRGRP)
def strip_files(self):
print '\nStripping files...'
strip_files(self.to_strip)
def create_exe(self):
gcc = os.environ.get('CC', 'gcc')
base = os.path.dirname(__file__)
out = join(self.contents_dir, 'MacOS', 'calibre')
subprocess.check_call([gcc, '-Wall', '-arch', 'x86_64', join(base,
'main.c'), '-o', out])
self.to_strip.append(out)
def set_id(self, path_to_lib, new_id):
old_mode = flipwritable(path_to_lib)
subprocess.check_call(['install_name_tool', '-id', new_id, path_to_lib])
if old_mode is not None:
flipwritable(path_to_lib, old_mode)
def get_dependencies(self, path_to_lib):
raw = subprocess.Popen(['otool', '-L', path_to_lib],
stdout=subprocess.PIPE).stdout.read()
for line in raw.splitlines():
if 'compatibility' not in line:
continue
idx = line.find('(')
path = line[:idx].strip()
bname = os.path.basename(path).partition('.')[0]
if bname in path_to_lib:
continue
yield path
def get_local_dependencies(self, path_to_lib):
for x in self.get_dependencies(path_to_lib):
for y in (SW+'/lib/', '/usr/local/lib/', SW+'/qt/lib/',
SW+'/python/'):
if x.startswith(y):
yield x, x[len(y):]
break
def change_dep(self, old_dep, new_dep, path_to_lib):
print '\tResolving dependency %s to'%old_dep, new_dep
subprocess.check_call(['install_name_tool', '-change', old_dep, new_dep,
path_to_lib])
def fix_dependencies_in_lib(self, path_to_lib):
print '\nFixing dependencies in', path_to_lib
self.to_strip.append(path_to_lib)
old_mode = flipwritable(path_to_lib)
for dep, bname in self.get_local_dependencies(path_to_lib):
ndep = self.FID+'/'+bname
self.change_dep(dep, ndep, path_to_lib)
if list(self.get_local_dependencies(path_to_lib)):
raise Exception('Failed to resolve deps in: '+path_to_lib)
if old_mode is not None:
flipwritable(path_to_lib, old_mode)
def add_python_framework(self):
src = join(SW, 'python', 'Python.framework')
x = join(self.frameworks_dir, 'Python.framework')
curr = os.path.realpath(join(src, 'Versions', 'Current'))
currd = join(x, 'Versions', basename(curr))
rd = join(currd, 'Resources')
os.makedirs(rd)
shutil.copy2(join(curr, 'Resources', 'Info.plist'), rd)
shutil.copy2(join(curr, 'Python'), currd)
self.set_id(join(currd, 'Python'),
self.FID+'/Python.framework/Versions/%s/Python'%basename(curr))
def add_qt_frameworks(self):
for f in ('QtCore', 'QtGui', 'QtXml', 'QtNetwork', 'QtSvg', 'QtWebkit',
'phonon'):
self.add_qt_framework(f)
for d in glob.glob(join(SW, 'qt', 'plugins', '*')):
shutil.copytree(d, join(self.contents_dir, 'MacOS', basename(d)))
for l in glob.glob(join(self.contents_dir, 'MacOS', '*/*.dylib')):
self.fix_dependencies_in_lib(l)
x = os.path.relpath(l, join(self.contents_dir, 'MacOS'))
self.set_id(l, '@executable_path/'+x)
def add_qt_framework(self, f):
libname = f
f = f+'.framework'
src = join(SW, 'qt', 'lib', f)
ignore = shutil.ignore_patterns('Headers', '*.h', 'Headers/*')
dest = join(self.frameworks_dir, f)
shutil.copytree(src, dest, symlinks=True,
ignore=ignore)
lib = os.path.realpath(join(dest, libname))
rpath = os.path.relpath(lib, self.frameworks_dir)
self.set_id(lib, self.FID+'/'+rpath)
self.fix_dependencies_in_lib(lib)
def create_skeleton(self):
c = join(self.build_dir, 'Contents')
for x in ('Frameworks', 'MacOS', 'Resources'):
os.makedirs(join(c, x))
x = 'library.icns'
shutil.copyfile(join('icons', x), join(self.resources_dir, x))
def add_calibre_plugins(self):
dest = join(self.frameworks_dir, 'plugins')
os.mkdir(dest)
for f in glob.glob('src/calibre/plugins/*.so'):
shutil.copy2(f, dest)
self.fix_dependencies_in_lib(join(dest, basename(f)))
def create_plist(self):
pl = dict(
CFBundleDevelopmentRegion='English',
CFBundleDisplayName=APPNAME,
CFBundleName=APPNAME,
CFBundleIdentifier='net.kovidgoyal.calibre',
CFBundleVersion=VERSION,
CFBundlePackageType='APPL',
CFBundleSignature='????',
CFBundleExecutable='calibre',
LSMinimumSystemVersion='10.5.2',
PyRuntimeLocations=[self.FID+'/Python.framework/Versions/Current/Python'],
LSRequiresNativeExecution=True,
NSAppleScriptEnabled=False,
NSHumanReadableCopyright='Copyright 2008, Kovid Goyal',
CFBundleGetInfoString=('calibre, an E-book management '
'application. Visit http://calibre.kovidgoyal.net for details.'),
CFBundleIconFile='library.icns',
LSMultipleInstancesProhibited=True,
LSEnvironment=ENV
)
plistlib.writePlist(pl, join(self.contents_dir, 'Info.plist'))
def install_dylib(self, path, set_id=True):
shutil.copy2(path, self.frameworks_dir)
if set_id:
self.set_id(join(self.frameworks_dir, basename(path)),
self.FID+'/'+basename(path))
self.fix_dependencies_in_lib(join(self.frameworks_dir, basename(path)))
def add_podofo(self):
print '\nAdding PoDoFo'
pdf = join(SW, 'lib', 'libpodofo.0.6.99.dylib')
self.install_dylib(pdf)
def add_poppler(self):
print '\nAdding poppler'
for x in ('libpoppler.4.dylib', 'libpoppler-qt4.3.dylib'):
self.install_dylib(os.path.join(SW, 'lib', x))
self.install_dylib(os.path.join(SW, 'bin', 'pdftohtml'), False)
def add_libjpeg(self):
print '\nAdding libjpeg'
self.install_dylib(os.path.join(SW, 'lib', 'libjpeg.7.dylib'))
def add_libpng(self):
print '\nAdding libpng'
self.install_dylib(os.path.join(SW, 'lib', 'libpng12.0.dylib'))
def add_fontconfig(self):
print '\nAdding fontconfig'
for x in ('fontconfig.1', 'freetype.6', 'expat.1'):
src = os.path.join(SW, 'lib', 'lib'+x+'.dylib')
self.install_dylib(src)
dst = os.path.join(self.resources_dir, 'fonts')
if os.path.exists(dst):
shutil.rmtree(dst)
src = os.path.join(SW, 'etc', 'fonts')
shutil.copytree(src, dst, symlinks=False)
fc = os.path.join(dst, 'fonts.conf')
raw = open(fc, 'rb').read()
raw = raw.replace('<dir>/usr/share/fonts</dir>', '''\
<dir>/Library/Fonts</dir>
<dir>/Network/Library/Fonts</dir>
<dir>/System/Library/Fonts</dir>
<dir>/usr/X11R6/lib/X11/fonts</dir>
<dir>/usr/share/fonts</dir>
<dir>/var/root/Library/Fonts</dir>
<dir>/usr/share/fonts</dir>
''')
open(fc, 'wb').write(raw)
def add_imagemagick(self):
print '\nAdding ImageMagick'
for x in ('Wand', 'Core'):
self.install_dylib(os.path.join(SW, 'lib', 'libMagick%s.2.dylib'%x))
idir = glob.glob(os.path.join(SW, 'lib', 'ImageMagick-*'))[-1]
dest = os.path.join(self.frameworks_dir, 'ImageMagick', 'lib')
if not os.path.exists(dest):
os.makedirs(dest)
dest = os.path.join(dest, os.path.basename(idir))
if os.path.exists(dest):
shutil.rmtree(dest)
shutil.copytree(idir, dest, True)
for x in os.walk(dest):
for f in x[-1]:
if f.endswith('.so'):
f = join(x[0], f)
self.fix_dependencies_in_lib(f)
def add_misc_libraries(self):
for x in ('usb', 'unrar'):
print '\nAdding', x
shutil.copy2(join(SW, 'lib', 'lib%s.dylib'%x), self.frameworks_dir)
def add_site_packages(self):
print '\nAdding site-packages'
self.site_packages = join(self.resources_dir, 'Python', 'site-packages')
os.makedirs(self.site_packages)
paths = reversed(map(abspath, [x for x in sys.path if x.startswith('/')]))
upaths = []
for x in paths:
if x not in upaths:
upaths.append(x)
for x in upaths:
if x.endswith('/PIL') or 'site-packages' not in x:
continue
tdir = None
try:
if not os.path.isdir(x):
try:
zf = zipfile.ZipFile(x)
except:
print "WARNING:", x, 'is neither a directory nor a zipfile'
continue
tdir = tempfile.mkdtemp()
zf.extractall(tdir)
x = tdir
self.add_modules_from_dir(x)
self.add_packages_from_dir(x)
finally:
if tdir is not None:
shutil.rmtree(tdir)
self.remove_bytecode(join(self.resources_dir, 'Python', 'site-packages'))
def add_modules_from_dir(self, src):
for x in glob.glob(join(src, '*.py'))+glob.glob(join(src, '*.so')):
dest = join(self.site_packages, basename(x))
shutil.copy2(x, self.site_packages)
if x.endswith('.so'):
self.fix_dependencies_in_lib(x)
def add_packages_from_dir(self, src):
for x in os.listdir(src):
x = join(src, x)
if os.path.isdir(x) and os.path.exists(join(x, '__init__.py')):
if self.filter_package(basename(x)):
continue
self.add_package_dir(x)
def add_package_dir(self, x, dest=None):
def ignore(root, files):
ans = []
for y in files:
if os.path.splitext(y) in ('.py', '.so'):
continue
ans.append(y)
return ans
if dest is None:
dest = self.site_packages
dest = join(dest, basename(x))
shutil.copytree(x, dest, symlinks=True, ignore=ignore)
self.postprocess_package(x, dest)
def filter_package(self, name):
return name in ('Cython', 'modulegraph', 'macholib', 'py2app',
'bdist_mpkg', 'altgraph')
def postprocess_package(self, src_path, dest_path):
pass
def add_stdlib(self):
print '\nAdding python stdlib'
src = join(SW, 'python/Python.framework/Versions/Current/lib/python')
src += '.'.join(map(str, sys.version_info[:2]))
dest = join(self.resources_dir, 'Python', 'lib', 'python')
dest += '.'.join(map(str, sys.version_info[:2]))
for x in os.listdir(src):
if x in ('site-packages', 'config', 'test', 'lib2to3', 'lib-tk',
'lib-old', 'idlelib', 'plat-mac', 'plat-darwin', 'site.py'):
continue
if os.path.isdir(x):
self.add_package_dir(join(src, x), dest)
elif os.path.splitext(x) in ('.so', '.py'):
shutil.copy2(join(src, x), dest)
dest = join(dest, basename(x))
if dest.endswith('.so'):
self.fix_dependencies_in_lib(dest)
self.remove_bytecode(join(self.resources_dir, 'Python', 'lib'))
def remove_bytecode(self, dest):
for x in os.walk(dest):
root = x[0]
for f in x[-1]:
if os.path.splitext(f) in ('.pyc', '.pyo'):
os.remove(join(root, f))
def compile_py_modules(self):
print '\nCompiling Python modules'
base = join(self.resources_dir, 'Python')
for x in os.walk(base):
root = x[0]
for f in x[-1]:
if f.endswith('.py'):
y = join(root, f)
rel = os.path.relpath(y, base)
try:
py_compile.compile(y, dfile=rel, doraise=True)
os.remove(y)
except:
print 'WARNING: Failed to byte-compile', y
def create_console_app(self):
print '\nCreating console.app'
cc_dir = os.path.join(self.contents_dir, 'console.app', 'Contents')
os.makedirs(cc_dir)
for x in os.listdir(self.contents_dir):
if x == 'console.app':
continue
if x == 'Info.plist':
plist = plistlib.readPlist(join(self.contents_dir, x))
plist['LSUIElement'] = '1'
plistlib.writePlist(plist, join(cc_dir, x))
else:
os.symlink(join('../..', x),
join(cc_dir, x))
def copy_launcher_and_site(self):
base = os.path.dirname(__file__)
for x in ('launcher', 'site'):
shutil.copy2(join(base, x+'.py'), self.resources_dir)
def makedmg(self, d, volname,
destdir='dist',
internet_enable=True,
format='UDBZ'):
''' Copy a directory d into a dmg named volname '''
if not os.path.exists(destdir):
os.makedirs(destdir)
dmg = os.path.join(destdir, volname+'.dmg')
if os.path.exists(dmg):
os.unlink(dmg)
subprocess.check_call(['/usr/bin/hdiutil', 'create', '-srcfolder', os.path.abspath(d),
'-volname', volname, '-format', format, dmg])
if internet_enable:
subprocess.check_call(['/usr/bin/hdiutil', 'internet-enable', '-yes', dmg])
return dmg
def main():
build_dir = abspath(join('build', APPNAME+'.app'))
if os.path.exists(build_dir):
shutil.rmtree(build_dir)
os.makedirs(build_dir)
py2app = Py2App(build_dir)
py2app.run()
return 0
if __name__ == '__main__':
sys.exit(main())

View File

@ -0,0 +1,106 @@
"""
Append module search paths for third-party packages to sys.path.
This is stripped down and customized for use in py2app applications
"""
import sys
import os
def makepath(*paths):
dir = os.path.abspath(os.path.join(*paths))
return dir, os.path.normcase(dir)
for m in sys.modules.values():
f = getattr(m, '__file__', None)
if isinstance(f, basestring) and os.path.exists(f):
m.__file__ = os.path.abspath(m.__file__)
del m
# This ensures that the initial path provided by the interpreter contains
# only absolute pathnames, even if we're running from the build directory.
L = []
_dirs_in_sys_path = {}
dir = dircase = None # sys.path may be empty at this point
for dir in sys.path:
# Filter out duplicate paths (on case-insensitive file systems also
# if they only differ in case); turn relative paths into absolute
# paths.
dir, dircase = makepath(dir)
if not dircase in _dirs_in_sys_path:
L.append(dir)
_dirs_in_sys_path[dircase] = 1
sys.path[:] = L
del dir, dircase, L
_dirs_in_sys_path = None
def _init_pathinfo():
global _dirs_in_sys_path
_dirs_in_sys_path = d = {}
for dir in sys.path:
if dir and not os.path.isdir(dir):
continue
dir, dircase = makepath(dir)
d[dircase] = 1
def addsitedir(sitedir):
global _dirs_in_sys_path
if _dirs_in_sys_path is None:
_init_pathinfo()
reset = 1
else:
reset = 0
sitedir, sitedircase = makepath(sitedir)
if not sitedircase in _dirs_in_sys_path:
sys.path.append(sitedir) # Add path component
try:
names = os.listdir(sitedir)
except os.error:
return
names.sort()
for name in names:
if name[-4:] == os.extsep + "pth":
addpackage(sitedir, name)
if reset:
_dirs_in_sys_path = None
def addpackage(sitedir, name):
global _dirs_in_sys_path
if _dirs_in_sys_path is None:
_init_pathinfo()
reset = 1
else:
reset = 0
fullname = os.path.join(sitedir, name)
try:
f = open(fullname)
except IOError:
return
while 1:
dir = f.readline()
if not dir:
break
if dir[0] == '#':
continue
if dir.startswith("import"):
exec dir
continue
if dir[-1] == '\n':
dir = dir[:-1]
dir, dircase = makepath(sitedir, dir)
if not dircase in _dirs_in_sys_path and os.path.exists(dir):
sys.path.append(dir)
_dirs_in_sys_path[dircase] = 1
if reset:
_dirs_in_sys_path = None
sys.setdefaultencoding('utf-8')
#
# Remove sys.setdefaultencoding() so that users cannot change the
# encoding after initialization. The test for presence is needed when
# this module is run as a script, because this code is executed twice.
#
if hasattr(sys, "setdefaultencoding"):
del sys.setdefaultencoding

View File

@ -23,13 +23,24 @@ elif find_executable('qmake'):
QMAKE = find_executable('qmake')
QMAKE = os.environ.get('QMAKE', QMAKE)
WINDOWS_PYTHON = ['C:/Python26/libs']
OSX_SDK = '/Developer/SDKs/MacOSX10.4u.sdk'
OSX_SDK = '/Developer/SDKs/MacOSX10.5.sdk'
if not os.path.exists(OSX_SDK):
OSX_SDK = '/Developer/SDKs/MacOSX10.4u.sdk'
leopard_build = '10.5' in OSX_SDK
def replace_suffix(path, new_suffix):
return os.path.splitext(path)[0] + new_suffix
class Extension(_Extension):
pass
def __init__(self, *args, **kwargs):
if leopard_build:
prev = kwargs.get('extra_compile_args', [])
prev.extend(['-arch', 'ppc64', '-arch', 'x86_64'])
kwargs['extra_compile_args'] = prev
_Extension.__init__(self, *args, **kwargs)
if iswindows:
from distutils import msvc9compiler
@ -38,7 +49,6 @@ if iswindows:
nmake = msvc.find_exe('nmake.exe')
rc = msvc.find_exe('rc.exe')
class PyQtExtension(Extension):
def __init__(self, name, sources, sip_sources, **kw):
@ -66,6 +76,7 @@ class build_ext(_build_ext):
cwd = os.getcwd()
sources = map(os.path.abspath, ext.sources)
os.chdir(bdir)
archs = 'x86_64 ppc64' if leopard_build else 'x86 ppc'
try:
headers = set([f for f in sources if f.endswith('.h')])
sources = set(sources) - headers
@ -76,10 +87,13 @@ TEMPLATE = lib
HEADERS = %s
SOURCES = %s
VERSION = 1.0.0
CONFIG += x86 ppc
'''%(name, ' '.join(headers), ' '.join(sources))
CONFIG += %s
'''%(name, ' '.join(headers), ' '.join(sources), archs)
open(name+'.pro', 'wb').write(pro)
self.spawn([QMAKE, '-o', 'Makefile.qt', name+'.pro'])
if leopard_build:
raw = open('Makefile.qt', 'rb').read()
open('Makefile.qt', 'wb').write(raw.replace('ppc64', 'x86_64'))
self.make('Makefile.qt')
pat = 'release\\*.obj' if iswindows else '*.o'
return map(os.path.abspath, glob.glob(pat))
@ -116,6 +130,13 @@ CONFIG += x86 ppc
makefile.generate()
cwd = os.getcwd()
os.chdir(bdir)
if leopard_build:
mf = 'Makefile.pyqt'
raw = open(mf, 'rb').read()
raw = raw.replace('ppc64 x86_64', 'x86_64')
for x in ('ppc64', 'ppc', 'i386'):
raw = raw.replace(x, 'x86_64')
open(mf, 'wb').write(raw)
try:
self.make('Makefile.pyqt')
finally:

View File

@ -71,7 +71,9 @@ if __name__ == '__main__':
tag_release, upload_demo, build_linux, build_windows, \
build_osx, upload_installers, upload_user_manual, \
upload_to_pypi, stage3, stage2, stage1, upload, \
upload_rss, betas, build_linux32, build_linux64
upload_rss, betas, build_linux32, build_linux64, \
build_osx64
resources.SCRIPTS = list(basenames['console']+basenames['gui'])
entry_points['console_scripts'].append(
'calibre_postinstall = calibre.linux:post_install')
@ -147,14 +149,19 @@ if __name__ == '__main__':
r'C:\cygwin\home\kovid\fontconfig\lib' if iswindows else \
'/Users/kovid/fontconfig/lib'
fc_inc = os.environ.get('FC_INC_DIR', fc_inc)
fc_lib = os.environ.get('FC_LIB_DIR', fc_lib)
if not os.path.exists(os.path.join(fc_inc, 'fontconfig.h')):
print 'ERROR: fontconfig not found on your system.',
print 'Use the FC_INC_DIR and FC_LIB_DIR environment variables.'
raise SystemExit(1)
ext_modules = optional + [
Extension('calibre.plugins.fontconfig',
sources = ['src/calibre/utils/fonts/fontconfig.c'],
include_dirs = [os.environ.get('FC_INC_DIR', fc_inc)],
include_dirs = [fc_inc],
libraries=['fontconfig'],
library_dirs=[os.environ.get('FC_LIB_DIR', fc_lib)]),
library_dirs=[fc_lib]),
Extension('calibre.plugins.lzx',
sources=['src/calibre/utils/lzx/lzxmodule.c',
@ -262,6 +269,7 @@ if __name__ == '__main__':
'build_linux64' : build_linux64,
'build_windows' : build_windows,
'build_osx' : build_osx,
'build_osx64' : build_osx64,
'upload_installers': upload_installers,
'upload_user_manual': upload_user_manual,
'upload_to_pypi': upload_to_pypi,

View File

@ -262,7 +262,7 @@ class Device(DeviceConfig, DevicePlugin):
return True
return False
time.sleep(6)
time.sleep(8)
drives = {}
wmi = __import__('wmi', globals(), locals(), [], -1)
c = wmi.WMI(find_classes=False)

View File

@ -26,7 +26,7 @@
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <mach/mach.h>
static PyObject *
usbobserver_get_usb_devices(PyObject *self, PyObject *args) {
@ -67,7 +67,7 @@ usbobserver_get_usb_devices(PyObject *self, PyObject *args) {
return NULL;
}
while (usbDevice = IOIteratorNext(iter)) {
while ((usbDevice = IOIteratorNext(iter))) {
plugInInterface = NULL; dev = NULL;
//Create an intermediate plugin
kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score);

View File

@ -3,7 +3,7 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
"""
Edit metadata in RTF files.
"""
import re, cStringIO, sys
import re, cStringIO, codecs
from calibre.ebooks.metadata import MetaInformation, string_to_authors
@ -52,6 +52,32 @@ def get_document_info(stream):
break
return data.getvalue(), pos
def detect_codepage(stream):
pat = re.compile(r'\\ansicpg(\d+)')
match = pat.search(stream.read(512))
if match is not None:
num = match.group(1)
if num == '0':
num = '1250'
codec = 'cp'+num
try:
codecs.lookup(codec)
return codec
except:
pass
def decode(raw, codec):
if codec is not None:
def codepage(match):
return chr(int(match.group(1), 16))
raw = re.sub(r"\\'([a-fA-F0-9]{2})", codepage, raw)
raw = raw.decode(codec)
def uni(match):
return unichr(int(match.group(1)))
raw = re.sub(r'\\u([0-9]{4}).', uni, raw)
return raw
def get_metadata(stream):
""" Return metadata as a L{MetaInfo} object """
title, author, comment, category = None, None, None, None
@ -62,18 +88,22 @@ def get_metadata(stream):
if not block:
return MetaInformation(None, None)
stream.seek(0)
cpg = detect_codepage(stream)
stream.seek(0)
title_match = title_pat.search(block)
if title_match:
title = title_match.group(1).strip()
title = decode(title_match.group(1).strip(), cpg)
author_match = author_pat.search(block)
if author_match:
author = author_match.group(1).strip()
author = decode(author_match.group(1).strip(), cpg)
comment_match = comment_pat.search(block)
if comment_match:
comment = comment_match.group(1).strip()
comment = decode(comment_match.group(1).strip(), cpg)
category_match = category_pat.search(block)
if category_match:
category = category_match.group(1).strip()
category = decode(category_match.group(1).strip(), cpg)
mi = MetaInformation(title, author)
if author:
mi.authors = string_to_authors(author)

View File

@ -48,8 +48,10 @@ class DetectStructure(object):
if opts.toc_filter is not None:
regexp = re.compile(opts.toc_filter)
for node in self.oeb.toc.iter():
for node in list(self.oeb.toc.iter()):
if not node.title or regexp.search(node.title) is not None:
self.log('Filtering', node.title if node.title else\
'empty node', 'from TOC')
self.oeb.toc.remove(node)
if opts.page_breaks_before is not None:
@ -104,6 +106,7 @@ class DetectStructure(object):
counter += 1
def create_toc_from_links(self):
num = 0
for item in self.oeb.spine:
for a in XPath('//h:a[@href]')(item.data):
href = a.get('href')
@ -118,8 +121,13 @@ class DetectStructure(object):
a.xpath('descendant::text()')])
text = text[:100].strip()
if not self.oeb.toc.has_text(text):
num += 1
self.oeb.toc.add(text, href,
play_order=self.oeb.toc.next_play_order())
if self.opts.max_toc_links > 0 and \
num >= self.opts.max_toc_links:
self.log('Maximum TOC links reached, stopping.')
return

View File

@ -14,7 +14,7 @@
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<item row="3" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -41,6 +41,16 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;p&gt;Markdown is a simple markup language for text files, that allows for advanced formatting. To learn more visit &lt;a href=&quot;http://daringfireball.net/projects/markdown&quot;&gt;markdown&lt;/a&gt;.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>

View File

@ -10,7 +10,7 @@ from PyQt4.Qt import QDialog, QListWidgetItem, QIcon, \
QDialogButtonBox, QTabWidget, QBrush, QLineEdit, \
QProgressDialog
from calibre.constants import islinux, iswindows
from calibre.constants import islinux, iswindows, isosx
from calibre.gui2.dialogs.config.config_ui import Ui_Dialog
from calibre.gui2 import qstring_to_unicode, choose_dir, error_dialog, config, \
ALL_COLUMNS, NONE, info_dialog, choose_files, \
@ -450,6 +450,9 @@ class ConfigDialog(QDialog, Ui_Dialog):
self.connect(self.remove_plugin, SIGNAL('clicked()'), lambda : self.modify_plugin(op='remove'))
self.connect(self.button_plugin_browse, SIGNAL('clicked()'), self.find_plugin)
self.connect(self.button_plugin_add, SIGNAL('clicked()'), self.add_plugin)
self.connect(self.button_osx_symlinks, SIGNAL('clicked()'),
self.create_symlinks)
self.button_osx_symlinks.setVisible(isosx)
self.separate_cover_flow.setChecked(config['separate_cover_flow'])
self.setup_email_page()
self.category_view.setCurrentIndex(self.category_view.model().index(0))
@ -458,6 +461,13 @@ class ConfigDialog(QDialog, Ui_Dialog):
self.delete_news.setEnabled)
self.setup_conversion_options()
def create_symlinks(self):
from calibre.utils.osx_symlinks import create_symlinks
loc, paths = create_symlinks()
info_dialog(self, _('Command line tools installed'),
_('Command line tools installed in')+' '+loc,
det_msg=paths, show=True)
def setup_conversion_options(self):
self.conversion_options = ConfigTabs(self)
self.stackedWidget.insertWidget(2, self.conversion_options)

View File

@ -677,28 +677,27 @@
<widget class="QWidget" name="page_7">
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="AddSave" name="add_save">
</widget>
<widget class="AddSave" name="add_save"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<layout class="QVBoxLayout">
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<layout class="QHBoxLayout">
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>154</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_12">
<item>
<widget class="QToolButton" name="compact_button">
<property name="toolTip">
@ -710,20 +709,27 @@
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
<widget class="QPushButton" name="button_osx_symlinks">
<property name="text">
<string>&amp;Install command line tools</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</widget>
</item>
</layout>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>153</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_4">

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

View File

@ -107,6 +107,11 @@ Now you should be able to access your books on your iPhone by opening Stanza and
Replace ``192.168.1.2`` with the local IP address of the computer running |app|. If you have changed the port the |app| content server is running on, you will have to change ``8080`` as well to the new port. The local IP address is the IP address you computer is assigned on your home network. A quick Google search will tell you how to find out your local IP address.
I get the error message "Failed to start content server: Port 8080 not free on '0.0.0.0'"?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The most likely cause of this is your antivirus program. Try temporarily disabling it and see if it does the trick.
Why is my device not detected in linux?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -216,7 +221,7 @@ Your antivirus program is wrong. |app| is a completely open source product. You
How do I use purchased EPUB books with |app|?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Most purchased EPUB books have `DRM <http://wiki.mobileread.com/wiki/DRM>`_. This prevents |app| from opening them. You can still use |app| to store and transfer them to your SONY Reader. First, you must authorize your reader on a windows machine with Adobe DIgital Editions. Once this is done, EPUB books transferred with |app| will work fine on your reader. Sometimes, the EPUB file itself is corrupted, in which case you should notify the e-book vendor.
Most purchased EPUB books have `DRM <http://wiki.mobileread.com/wiki/DRM>`_. This prevents |app| from opening them. You can still use |app| to store and transfer them to your SONY Reader. First, you must authorize your reader on a windows machine with Adobe Digital Editions. Once this is done, EPUB books transferred with |app| will work fine on your reader. Sometimes, the EPUB file itself is corrupted, in which case you should notify the e-book vendor.
I want some feature added to |app|. What can I do?

View File

@ -185,7 +185,7 @@ else:
note=Markup(\
u'''
<ol>
<li>Before trying to use the command line tools, you must run the app at least once. This will ask you for you password and then setup the symbolic links for the command line tools.</li>
<li>To install the command line tools, go to Preferences-&gt;Advanced</li>
<li>The app cannot be run from within the dmg. You must drag it to a folder on your filesystem (The Desktop, Applications, wherever).</li>
<li>In order for localization of the user interface in your language, select your language in the preferences (by pressing u\2318+P) and select your language.</li>
</ol>

File diff suppressed because it is too large Load Diff

View File

@ -73,8 +73,13 @@ isosx = 'darwin' in sys.platform
isfrozen = getattr(sys, 'frozen', False)
if isosx:
_lib = os.path.join(getattr(sys, 'frameworks_dir'), 'ImageMagick', 'libMagickWand.dylib') \
if isfrozen else util.find_library('Wand')
if isfrozen:
fd = getattr(sys, 'frameworks_dir')
_lib = os.path.join(fd, 'libMagickWand.2.dylib')
if not os.path.exists(_lib):
_lib = os.path.join(fd, 'ImageMagick', 'libMagickWand.dylib')
else:
_lib = util.find_library('Wand')
elif iswindows:
_lib = os.path.join(os.path.dirname(sys.executable), 'CORE_RL_wand_.dll') \
if isfrozen else 'CORE_RL_wand_'

View File

@ -18,7 +18,7 @@
static PyObject *
fontconfig_initialize(PyObject *self, PyObject *args) {
char *path;
FcChar8 *path;
FcBool ok;
FcConfig *config;
PyThreadState *_save;
@ -44,7 +44,7 @@ fontconfig_initialize(PyObject *self, PyObject *args) {
Py_RETURN_FALSE;
}
static
static void
fontconfig_cleanup_find(FcPattern *p, FcObjectSet *oset, FcFontSet *fs) {
if (p != NULL) FcPatternDestroy(p);
if (oset != NULL) FcObjectSetDestroy(oset);
@ -105,13 +105,13 @@ fontconfig_find_font_families(PyObject *self, PyObject *args) {
ext = PyBytes_AS_STRING(PySequence_ITEM(exts, j));
extlen = PyBytes_GET_SIZE(PySequence_ITEM(exts, j));
ok = flen > extlen && extlen > 0 &&
PyOS_strnicmp(ext, v.u.s + (flen - extlen), extlen) == 0;
PyOS_strnicmp(ext, ((char *)v.u.s) + (flen - extlen), extlen) == 0;
}
if (ok) {
if (FcPatternGet(temp, FC_FAMILY, 0, &w) != FcResultMatch) continue;
if (w.type != FcTypeString) continue;
t = PyString_FromString(w.u.s);
t = PyString_FromString((char *)w.u.s);
if (t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
if (PyList_Append(ans, t) != 0)
{ fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
@ -169,16 +169,16 @@ fontconfig_files_for_family(PyObject *self, PyObject *args) {
temp = PyTuple_New(6);
if(temp == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
t = PyBytes_FromString(fullname.u.s);
t = PyBytes_FromString((char *)fullname.u.s);
if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
PyTuple_SET_ITEM(temp, 0, t);
t = PyBytes_FromString(file.u.s);
t = PyBytes_FromString((char *)file.u.s);
if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
PyTuple_SET_ITEM(temp, 1, t);
t = PyBytes_FromString(style.u.s);
t = PyBytes_FromString((char *)style.u.s);
if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
PyTuple_SET_ITEM(temp, 2, t);
t = PyBytes_FromString(family2.u.s);
t = PyBytes_FromString((char *)family2.u.s);
if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
PyTuple_SET_ITEM(temp, 3, t);
t = PyInt_FromLong((long)weight.u.i);
@ -197,7 +197,7 @@ fontconfig_files_for_family(PyObject *self, PyObject *args) {
static PyObject *
fontconfig_match(PyObject *self, PyObject *args) {
char *namespec; int i;
FcChar8 *namespec; int i;
FcPattern *pat, *tp;
FcObjectSet *oset;
FcFontSet *fs, *fs2;
@ -255,16 +255,16 @@ fontconfig_match(PyObject *self, PyObject *args) {
temp = PyTuple_New(6);
if(temp == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
t = PyBytes_FromString(fullname.u.s);
t = PyBytes_FromString((char *)fullname.u.s);
if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
PyTuple_SET_ITEM(temp, 0, t);
t = PyBytes_FromString(file.u.s);
t = PyBytes_FromString((char *)file.u.s);
if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
PyTuple_SET_ITEM(temp, 1, t);
t = PyBytes_FromString(style.u.s);
t = PyBytes_FromString((char *)style.u.s);
if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
PyTuple_SET_ITEM(temp, 2, t);
t = PyBytes_FromString(family.u.s);
t = PyBytes_FromString((char *)family.u.s);
if(t == NULL) { fontconfig_cleanup_find(pat, oset, fs); return PyErr_NoMemory(); }
PyTuple_SET_ITEM(temp, 3, t);
t = PyInt_FromLong((long)weight.u.i);

View File

@ -0,0 +1,57 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
AUTHTOOL="""#!%s
import os
scripts = %s
links = %s
os.setuid(0)
for s, l in zip(scripts, links):
if os.path.lexists(l):
os.remove(l)
print 'Creating link:', l, '->', s
omask = os.umask(022)
os.symlink(s, l)
os.umask(omask)
"""
DEST_PATH = '/usr/bin'
def create_symlinks():
import os, tempfile, traceback, sys
from Authorization import Authorization, kAuthorizationFlagDestroyRights
from calibre.resources import scripts
resources_path = os.environ['RESOURCEPATH']
links = [os.path.join(DEST_PATH, i) for i in scripts]
scripts = [os.path.join(resources_path, 'loaders', 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 % (sys.executable, repr(scripts), repr(links)))
os.close(fd)
os.chmod(name, 0700)
try:
pipe = auth.executeWithPrivileges(sys.executable, name)
sys.stdout.write(pipe.read())
pipe.close()
except:
traceback.print_exc()
finally:
os.unlink(name)
return DEST_PATH, links

View File

@ -144,7 +144,6 @@ podofo_PDFDoc_version_getter(podofo_PDFDoc *self, void *closure) {
static PyObject *
podofo_PDFDoc_extract_first_page(podofo_PDFDoc *self, PyObject *args, PyObject *kwargs) {
int i, num_pages;
try {
while (self->doc->GetPageCount() > 1) self->doc->GetPagesTree()->DeletePage(1);
} catch(const PdfError & err) {

View File

@ -56,7 +56,7 @@ recipe_modules = ['recipe_' + r for r in (
'volksrant', 'theeconomictimes_india', 'ourdailybread',
'monitor', 'republika', 'beta', 'beta_en', 'glasjavnosti',
'esquire', 'livemint', 'thedgesingapore', 'darknet', 'rga',
'intelligencer',
'intelligencer', 'theoldfoodie', 'hln_be', 'honvedelem',
)]

View File

@ -9,25 +9,21 @@ from calibre.web.feeds.news import BasicNewsRecipe
class DeStandaard(BasicNewsRecipe):
title = u'De Standaard'
__author__ = u'Darko Miletic'
language = _('Dutch')
language = _('Dutch')
description = u'News from Belgium'
oldest_article = 7
max_articles_per_feed = 100
no_stylesheets = True
use_embedded_content = False
encoding = 'utf-8'
keep_only_tags = [dict(name='div' , attrs={'id':'_parts_midContainer_div'})]
remove_tags_after = dict(name='h3', attrs={'title':'Binnenland'})
remove_tags = [
dict(name='h3' , attrs={'title':'Binnenland' })
,dict(name='p' , attrs={'class':'by' })
,dict(name='div' , attrs={'class':'articlesright'})
,dict(name='a' , attrs={'class':'help' })
,dict(name='a' , attrs={'class':'archive' })
,dict(name='a' , attrs={'class':'print' })
,dict(name='a' , attrs={'class':'email' })
]
keep_only_tags = [dict(name='div' , attrs={'id':['intro','continued']})]
feeds = [
(u'De Standaard Online', u'http://feeds.feedburner.com/dso-front')
]
feeds = [(u'De Standaard Online', u'http://feeds.feedburner.com/dso-front')]
def get_article_url(self, article):
return article.get('guid', None)
def print_version(self, url):
return url.replace('/Detail.aspx?','/PrintArtikel.aspx?')

View File

@ -0,0 +1,35 @@
#!/usr/bin/env python
__license__ = 'GPL v3'
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
'''
www.hln.be
'''
from calibre.web.feeds.news import BasicNewsRecipe
class HLN_be(BasicNewsRecipe):
title = 'HLN Belgium'
__author__ = 'Darko Miletic'
description = 'Belgium news'
publisher = 'HLN'
category = 'news, politics, Belgium'
oldest_article = 2
max_articles_per_feed = 100
use_embedded_content = False
no_stylesheets = True
encoding = 'utf-8'
language = _('Dutch')
conversion_options = {
'comments' : description
,'tags' : category
,'language' : 'nl-NL'
,'publisher' : publisher
}
remove_tags = [dict(name=['form','object','embed'])]
keep_only_tags = [dict(name='div', attrs={'id':'art_box2'})]
feeds = [(u'Articles', u'http://www.hln.be/rss.xml')]

View File

@ -0,0 +1,49 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
from calibre.web.feeds.news import BasicNewsRecipe
class HunMilNews(BasicNewsRecipe):
title = u'Honvedelem.hu'
oldest_article = 3
description = u'Katonah\xedrek'
language = _('Hungarian')
lang = 'hu'
encoding = 'windows-1250'
category = 'news, military'
no_stylesheets = True
__author__ = 'Devilinside'
max_articles_per_feed = 16
no_stylesheets = True
keep_only_tags = [dict(name='div', attrs={'class':'cikkoldal_cikk_cim'}),
dict(name='div', attrs={'class':'cikkoldal_cikk_alcim'}),
dict(name='div', attrs={'class':'cikkoldal_datum'}),
dict(name='div', attrs={'class':'cikkoldal_lead'}),
dict(name='div', attrs={'class':'cikkoldal_szoveg'}),
dict(name='img', attrs={'class':'ajanlo_kep_keretes'}),
]
feeds = [(u'Misszi\xf3k', u'http://www.honvedelem.hu/rss_b?c=22'),
(u'Aktu\xe1lis hazai h\xedrek', u'http://www.honvedelem.hu/rss_b?c=3'),
(u'K\xfclf\xf6ldi h\xedrek', u'http://www.honvedelem.hu/rss_b?c=4'),
(u'A h\xf3nap t\xe9m\xe1ja', u'http://www.honvedelem.hu/rss_b?c=6'),
(u'Riport', u'http://www.honvedelem.hu/rss_b?c=5'),
(u'Portr\xe9k', u'http://www.honvedelem.hu/rss_b?c=7'),
(u'Haditechnika', u'http://www.honvedelem.hu/rss_b?c=8'),
(u'Programok, esem\xe9nyek', u'http://www.honvedelem.hu/rss_b?c=12')
]

View File

@ -0,0 +1,29 @@
#!/usr/bin/env python
__license__ = 'GPL v3'
__copyright__ = '2009, Darko Miletic <darko.miletic at gmail.com>'
'''
www.theoldfoodie.com
'''
from calibre.web.feeds.news import BasicNewsRecipe
class TheOldFoodie(BasicNewsRecipe):
title = 'The Old Foodie'
__author__ = 'Darko Miletic'
description = 'Food blog'
category = 'cuisine, food, blog'
oldest_article = 30
max_articles_per_feed = 100
use_embedded_content = True
no_stylesheets = True
encoding = 'utf-8'
language = _('English')
conversion_options = {
'comments' : description
,'tags' : category
,'language' : 'en'
}
feeds = [(u'Articles', u'http://www.theoldfoodie.com/feeds/posts/default?alt=rss')]

View File

@ -13,7 +13,7 @@ class ZeitDe(BasicNewsRecipe):
title = 'Die Zeit Nachrichten'
description = 'Die Zeit - Online Nachrichten'
language = _('German')
__author__ = 'Kovid Goyal'
__author__ = 'Kovid Goyal and Martin Pitt'
use_embedded_content = False
timefmt = ' [%d %b %Y]'
max_articles_per_feed = 40
@ -21,7 +21,14 @@ class ZeitDe(BasicNewsRecipe):
encoding = 'latin1'
feeds = [ ('Zeit.de', 'http://newsfeed.zeit.de/news/index') ]
feeds = [ ('Kurznachrichten', 'http://newsfeed.zeit.de/news/index'),
('Politik', 'http://newsfeed.zeit.de/politik/index'),
('Wirtschaft', 'http://newsfeed.zeit.de/wirtschaft/index'),
('Meinung', 'http://newsfeed.zeit.de/meinung/index'),
('Gesellschaft', 'http://newsfeed.zeit.de/gesellschaft/index'),
('Kultur', 'http://newsfeed.zeit.de/kultur/index'),
('Wissen', 'http://newsfeed.zeit.de/wissen/index'),
]
def print_version(self,url):
return url.replace('http://www.zeit.de/', 'http://images.zeit.de/text/').replace('?from=rss', '')

View File

@ -167,7 +167,7 @@ class resources(OptionlessCommand):
translations_found = True
break
if not translations_found:
print 'WARNING: Could not find Qt transations'
print 'WARNING: Could not find Qt translations'
return data
def get_static_resources(self):
@ -216,7 +216,8 @@ class resources(OptionlessCommand):
static, smax = self.get_static_resources()
recipes, rmax = self.get_recipes()
hyphenate, hmax = self.get_hyphenate()
amax = max(rmax, smax, hmax, os.stat(__file__).st_mtime)
lmax = os.stat(os.path.join('src', 'calibre', 'linux.py')).st_mtime
amax = max(rmax, smax, hmax, lmax, os.stat(__file__).st_mtime)
if newer([dest], RESOURCES.values()) or os.stat(dest).st_mtime < amax:
print 'Compiling resources...'
with open(dest, 'wb') as f:
@ -226,6 +227,7 @@ class resources(OptionlessCommand):
f.write('server_resources = %s\n\n'%repr(static))
f.write('recipes = %s\n\n'%repr(recipes))
f.write('hyphenate = %s\n\n'%repr(hyphenate))
f.write('scripts = %r\n\n'%self.SCRIPTS)
f.write('build_time = "%s"\n\n'%time.strftime('%d %m %Y %H%M%S'))
else:
print 'Resources are up to date'
@ -504,6 +506,8 @@ class VMInstaller(OptionlessCommand):
user_options = [('dont-shutdown', 'd', 'Dont shutdown VM after build')]
boolean_options = ['dont-shutdown']
EXTRA_SLEEP = 5
BUILD_CMD = 'ssh -t %s bash build-calibre'
INIT_CMD = ''
def initialize_options(self):
self.dont_shutdown = False
@ -511,6 +515,7 @@ class VMInstaller(OptionlessCommand):
BUILD_SCRIPT = textwrap.dedent('''\
#!/bin/bash
export CALIBRE_BUILDBOT=1
%%s
cd ~/build && \
rsync -avz --exclude src/calibre/plugins \
--exclude calibre/src/calibre.egg-info --exclude docs \
@ -519,12 +524,13 @@ class VMInstaller(OptionlessCommand):
rsync://%(host)s/work/%(project)s . && \
cd %(project)s && \
%%s && \
rm -rf build/* dist/* && \
rm -rf build/* dist/* src/calibre/plugins/* && \
%%s %%s
'''%dict(host=HOST, project=__appname__))
def get_build_script(self, subs):
return self.BUILD_SCRIPT%subs
subs = [self.INIT_CMD]+list(subs)
return self.BUILD_SCRIPT%tuple(subs)
def vmware_started(self):
return 'started' in subprocess.Popen('/etc/init.d/vmware status', shell=True, stdout=subprocess.PIPE).stdout.read()
@ -562,16 +568,7 @@ class VMInstaller(OptionlessCommand):
time.sleep(self.EXTRA_SLEEP)
print 'Trying to SSH into VM'
check_call(('scp', t.name, ssh_host+':build-calibre'))
check_call('ssh -t %s bash build-calibre'%ssh_host, shell=True)
class KVMInstaller(VMInstaller):
def run_vm(self):
self.stop_vmware()
check_call('sudo modprobe kvm-intel', shell=True)
self.__p = Popen(self.VM)
check_call(self.BUILD_CMD%ssh_host, shell=True)
class build_linux32(VMInstaller):
@ -582,7 +579,7 @@ class build_linux32(VMInstaller):
installer = installer_name('tar.bz2').replace('x86_64', 'i686')
self.start_vm('gentoo32_build', ('sudo python setup.py develop && sudo chown -R kovid:users *',
'python', 'installer/linux/freeze.py'))
check_call(('scp', 'gentoo32_build:build/calibre/dist/*.dmg', 'dist'))
check_call(('scp', 'gentoo32_build:build/calibre/dist/*.bz2', 'dist'))
if not os.path.exists(installer):
raise Exception('Failed to build installer '+installer)
if not self.dont_shutdown:
@ -624,22 +621,44 @@ class build_windows(VMInstaller):
class build_osx(VMInstaller):
description = 'Build OS X app bundle'
VM = '/vmware/bin/tiger_build'
FREEZE_SCRIPT = 'installer/osx/freeze.py'
VM_NAME = 'tiger_build'
PYTHON = '/Library/Frameworks/Python.framework/Versions/Current/bin/python'
DEVELOP = 'sudo %s setup.py develop'
def get_build_script(self, subs):
return (self.BUILD_SCRIPT%subs).replace('rm ', 'sudo rm ')
return VMInstaller.get_build_script(self, subs).replace('rm ', 'sudo rm ')
def installer_name(self):
return installer_name('dmg')
def run(self):
installer = installer_name('dmg')
python = '/Library/Frameworks/Python.framework/Versions/Current/bin/python'
self.start_vm('tiger_build', ('sudo %s setup.py develop'%python, python,
'installer/osx/freeze.py'))
check_call(('scp', 'tiger_build:build/calibre/dist/*.dmg', 'dist'))
installer = self.installer_name()
python = self.PYTHON
self.start_vm(self.VM_NAME, (self.DEVELOP%python, python,
self.FREEZE_SCRIPT))
check_call(('scp', self.VM_NAME+':build/calibre/dist/*.dmg', 'dist'))
if not os.path.exists(installer):
raise Exception('Failed to build installer '+installer)
if not self.dont_shutdown:
Popen(('ssh', 'tiger_build', 'sudo', '/sbin/shutdown', '-h', 'now'))
Popen(('ssh', self.VM_NAME, 'sudo', '/sbin/shutdown', '-h', 'now'))
return os.path.basename(installer)
class build_osx64(build_osx):
description = 'Build OS X 64-bit app bundle'
VM = '/vmware/bin/leopard_build'
FREEZE_SCRIPT = 'installer/osx/py2app/main.py'
VM_NAME = 'leopard_build'
PYTHON = '/sw/bin/python -OO'
DEVELOP = '%s setup.py develop'
BUILD_CMD = 'ssh -t %s bash --login build-calibre'
INIT_CMD = 'source ~/.profile'
def installer_name(self):
return installer_name('dmg').replace('.dmg', '-x86_64.dmg')
class upload_installers(OptionlessCommand):
description = 'Upload any installers present in dist/'
def curl_list_dir(self, url=MOBILEREAD, listonly=1):