Sync to trunk.

This commit is contained in:
John Schember 2009-12-21 18:14:49 -05:00
commit fd81ca32a9
20 changed files with 844 additions and 404 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,64 @@
from calibre.web.feeds.news import BasicNewsRecipe
class StrategyBusinessRecipe(BasicNewsRecipe):
__license__ = 'GPL v3'
__author__ = 'kwetal'
language = 'en'
version = 1
title = u'Strategy+Business'
publisher = u' Booz & Company'
category = u'Business'
description = u'Business magazine for senior business executives and the people who influence them.'
oldest_article = 13 * 7 # 3 months
max_articles_per_feed = 100
use_embedded_content = False
remove_empty_feeds = True
no_stylesheets = True
remove_javascript = True
extra_css = '''
body{font-family:verdana,arial,helvetica,geneva,sans-serif ;}
a {text-decoration: none; color: blue;}
h1 {margin: 0em; padding: 0em;}
h2 {font-size: medium; font-weight: bold;}
#sb-date {font-size: xx-small; color: #696969}
#category {font-style: italic; font-size: small; color: black; margin: 0em; padding: 0em;}
#byline {font-size: small; color: #666666}
div.profiles {font-size: small; font-style: italic; color: #696969}
div.profiles h2 {font-size: medium; font-style: normal; font-weight: bold; color: black}
'''
feeds = []
feeds.append((u'Finance', u'http://feeds.feedburner.com/StrategyBusiness-Finance?format=xml'))
feeds.append((u'Global Perspective', u'http://feeds.feedburner.com/StrategyBusiness-GlobalPerspective?format=xml'))
feeds.append((u'Innovation', u'http://feeds.feedburner.com/StrategyBusiness-Innovation?format=xml'))
feeds.append((u'Marketing And Sales', u'http://feeds.feedburner.com/StrategyBusiness-MarketingAndSales?format=xml'))
feeds.append((u'Operations And Manufacturing', u'http://feeds.feedburner.com/StrategyBusiness-OperationsAndManufacturing?format=xml'))
feeds.append((u'Organizations And People', u'http://feeds.feedburner.com/StrategyBusiness-OrganizationsAndPeople?format=xml'))
feeds.append((u'Strategy And Leadership', u'http://feeds.feedburner.com/StrategyBusiness-StrategyAndLeadership?format=xml'))
feeds.append((u'Sustainability', u'http://feeds.feedburner.com/StrategyBusiness-Sustainability?format=xml'))
feeds.append((u'Auto, Airlines And Transport', u'http://feeds.feedburner.com/StrategyBusiness-AutoAirlinesAndTransport?format=xml'))
feeds.append((u'Consumer Products', u'http://feeds.feedburner.com/StrategyBusiness-ConsumerProducts?format=xml'))
feeds.append((u'Energy', u'http://feeds.feedburner.com/StrategyBusiness-Energy?format=xml'))
feeds.append((u'Health Care', u'http://feeds.feedburner.com/StrategyBusiness-HealthCare?format=xml'))
feeds.append((u'Technology', u'http://feeds.feedburner.com/StrategyBusiness-Technology?format=xml'))
feeds.append((u'Thought Leaders', u'http://feeds.feedburner.com/StrategyBusiness-ThoughtLeaders?format=xml'))
feeds.append((u'Business Literature', u'http://feeds.feedburner.com/StrategyBusiness-BusinessLiterature?format=xml'))
feeds.append((u'Recent Research', u'http://feeds.feedburner.com/StrategyBusiness-RecentResearch?format=xml'))
keep_only_tags = []
keep_only_tags.append(dict(name = 'div', attrs = {'id': 'sb-column2'}))
remove_tags = []
remove_tags.append(dict(name = 'img', attrs = {'class': 'content1'}))
remove_tags.append(dict(name = 'img', attrs = {'src': '/media/image/end_of_story.gif'}))
remove_tags.append(dict(name = 'div', attrs = {'class': 'sb-adarea468'}))
remove_tags.append(dict(name = 'div', attrs = {'id': 'sb-paging'}))
remove_tags.append(dict(name = 'div', attrs = {'id': 'textsize'}))
def print_version(self, url):
return url + '?pg=all'

View File

@ -0,0 +1,96 @@
from calibre.web.feeds.news import BasicNewsRecipe
from calibre.ebooks.BeautifulSoup import BeautifulSoup
class WatchingAmericaRecipe(BasicNewsRecipe):
__license__ = 'GPL v3'
__author__ = 'kwetal'
language = 'en'
version = 1
title = u'Watching America'
publisher = u'watchingamerica.com'
category = u'News'
description = u'Global opinion about the United States'
oldest_article = 7
max_articles_per_feed = 100
use_embedded_content = False
no_stylesheets = True
remove_javascript = True
remove_attributes = ['style']
extra_css = '''
body{font-family:verdana,arial,helvetica,geneva,sans-serif ;}
.main_content em {font-size: x-small; font-style: italic; color: #696969;}
.main_content span strong {font-size: x-large; font-weight: bold;}
.insideitro {font-size: xx-small; font-style: italic; color: #666666;}
span {padding: 0em; margin 0em;}
'''
INDEX = u'http://watchingamerica.com/News/'
def parse_index(self):
answer = []
soup = self.index_to_soup(self.INDEX)
articles = []
feature = soup.find('div', attrs = {'id': 'headzone'})
if feature:
link = feature.find('a', attrs = {'class': 'feature'})
url = link.get('href', None)
title = self.tag_to_string(link)
description = self.tag_to_string(feature.find('h1', attrs = {'class': 'pull'}))
article = {'title': title, 'date': u'', 'url': url, 'description': description}
articles.append(article)
answer.append(('Feature', articles))
feed_titles = ['Translations from the West', 'Translations from the East']
for i in range(1, 3):
articles = []
div = soup.find('div', attrs = {'class': 'newscol' + str(i)})
if div:
for link in div.findAll('a', attrs = {'class': 'headline'}):
url = link.get('href', None)
title = self.tag_to_string(link)
description = None
h3 = link.findNextSibling('h3')
if h3:
description = self.tag_to_string(h3)
article = {'title': title, 'date': u'', 'url': url, 'description': description}
articles.append(article)
answer.append((feed_titles[i - 1], articles))
return answer
def preprocess_html(self, soup):
freshSoup = self.get_fresh_soup(soup)
article = soup.find('p', attrs = {'class': 'MsoNormal'}).parent
if article:
article.name = 'div'
del article['width']
article['class'] = 'main_content'
org = article.find('a', attrs = {'href': '?SHOW_ORIGINAL_TEXT'})
if org:
org.parent.extract()
intro = article.find('span', attrs = {'class': 'insideitro'})
if intro:
for el in intro.findAll(['strong', 'em', 'br']):
if el.name == 'br':
el.extract()
else:
el.name = 'div'
freshSoup.body.append(article)
return freshSoup
def get_fresh_soup(self, oldSoup):
freshSoup = BeautifulSoup('<html><head><title></title></head><body></body></html>')
if oldSoup.head.title:
freshSoup.head.title.append(self.tag_to_string(oldSoup.head.title))
return freshSoup

