mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
sync to trunk.
This commit is contained in:
commit
b6c7517f86
@ -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)
|
||||
|
10
installer/osx/py2app/__init__.py
Normal file
10
installer/osx/py2app/__init__.py
Normal 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'
|
||||
|
||||
|
||||
|
51
installer/osx/py2app/launcher.py
Normal file
51
installer/osx/py2app/launcher.py
Normal 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()
|
30
installer/osx/py2app/loader.py
Normal file
30
installer/osx/py2app/loader.py
Normal 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
1002
installer/osx/py2app/main.c
Normal file
File diff suppressed because it is too large
Load Diff
479
installer/osx/py2app/main.py
Normal file
479
installer/osx/py2app/main.py
Normal 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())
|
106
installer/osx/py2app/site.py
Normal file
106
installer/osx/py2app/site.py
Normal 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
|
@ -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.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:
|
||||
|
16
setup.py
16
setup.py
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
@ -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><p>Markdown is a simple markup language for text files, that allows for advanced formatting. To learn more visit <a href="http://daringfireball.net/projects/markdown">markdown</a>.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
@ -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)
|
||||
|
@ -677,15 +677,12 @@
|
||||
<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">
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
@ -693,12 +690,14 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<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">
|
||||
@ -709,6 +708,15 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_osx_symlinks">
|
||||
<property name="text">
|
||||
<string>&Install command line tools</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
@ -716,15 +724,13 @@
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<width>153</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_4">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
|
BIN
src/calibre/gui2/images/news/hln_be.png
Normal file
BIN
src/calibre/gui2/images/news/hln_be.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 359 B |
@ -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?
|
||||
|
@ -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->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
@ -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_'
|
||||
|
@ -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);
|
||||
|
57
src/calibre/utils/osx_symlinks.py
Normal file
57
src/calibre/utils/osx_symlinks.py
Normal 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
|
||||
|
@ -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) {
|
||||
|
@ -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',
|
||||
)]
|
||||
|
||||
|
||||
|
@ -15,19 +15,15 @@ class DeStandaard(BasicNewsRecipe):
|
||||
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?')
|
||||
|
35
src/calibre/web/feeds/recipes/recipe_hln_be.py
Normal file
35
src/calibre/web/feeds/recipes/recipe_hln_be.py
Normal 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')]
|
49
src/calibre/web/feeds/recipes/recipe_honvedelem.py
Normal file
49
src/calibre/web/feeds/recipes/recipe_honvedelem.py
Normal 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')
|
||||
]
|
||||
|
29
src/calibre/web/feeds/recipes/recipe_theoldfoodie.py
Normal file
29
src/calibre/web/feeds/recipes/recipe_theoldfoodie.py
Normal 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')]
|
@ -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', '')
|
||||
|
63
upload.py
63
upload.py
@ -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):
|
||||
|
Loading…
x
Reference in New Issue
Block a user