View File

@ -1,138 +1,17 @@
#include "util.h"
#include <stdlib.h>
#include <strings.h>
#include <CoreFoundation/CoreFoundation.h>
#include <mach-o/dyld.h>
#include <Python.h>
static const char *ERR_UNKNOWNPYTHONEXCEPTION = "An uncaught exception was raised during execution of the main script, but its class or name could not be determined";
static int
report_error(const char *msg) {
fprintf(stderr, msg);
fprintf(stderr, "\n");
fflush(stderr);
return -1;
}
// These variable must be filled in before compiling
// These variables must be filled in before compiling
static const char *ENV_VARS[] = { /*ENV_VARS*/ NULL };
static const char *ENV_VAR_VALS[] = { /*ENV_VAR_VALS*/ NULL};
static char PROGRAM[] = "**PROGRAM**";
static const char MODULE[] = "**MODULE**";
static const char FUNCTION[] = "**FUNCTION**";
static const char PYVER[] = "**PYVER**";
#define EXE "@executable_path/.."
static void
set_env_vars(const char* exe_path, const char* rpath) {
int i = 0;
char buf[3*PATH_MAX];
const char *env_var, *val;
while(1) {
env_var = ENV_VARS[i];
if (env_var == NULL) break;
val = ENV_VAR_VALS[i++];
if (strstr(val, EXE) == val && strlen(val) >= strlen(EXE)+1) {
strncpy(buf, exe_path, 3*PATH_MAX-150);
strncpy(buf+strlen(exe_path), val+strlen(EXE), 150);
setenv(env_var, buf, 1);
} else
setenv(env_var, val, 1);
}
setenv("CALIBRE_LAUNCH_MODULE", MODULE, 1);
setenv("RESOURCEPATH", rpath, 1);
return;
}
int
main(int argc, char * const *argv, char * const *envp) {
char *pathPtr = NULL;
char buf[3*PATH_MAX];
int ret, i;
uint32_t buf_size = PATH_MAX+1;
char *ebuf = calloc(buf_size, sizeof(char));
ret = _NSGetExecutablePath(ebuf, &buf_size);
if (ret == -1) {
free(ebuf);
ebuf = calloc(buf_size, sizeof(char));
if (_NSGetExecutablePath(ebuf, &buf_size) != 0)
return report_error("Failed to find real path of executable.");
}
pathPtr = realpath(ebuf, buf);
if (pathPtr == NULL) {
return report_error(strerror(errno));
}
char *t;
for (i = 0; i < 3; i++) {
t = rindex(pathPtr, '/');
if (t == NULL) return report_error("Failed to determine bundle path.");
*t = '\0';
main(int argc, const char **argv, const char **envp) {
return run(ENV_VARS, ENV_VAR_VALS, PROGRAM, MODULE, FUNCTION, PYVER, argc, argv, envp);
}
char rpath[PATH_MAX+1];
strncpy(rpath, pathPtr, strlen(pathPtr));
strncat(rpath, "/Contents/Resources", 50);
char exe_path[PATH_MAX+1];
strncpy(exe_path, pathPtr, strlen(pathPtr));
strncat(exe_path, "/Contents", 50);
set_env_vars(exe_path, rpath);
char main_script[PATH_MAX+1];
strncpy(main_script, rpath, strlen(rpath));
strncat(main_script, "/launcher.py", 20);
Py_SetProgramName(PROGRAM);
Py_Initialize();
char **argv_new = calloc(argc+1, sizeof(char *));
argv_new[argc] = NULL;
argv_new[0] = main_script;
memcpy(&argv_new[1], &argv[1], (argc - 1) * sizeof(char *));
PySys_SetArgv(argc, argv_new);
FILE *main_script_file = fopen(main_script, "r");
int rval = PyRun_SimpleFileEx(main_script_file, main_script, 1);
while (rval != 0) {
PyObject *exc, *exceptionClassName, *v, *exceptionName;
exc = PySys_GetObject("last_type");
if ( !exc ) {
rval = report_error(ERR_UNKNOWNPYTHONEXCEPTION);
break;
}
exceptionClassName = PyObject_GetAttrString(exc, "__name__");
if (!exceptionClassName) {
rval = report_error(ERR_UNKNOWNPYTHONEXCEPTION);
break;
}
v = PySys_GetObject("last_value");
exceptionName = (v ? PyObject_Str(v) : NULL);
char *class = PyString_AsString(exceptionClassName);
char *exception = "";
Py_DecRef(exceptionClassName);
if (exceptionName) {
exception = PyString_AsString(exceptionName);
Py_DecRef(exceptionName);
}
char msg[2000];
strncpy(msg, "An unexpected error occurred: ", 100);
strncpy(msg, class, 500);
strncpy(msg, " : ", 3);
strncpy(msg, exception, 500);
rval = report_error(msg);
break;
}
Py_Finalize();
return rval;
}

View File

@ -1,58 +0,0 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
__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
base = os.environ['RESOURCEPATH']
sys.frozen = 'macosx_app'
sys.frameworks_dir = os.path.join(os.path.dirname(base), 'Frameworks')
sys.new_app_bundle = True
sys.site_packages = os.path.join(base, 'Python', 'site-packages')
sys.binaries_path = os.path.join(os.path.dirname(base), 'MacOS')
sys.console_binaries_path = os.path.join(os.path.dirname(base),
'console.app', 'Contents', 'MacOS')
exe = os.environ.get('CALIBRE_LAUNCH_MODULE', 'calibre.gui2.main')
exe = os.path.join(base, 'Python', 'site-packages', *exe.split('.'))
exe += '.py'
sys.argv[0] = __file__ = exe
for arg in list(sys.argv[1:]):
if arg.startswith('-psn'):
sys.argv.remove(arg)
execfile(exe, globals(), globals())
_run()

View File

@ -10,33 +10,58 @@ 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
#TODO: WMF support in ImageMagick
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']
from setup import __version__ as VERSION, __appname__ as APPNAME, basenames, \
modules as main_modules, Command, SRC, functions as main_functions
LICENSE = open('LICENSE', 'rb').read()
ENV = dict(
PYTHONPATH='@executable_path/../Resources/Python/site-packages',
PYTHONHOME='@executable_path/../Resources/Python',
FC_CONFIG_DIR='@executable_path/../Resources/fonts',
MAGICK_HOME='@executable_path/../Frameworks/ImageMagick',
QT_PLUGIN_PATH='@executable_path/../MacOS',
PYTHONDONTWRITEBYTECODE='1',
PYTHONIOENCODING='utf-8:replace',
PYTHONOPTIMIZE='2',
PYTHONIOENCODING='UTF-8',
)
SW = os.environ.get('SW', '/sw')
def compile_launchers(contents_dir, xprograms):
info = warn = None
class OSX32_Freeze(Command):
description = 'Freeze OSX calibre installation'
def add_options(self, parser):
parser.add_option('--test-launchers', default=False,
action='store_true',
help='Only build launchers')
def run(self, opts):
global info, warn
info, warn = self.info, self.warn
main(opts.test_launchers)
def compile_launcher_lib(contents_dir, gcc, base):
info('\tCompiling calibre_launcher.dylib')
fd = join(contents_dir, 'Frameworks')
dest = join(fd, 'calibre-launcher.dylib')
src = join(base, 'util.c')
cmd = [gcc] + '-Wall -arch i386 -arch ppc -dynamiclib -std=gnu99'.split() + [src] + \
['-I'+base] + \
['-I%s/python/Python.framework/Headers'%SW] + \
'-current_version 1.0 -compatibility_version 1.0'.split() + \
'-fvisibility=hidden -o'.split() + [dest, '-F%s/python'%SW] + \
['-install_name',
'@executable_path/../Frameworks/'+os.path.basename(dest)] + \
['-framework', 'Python', '-framework', 'CoreFoundation', '-headerpad_max_install_names']
info('\t'+' '.join(cmd))
sys.stdout.flush()
subprocess.check_call(cmd)
return dest
def compile_launchers(contents_dir, xprograms, pyver):
gcc = os.environ.get('CC', 'gcc')
base = os.path.dirname(__file__)
lib = compile_launcher_lib(contents_dir, gcc, base)
src = open(join(base, 'launcher.c'), 'rb').read()
env, env_vals = [], []
for key, val in ENV.items():
@ -46,22 +71,23 @@ def compile_launchers(contents_dir, xprograms):
env_vals = ', '.join(env_vals)+', '
src = src.replace('/*ENV_VARS*/', env)
src = src.replace('/*ENV_VAR_VALS*/', env_vals)
programs = []
for program, module in xprograms.items():
print '\tCompiling', program
programs = [lib]
for program, x in xprograms.items():
module, func = x
info('\tCompiling', program)
out = join(contents_dir, 'MacOS', program)
programs.append(out)
psrc = src.replace('**PROGRAM**', program)
psrc = psrc.replace('**MODULE**', module)
psrc = psrc.replace('**FUNCTION**', func)
psrc = psrc.replace('**PYVER**', pyver)
fsrc = '/tmp/%s.c'%program
with open(fsrc, 'wb') as f:
f.write(psrc)
cmd = [gcc, '-Wall', '-arch', 'x86_64',
'-I%s/python/Python.framework/Headers'%SW,
fsrc, '-o', out, '-F%s/python'%SW,
'-framework', 'Python', '-framework', 'CoreFoundation',
cmd = [gcc, '-Wall', '-arch', 'ppc', '-arch', 'i386',
'-I'+base, fsrc, lib, '-o', out,
'-headerpad_max_install_names']
print ' '.join(cmd)
info('\t'+' '.join(cmd))
sys.stdout.flush()
subprocess.check_call(cmd)
return programs
@ -81,7 +107,7 @@ def flipwritable(fn, mode=None):
def thin(path):
try:
subprocess.check_call(['lipo', path, '-verify_arch', 'ppc64'])
print '\tThinning', path
info('\tThinning', path)
except:
return
else:
@ -92,7 +118,7 @@ def strip_files(files, argv_max=(256 * 1024)):
"""
Strip a list of files
"""
tostrip = [(fn, flipwritable(fn)) for fn in files]
tostrip = [(fn, flipwritable(fn)) for fn in files if os.path.exists(fn)]
while tostrip:
cmd = list(STRIPCMD)
flips = []
@ -125,23 +151,27 @@ class Py2App(object):
FID = '@executable_path/../Frameworks'
def __init__(self, build_dir):
def __init__(self, build_dir, test_launchers=False):
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.version_info = '.'.join(map(str, sys.version_info[:2]))
self.site_packages = join(self.resources_dir, 'Python', 'site-packages')
self.to_strip = []
self.warnings = []
self.run(test_launchers)
def warn(self, *args):
self.warnings.append(args)
prefix = '' if args and args[0].startswith('WARNING:') else 'WARNING: '
sys.stdout.write(prefix+' '.join(args)+'\n')
sys.stdout.flush()
warn(*args)
def run(self):
def run(self, test_launchers):
ret = 0
if not test_launchers:
if os.path.exists(self.build_dir):
shutil.rmtree(self.build_dir)
os.makedirs(self.build_dir)
self.create_skeleton()
self.create_plist()
@ -158,28 +188,29 @@ class Py2App(object):
self.add_site_packages()
self.add_stdlib()
self.add_resources()
self.compile_py_modules()
self.create_console_app()
self.copy_launcher_and_site()
self.copy_site()
self.create_exe()
self.thin_to_x86_64()
if not test_launchers:
#self.thin_to_x86_64()
self.strip_files()
ret = self.makedmg(self.build_dir, APPNAME+'-'+VERSION+'-x86_64')
sys.stdout.flush()
sys.stderr.flush()
ret = self.makedmg(self.build_dir, APPNAME+'-'+VERSION)
print '\nThere were', len(self.warnings), 'warnings'
for w in list(self.warnings):
print
self.warn(*w)
return ret
@flush
def add_resources(self):
shutil.copytree('resources', os.path.join(self.resources_dir,
'resources'))
@flush
def thin_to_x86_64(self):
print '\nThinning to x86_64'
info('\nThinning to x86_64')
for y in (self.frameworks_dir, join(self.resources_dir, 'Python')):
for x in os.walk(y):
for f in x[-1]:
@ -192,24 +223,22 @@ class Py2App(object):
@flush
def strip_files(self):
print '\nStripping files...'
info('\nStripping files...')
strip_files(self.to_strip)
@flush
def create_exe(self):
print '\nCreating launchers'
info('\nCreating launchers')
programs = {}
for program, module in zip(basenames['console'],
main_modules['console'])+zip(basenames['gui'],
main_modules['gui']):
programs[program] = module
programs = compile_launchers(self.contents_dir, programs)
progs = []
for x in ('console', 'gui'):
progs += list(zip(basenames[x], main_modules[x], main_functions[x]))
for program, module, func in progs:
programs[program] = (module, func)
programs = compile_launchers(self.contents_dir, programs,
self.version_info)
for out in programs:
self.fix_dependencies_in_lib(out)
for module in main_modules['console'] + main_modules['gui']:
base = join(*module.split('.'))+'.py'
shutil.copy2(join('src', base),
join(self.resources_dir, 'Python', 'site-packages', base))
@flush
def set_id(self, path_to_lib, new_id):
@ -233,20 +262,20 @@ class Py2App(object):
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/'):
SW+'/python/', SW+'/freetype/lib/'):
if x.startswith(y):
yield x, x[len(y):]
break
@flush
def change_dep(self, old_dep, new_dep, path_to_lib):
print '\tResolving dependency %s to'%old_dep, new_dep
info('\tResolving dependency %s to'%old_dep, new_dep)
subprocess.check_call(['install_name_tool', '-change', old_dep, new_dep,
path_to_lib])
@flush
def fix_dependencies_in_lib(self, path_to_lib):
print '\nFixing dependencies in', path_to_lib
info('\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):
@ -259,7 +288,7 @@ class Py2App(object):
@flush
def add_python_framework(self):
print '\nAdding Python framework'
info('\nAdding Python framework')
src = join(SW, 'python', 'Python.framework')
x = join(self.frameworks_dir, 'Python.framework')
curr = os.path.realpath(join(src, 'Versions', 'Current'))
@ -274,7 +303,7 @@ class Py2App(object):
@flush
def add_qt_frameworks(self):
for f in ('QtCore', 'QtGui', 'QtXml', 'QtNetwork', 'QtSvg', 'QtWebkit',
'phonon'):
'QtXmlPatterns', '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)))
@ -353,30 +382,30 @@ class Py2App(object):
@flush
def add_podofo(self):
print '\nAdding PoDoFo'
info('\nAdding PoDoFo')
pdf = join(SW, 'lib', 'libpodofo.0.6.99.dylib')
self.install_dylib(pdf)
@flush
def add_poppler(self):
print '\nAdding poppler'
for x in ('libpoppler.4.dylib', 'libpoppler-qt4.3.dylib'):
info('\nAdding poppler')
for x in ('libpoppler.5.dylib', 'libpoppler-qt4.3.dylib'):
self.install_dylib(os.path.join(SW, 'lib', x))
self.install_dylib(os.path.join(SW, 'bin', 'pdftohtml'), False)
@flush
def add_libjpeg(self):
print '\nAdding libjpeg'
info('\nAdding libjpeg')
self.install_dylib(os.path.join(SW, 'lib', 'libjpeg.7.dylib'))
@flush
def add_libpng(self):
print '\nAdding libpng'
info('\nAdding libpng')
self.install_dylib(os.path.join(SW, 'lib', 'libpng12.0.dylib'))
@flush
def add_fontconfig(self):
print '\nAdding fontconfig'
info('\nAdding fontconfig')
for x in ('fontconfig.1', 'freetype.6', 'expat.1'):
src = os.path.join(SW, 'lib', 'lib'+x+'.dylib')
self.install_dylib(src)
@ -400,7 +429,7 @@ class Py2App(object):
@flush
def add_imagemagick(self):
print '\nAdding ImageMagick'
info('\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]
@ -419,16 +448,15 @@ class Py2App(object):
@flush
def add_misc_libraries(self):
for x in ('usb', 'unrar', 'readline.6.0'):
print '\nAdding', x
for x in ('usb', 'unrar', 'readline.6.0', 'wmflite-0.2.7'):
info('\nAdding', x)
x = 'lib%s.dylib'%x
shutil.copy2(join(SW, 'lib', x), self.frameworks_dir)
self.set_id(join(self.frameworks_dir, x), self.FID+'/'+x)
@flush
def add_site_packages(self):
print '\nAdding site-packages'
self.site_packages = join(self.resources_dir, 'Python', 'site-packages')
info('\nAdding site-packages')
os.makedirs(self.site_packages)
paths = reversed(map(abspath, [x for x in sys.path if x.startswith('/')]))
upaths = []
@ -455,12 +483,12 @@ class Py2App(object):
finally:
if tdir is not None:
shutil.rmtree(tdir)
shutil.rmtree(os.path.join(self.site_packages, 'calibre', 'plugins'))
self.remove_bytecode(join(self.resources_dir, 'Python', 'site-packages'))
@flush
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)
@ -507,7 +535,7 @@ class Py2App(object):
@flush
def add_stdlib(self):
print '\nAdding python stdlib'
info('\nAdding python stdlib')
src = join(SW, 'python/Python.framework/Versions/Current/lib/python')
src += self.version_info
dest = join(self.resources_dir, 'Python', 'lib', 'python')
@ -537,7 +565,7 @@ class Py2App(object):
@flush
def compile_py_modules(self):
print '\nCompiling Python modules'
info( '\nCompiling Python modules')
base = join(self.resources_dir, 'Python')
for x in os.walk(base):
root = x[0]
@ -553,7 +581,7 @@ class Py2App(object):
@flush
def create_console_app(self):
print '\nCreating console.app'
info( '\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):
@ -568,9 +596,8 @@ class Py2App(object):
join(cc_dir, x))
@flush
def copy_launcher_and_site(self):
def copy_site(self):
base = os.path.dirname(__file__)
shutil.copy2(join(base, 'launcher.py'), self.resources_dir)
shutil.copy2(join(base, 'site.py'), join(self.resources_dir, 'Python',
'lib', 'python'+self.version_info))
@ -581,7 +608,7 @@ class Py2App(object):
internet_enable=True,
format='UDBZ'):
''' Copy a directory d into a dmg named volname '''
print '\nCreating dmg'
info('\nCreating dmg')
sys.stdout.flush()
if not os.path.exists(destdir):
os.makedirs(destdir)
@ -593,7 +620,7 @@ class Py2App(object):
if internet_enable:
subprocess.check_call(['/usr/bin/hdiutil', 'internet-enable', '-yes', dmg])
size = os.stat(dmg).st_size/(1024*1024.)
print '\nInstaller size: %.2fMB\n'%size
info('\nInstaller size: %.2fMB\n'%size)
return dmg
def test_exe():
@ -603,15 +630,11 @@ def test_exe():
return 0
def main():
def main(test=False):
if 'test_exe' in sys.argv:
return test_exe()
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()
build_dir = abspath(join(os.path.dirname(SRC), 'build', APPNAME+'.app'))
Py2App(build_dir, test_launchers=test)
return 0

View File

@ -11,11 +11,15 @@ def makepath(*paths):
dir = os.path.abspath(os.path.join(*paths))
return dir, os.path.normcase(dir)
def abs__file__():
"""Set all module __file__ attribute to an absolute path"""
for m in sys.modules.values():
f = getattr(m, '__file__', None)
if isinstance(f, basestring) and os.path.exists(f):
if hasattr(m, '__loader__'):
continue # don't mess with a PEP 302-supplied __file__
try:
m.__file__ = os.path.abspath(m.__file__)
del m
except AttributeError:
continue
# This ensures that the initial path provided by the interpreter contains
# only absolute pathnames, even if we're running from the build directory.
@ -104,3 +108,42 @@ sys.setdefaultencoding('utf-8')
#
if hasattr(sys, "setdefaultencoding"):
del sys.setdefaultencoding
def run_entry_point():
bname, mod, func = sys.calibre_basename, sys.calibre_module, sys.calibre_function
sys.argv[0] = bname
pmod = __import__(mod, fromlist=[1], level=0)
return getattr(pmod, func)()
def add_calibre_vars(base):
sys.frameworks_dir = os.path.join(os.path.dirname(base), 'Frameworks')
sys.resources_location = os.path.abspath(os.path.join(base, 'resources'))
sys.extensions_location = os.path.join(sys.frameworks_dir, 'plugins')
sys.binaries_path = os.path.join(os.path.dirname(base), 'MacOS')
sys.console_binaries_path = os.path.join(os.path.dirname(base),
'console.app', 'Contents', 'MacOS')
dv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
if dv and os.path.exists(dv):
sys.path.insert(0, os.path.abspath(dv))
def main():
global __file__
base = sys.resourcepath
sys.frozen = 'macosx_app'
sys.new_app_bundle = True
abs__file__()
add_calibre_vars(base)
addsitedir(sys.site_packages)
for arg in list(sys.argv[1:]):
if arg.startswith('-psn'):
sys.argv.remove(arg)
return run_entry_point()

View File

@ -0,0 +1,220 @@
#include "util.h"
#include <stdlib.h>
#include <strings.h>
#include <CoreFoundation/CoreFoundation.h>
#include <mach-o/dyld.h>
#include <Python.h>
#define EXPORT __attribute__((visibility("default")))
static const char *ERR_OOM = "Out of memory";
static int
report_error(const char *msg) {
fprintf(stderr, msg);
fprintf(stderr, "\n");
fflush(stderr);
return -1;
}
static int
report_code(const char *preamble, const char* msg, int code) {
fprintf(stderr, "%s: %s\n", preamble, msg);
fflush(stderr);
return code;
}
#define EXE "@executable_path/.."
static void
set_env_vars(const char **ENV_VARS, const char **ENV_VAR_VALS, const char* exe_path) {
int i = 0;
char buf[3*PATH_MAX];
const char *env_var, *val;
while(1) {
env_var = ENV_VARS[i];
if (env_var == NULL) break;
val = ENV_VAR_VALS[i++];
if (strstr(val, EXE) == val && strlen(val) >= strlen(EXE)+1) {
strncpy(buf, exe_path, 3*PATH_MAX-150);
strncpy(buf+strlen(exe_path), val+strlen(EXE), 150);
setenv(env_var, buf, 1);
} else
setenv(env_var, val, 1);
}
return;
}
void initialize_interpreter(const char **ENV_VARS, const char **ENV_VAR_VALS,
char *PROGRAM, const char *MODULE, const char *FUNCTION, const char *PYVER,
const char* exe_path, const char *rpath, int argc, const char **argv) {
PyObject *pargv, *v;
int i;
Py_OptimizeFlag = 2;
Py_NoSiteFlag = 1;
Py_DontWriteBytecodeFlag = 1;
Py_IgnoreEnvironmentFlag = 1;
Py_NoUserSiteDirectory = 1;
//Py_VerboseFlag = 1;
//Py_DebugFlag = 1;
Py_SetProgramName(PROGRAM);
char pyhome[1000];
snprintf(pyhome, 1000, "%s/Python", rpath);
Py_SetPythonHome(pyhome);
set_env_vars(ENV_VARS, ENV_VAR_VALS, exe_path);
//printf("Path before Py_Initialize(): %s\r\n\n", Py_GetPath());
Py_Initialize();
char *dummy_argv[1] = {""};
PySys_SetArgv(1, dummy_argv);
//printf("Path after Py_Initialize(): %s\r\n\n", Py_GetPath());
char path[3000];
snprintf(path, 3000, "%s/lib/python%s:%s/lib/python%s/lib-dynload:%s/site-packages", pyhome, PYVER, pyhome, PYVER, pyhome);
PySys_SetPath(path);
//printf("Path set by me: %s\r\n\n", path);
PySys_SetObject("calibre_basename", PyBytes_FromString(PROGRAM));
PySys_SetObject("calibre_module", PyBytes_FromString(MODULE));
PySys_SetObject("calibre_function", PyBytes_FromString(FUNCTION));
PySys_SetObject("resourcepath", PyBytes_FromString(rpath));
snprintf(path, 3000, "%s/site-packages", pyhome);
PySys_SetObject("site_packages", PyBytes_FromString(pyhome));
pargv = PyList_New(argc);
if (pargv == NULL) exit(report_error(ERR_OOM));
for (i = 0; i < argc; i++) {
v = PyBytes_FromString(argv[i]);
if (v == NULL) exit(report_error(ERR_OOM));
PyList_SetItem(pargv, i, v);
}
PySys_SetObject("argv", pargv);
}
int pyobject_to_int(PyObject *res) {
int ret; PyObject *tmp;
tmp = PyNumber_Int(res);
if (tmp == NULL) ret = (PyObject_IsTrue(res)) ? 1 : 0;
else ret = (int)PyInt_AS_LONG(tmp);
return ret;
}
int handle_sysexit(PyObject *e) {
PyObject *code;
code = PyObject_GetAttrString(e, "code");
if (!code) return 0;
return pyobject_to_int(code);
}
int calibre_show_python_error(const char *preamble, int code) {
PyObject *exc, *val, *tb, *str;
int ret, issysexit = 0; char *i;
if (!PyErr_Occurred()) return code;
issysexit = PyErr_ExceptionMatches(PyExc_SystemExit);
PyErr_Fetch(&exc, &val, &tb);
if (exc != NULL) {
PyErr_NormalizeException(&exc, &val, &tb);
if (issysexit) {
return (val) ? handle_sysexit(val) : 0;
}
if (val != NULL) {
str = PyObject_Unicode(val);
if (str == NULL) {
PyErr_Clear();
str = PyObject_Str(val);
}
i = PyString_AsString(str);
ret = report_code(preamble, (i==NULL)?ERR_OOM:i, code);
if (tb != NULL) {
PyErr_Restore(exc, val, tb);
PyErr_Print();
}
return ret;
}
}
return report_code(preamble, "", code);
}
EXPORT
int
run(const char **ENV_VARS, const char **ENV_VAR_VALS, char *PROGRAM,
const char *MODULE, const char *FUNCTION, const char *PYVER,
int argc, const char **argv, const char **envp) {
char *pathPtr = NULL;
char buf[3*PATH_MAX];
int ret = 0, i;
PyObject *site, *mainf, *res;
uint32_t buf_size = PATH_MAX+1;
char *ebuf = calloc(buf_size, sizeof(char));
ret = _NSGetExecutablePath(ebuf, &buf_size);
if (ret == -1) {
free(ebuf);
ebuf = calloc(buf_size, sizeof(char));
if (_NSGetExecutablePath(ebuf, &buf_size) != 0)
return report_error("Failed to find real path of executable.");
}
pathPtr = realpath(ebuf, buf);
if (pathPtr == NULL) {
return report_error(strerror(errno));
}
char *t;
for (i = 0; i < 3; i++) {
t = rindex(pathPtr, '/');
if (t == NULL) return report_error("Failed to determine bundle path.");
*t = '\0';
}
char rpath[PATH_MAX+1], exe_path[PATH_MAX+1];
snprintf(exe_path, PATH_MAX+1, "%s/Contents", pathPtr);
snprintf(rpath, PATH_MAX+1, "%s/Resources", exe_path);
initialize_interpreter(ENV_VARS, ENV_VAR_VALS, PROGRAM, MODULE, FUNCTION, PYVER,
exe_path, rpath, argc, argv);
site = PyImport_ImportModule("site");
if (site == NULL)
ret = calibre_show_python_error("Failed to import site module", -1);
else {
Py_XINCREF(site);
mainf = PyObject_GetAttrString(site, "main");
if (mainf == NULL || !PyCallable_Check(mainf))
ret = calibre_show_python_error("site module has no main function", -1);
else {
Py_XINCREF(mainf);
res = PyObject_CallObject(mainf, NULL);
if (res == NULL)
ret = calibre_show_python_error("Python function terminated unexpectedly", -1);
else {
}
}
}
PyErr_Clear();
Py_Finalize();
//printf("11111 Returning: %d\r\n", ret);
return ret;
}

View File

@ -0,0 +1,5 @@
#pragma once
int run(const char **ENV_VARS, const char **ENV_VAR_VALS, char *PROGRAM,
const char *MODULE, const char *FUNCTION, const char *PYVER,
int argc, const char **argv, const char **envp);

View File

@ -11,8 +11,6 @@ from math import floor
warnings.simplefilter('ignore', DeprecationWarning)
from PyQt4.QtCore import QUrl
from PyQt4.QtGui import QDesktopServices
from calibre.startup import plugins, winutil, winutilerror
from calibre.constants import iswindows, isosx, islinux, isfrozen, \
terminal_controller, preferred_encoding, \
@ -140,9 +138,6 @@ def prints(*args, **kwargs):
class CommandLineError(Exception):
pass
def setup_cli_handlers(logger, level):
if os.environ.get('CALIBRE_WORKER', None) is not None and logger.handlers:
return
@ -347,6 +342,8 @@ def detect_ncpus():
def launch(path_or_url):
from PyQt4.QtCore import QUrl
from PyQt4.QtGui import QDesktopServices
if os.path.exists(path_or_url):
path_or_url = 'file:'+path_or_url
QDesktopServices.openUrl(QUrl(path_or_url))
@ -456,6 +453,60 @@ def ipython(user_ns=None):
from calibre.utils.config import config_dir
ipydir = os.path.join(config_dir, ('_' if iswindows else '.')+'ipython')
os.environ['IPYTHONDIR'] = ipydir
if not os.path.exists(ipydir):
os.makedirs(ipydir)
rc = os.path.join(ipydir, 'ipythonrc')
if not os.path.exists(rc):
open(rc, 'wb').write(' ')
UC = '''
import IPython.ipapi
ip = IPython.ipapi.get()
# You probably want to uncomment this if you did %upgrade -nolegacy
import ipy_defaults
import os, re, sys
def main():
# Handy tab-completers for %cd, %run, import etc.
# Try commenting this out if you have completion problems/slowness
import ipy_stock_completers
# uncomment if you want to get ipython -p sh behaviour
# without having to use command line switches
import ipy_profile_sh
# Configure your favourite editor?
# Good idea e.g. for %edit os.path.isfile
import ipy_editors
# Choose one of these:
#ipy_editors.scite()
#ipy_editors.scite('c:/opt/scite/scite.exe')
#ipy_editors.komodo()
#ipy_editors.idle()
# ... or many others, try 'ipy_editors??' after import to see them
# Or roll your own:
#ipy_editors.install_editor("c:/opt/jed +$line $file")
ipy_editors.kate()
o = ip.options
# An example on how to set options
#o.autocall = 1
o.system_verbose = 0
o.confirm_exit = 0
main()
'''
uc = os.path.join(ipydir, 'ipy_user_conf.py')
if not os.path.exists(uc):
open(uc, 'wb').write(UC)
from IPython.Shell import IPShellEmbed
ipshell = IPShellEmbed(user_ns=user_ns)
ipshell()

View File

@ -417,6 +417,7 @@ from calibre.devices.nokia.driver import N770, N810
from calibre.devices.eslick.driver import ESLICK
from calibre.devices.nuut2.driver import NUUT2
from calibre.devices.iriver.driver import IRIVER_STORY
from calibre.devices.boox.driver import BOOX
from calibre.ebooks.metadata.fetch import GoogleBooks, ISBNDB, Amazon
plugins = [HTML2ZIP, PML2PMLZ, GoogleBooks, ISBNDB, Amazon]
@ -481,6 +482,7 @@ plugins += [
ITALICA,
SHINEBOOK,
ECLICTO,
BOOX,
EB600,
]
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \

View File

View File

@ -0,0 +1,87 @@
__license__ = 'GPL v3'
__copyright__ = '2009, Jesus Manuel Marinho Valcarce <jjjesss at gmail.com>'
__docformat__ = 'restructuredtext en'
'''
Device driver for BOOX
'''
import re
from calibre.devices.usbms.driver import USBMS
class BOOX(USBMS):
name = 'BOOX driver'
gui_name = 'BOOX'
description = _('Communicate with the BOOX eBook reader.')
author = 'Jesus Manuel Marinho Valcarce'
supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats
FORMATS = ['ebub', 'pdf', 'html', 'txt', 'rtf', 'mobi', 'prc', 'chm']
VENDOR_ID = [0x0525]
PRODUCT_ID = [0xa4a5]
BCD = [0x322]
VENDOR_NAME = 'Linux 2.6.26-466-ga04670e with fsl-usb2-udc'
WINDOWS_MAIN_MEM = 'FILE-STOR_GADGET'
WINDOWS_CARD_A_MEM = 'FILE-STOR_GADGET'
OSX_MAIN_MEM = 'Linux File-Stor Gadget Media'
OSX_CARD_A_MEM = 'Linux File-Stor Gadget Media'
MAIN_MEMORY_VOLUME_LABEL = 'BOOX Internal Memory'
STORAGE_CARD_VOLUME_LABEL = 'BOOX Storage Card'
EBOOK_DIR_MAIN = 'MyBooks'
EBOOK_DIR_CARD_A = 'MyBooks'
SUPPORTS_SUB_DIRS = True
def windows_sort_drives(self, drives):
main = drives.get('main', None)
card = drives.get('carda', None)
if card and main and card > main:
drives['main'] = card
drives['carda'] = main
if card and not main:
drives['main'] = card
drives['carda'] = None
return drives
def osx_sort_names(self, names):
main = names.get('main', None)
card = names.get('carda', None)
try:
main_num = int(re.findall('\d+', main)[0]) if main else None
except:
main_num = None
try:
card_num = int(re.findall('\d+', card)[0]) if card else None
except:
card_num = None
if card_num is not None and main_num is not None and card_num > main_num:
names['main'] = card
names['carda'] = main
if card and not main:
names['main'] = card
names['carda'] = None
return names
def linux_swap_drives(self, drives):
if len(drives) < 2: return drives
drives = list(drives)
t = drives[0]
drives[0] = drives[1]
drives[1] = t
return tuple(drives)

View File

@ -23,6 +23,7 @@ class NOOK(USBMS):
gui_name = _('The Nook')
description = _('Communicate with the Nook eBook reader.')
author = 'John Schember'
icon = I('devices/nook.jpg')
supported_platforms = ['windows', 'linux', 'osx']
# Ordered list of supported formats

View File

@ -8,6 +8,7 @@ Based on ideas from comiclrf created by FangornUK.
'''
import os, shutil, traceback, textwrap, time
from ctypes import byref
from Queue import Empty
from calibre.customize.conversion import InputFormatPlugin, OptionRecommendation
@ -75,7 +76,10 @@ class PageProcessor(list):
if img < 0:
raise RuntimeError('Cannot create wand.')
if not pw.MagickReadImage(img, self.path_to_page):
raise IOError('Failed to read image from: %'%self.path_to_page)
severity = pw.ExceptionType(0)
msg = pw.MagickGetException(img, byref(severity))
raise IOError('Failed to read image from: %s: %s'
%(self.path_to_page, msg))
width = pw.MagickGetImageWidth(img)
height = pw.MagickGetImageHeight(img)
if self.num == 0: # First image so create a thumbnail from it
@ -363,14 +367,14 @@ class ComicInput(InputFormatPlugin):
else:
new_pages, failures = process_pages(new_pages, self.opts,
self.report_progress, tdir2)
if not new_pages:
raise ValueError('Could not find any valid pages in comic: %s'
% comic)
if failures:
self.log.warning('Could not process the following pages '
'(run with --verbose to see why):')
for f in failures:
self.log.warning('\t', f)
if not new_pages:
raise ValueError('Could not find any valid pages in comic: %s'
% comic)
thumbnail = os.path.join(tdir2,
'thumbnail.'+self.opts.output_format.lower())
if not os.access(thumbnail, os.R_OK):

View File

@ -7,7 +7,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<width>838</width>
<height>730</height>
</rect>
</property>
@ -89,7 +89,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>524</width>
<width>562</width>
<height>683</height>
</rect>
</property>

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>335</width>
<height>540</height>
<height>570</height>
</rect>
</property>
<property name="windowTitle">
@ -84,6 +84,21 @@ p, li { white-space: pre-wrap; }
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>301</width>
<height>234</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
@ -91,7 +106,7 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<item row="0" column="1">
<widget class="QLineEdit" name="title">
<property name="toolTip">
<string>Regular expression (?P&amp;lt;title&amp;gt;)</string>
@ -111,7 +126,7 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<item row="1" column="1">
<widget class="QLineEdit" name="authors">
<property name="toolTip">
<string>Regular expression (?P&lt;author&gt;)</string>
@ -131,7 +146,7 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<item row="2" column="1">
<widget class="QLineEdit" name="series">
<property name="toolTip">
<string>Regular expression (?P&lt;series&gt;)</string>
@ -144,14 +159,14 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="3" column="0" rowspan="2">
<item row="3" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Series index:</string>
</property>
</widget>
</item>
<item row="3" column="1" rowspan="2" colspan="2">
<item row="3" column="1">
<widget class="QLineEdit" name="series_index">
<property name="toolTip">
<string>Regular expression (?P&lt;series_index&gt;)</string>
@ -164,14 +179,14 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
<item row="5" column="0">
<item row="4" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>ISBN:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="4" column="1">
<widget class="QLineEdit" name="isbn">
<property name="toolTip">
<string>Regular expression (?P&lt;isbn&gt;)</string>
@ -185,6 +200,10 @@ p, li { white-space: pre-wrap; }
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>

View File

@ -46,7 +46,10 @@ class PersistentTemporaryFile(object):
self.close()
def __del__(self):
try:
self.close()
except:
pass
def PersistentTemporaryDirectory(suffix='', prefix='', dir=None):

View File

@ -828,7 +828,7 @@ else:
IsMagickWand = _magick.IsMagickWand
# MagickGetException
try:
_magick.MagickGetException.restype = ctypes.POINTER(ctypes.c_char)
_magick.MagickGetException.restype = ctypes.c_char_p
_magick.MagickGetException.argtypes = (MagickWand,ctypes.POINTER(ExceptionType))
except AttributeError,e:
pass

View File

@ -7,6 +7,7 @@ __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import sys, os, cPickle
from calibre.constants import isnewosx
AUTHTOOL="""#!/usr/bin/python
import os
@ -27,7 +28,7 @@ for s, l in zip(scripts, links):
DEST_PATH = '/usr/bin'
def create_symlinks():
return create_symlinks_new() if getattr(sys, 'new_app_bundle', False) else create_symlinks_old()
return create_symlinks_new() if isnewosx else create_symlinks_old()
def get_scripts():
return cPickle.load(open(P('scripts.pickle'), 'rb'))