Merge from trunk

This commit is contained in:
Charles Haley 2012-01-12 13:02:30 +01:00
commit dde61529c8
25 changed files with 630 additions and 185 deletions

View File

@ -6,7 +6,7 @@ __license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import os, cPickle, re, shutil, marshal, zipfile, glob, time
import os, cPickle, re, shutil, marshal, zipfile, glob, time, subprocess, sys
from zlib import compress
from setup import Command, basenames, __appname__
@ -35,8 +35,8 @@ class Coffee(Command): # {{{
help='Display the generated javascript')
def run(self, opts):
from calibre.utils.coffeescript import compile_coffeescript
self.compiler = compile_coffeescript
cc = self.j(self.SRC, 'calibre', 'utils', 'serve_coffee.py')
self.compiler = [sys.executable, cc, 'compile']
self.do_coffee_compile(opts)
if opts.watch:
try:
@ -63,24 +63,24 @@ class Coffee(Command): # {{{
if self.newer(js, x):
print ('\t%sCompiling %s'%(time.strftime('[%H:%M:%S] ') if
timestamp else '', os.path.basename(x)))
with open(x, 'rb') as f:
cs, errs = self.compiler(f.read())
for line in errs:
print (line)
if cs and not errs:
try:
cs = subprocess.check_output(self.compiler +
[x]).decode('utf-8')
except Exception as e:
print ('\n\tCompilation of %s failed'%os.path.basename(x))
print (e)
if ignore_errors:
with open(js, 'wb') as f:
f.write('# Compilation from coffeescript failed')
else:
raise SystemExit(1)
else:
with open(js, 'wb') as f:
f.write(cs.encode('utf-8'))
if opts.show_js:
self.show_js(js)
print ('#'*80)
print ('#'*80)
else:
print ('\n\tCompilation of %s failed'%os.path.basename(x))
if ignore_errors:
with open(js, 'wb') as f:
f.write('# Compilation from coffeescript failed')
else:
raise SystemExit(1)
def clean(self):
for toplevel, dest in self.COFFEE_DIRS.iteritems():

View File

@ -31,7 +31,7 @@ if False:
# Prevent pyflakes from complaining
winutil, winutilerror, __appname__, islinux, __version__
fcntl, win32event, isfrozen, __author__
winerror, win32api, isbsd
winerror, win32api, isbsd, config_dir
_mt_inited = False
def _init_mimetypes():
@ -699,69 +699,6 @@ if isosx:
traceback.print_exc()
def ipython(user_ns=None):
old_argv = sys.argv
sys.argv = ['ipython']
if user_ns is None:
user_ns = locals()
ipydir = os.path.join(config_dir, ('_' if iswindows else '.')+'ipython')
os.environ['IPYTHONDIR'] = ipydir
if not os.path.exists(ipydir):
os.makedirs(ipydir)
for x in ('', '.ini'):
rc = os.path.join(ipydir, 'ipythonrc'+x)
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()
sys.argv = old_argv
from calibre.utils.ipython import ipython
ipython(user_ns=user_ns)

View File

@ -153,3 +153,12 @@ else:
atexit.register(cleanup_cdir)
# }}}
def get_version():
'''Return version string that indicates if we are running in a dev env'''
dv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
v = __version__
if getattr(sys, 'frozen', False) and dv and os.path.abspath(dv) in sys.path:
v += '*'
return v

View File

@ -95,11 +95,11 @@ class POCKETBOOK360(EB600):
FORMATS = ['epub', 'fb2', 'prc', 'mobi', 'pdf', 'djvu', 'rtf', 'chm', 'txt']
VENDOR_NAME = ['PHILIPS', '__POCKET']
WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['MASS_STORGE', 'BOOK_USB_STORAGE']
VENDOR_NAME = ['PHILIPS', '__POCKET', 'POCKETBO']
WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = ['MASS_STORGE', 'BOOK_USB_STORAGE',
'POCKET_611_61']
OSX_MAIN_MEM = 'Philips Mass Storge Media'
OSX_CARD_A_MEM = 'Philips Mass Storge Media'
OSX_MAIN_MEM = OSX_CARD_A_MEM = 'Philips Mass Storge Media'
OSX_MAIN_MEM_VOL_PAT = re.compile(r'/Pocket')
@classmethod

View File

@ -568,7 +568,11 @@ class MobiMLizer(object):
if isblock:
para = bstate.para
if para is not None and para.text == u'\xa0' and len(para) < 1:
if style.height > 2:
para.getparent().replace(para, etree.Element(XHTML('br')))
else:
# This is too small to be rendered effectively, drop it
para.getparent().remove(para)
bstate.para = None
bstate.istate = None
vmargin = asfloat(style['margin-bottom'])

View File

@ -244,7 +244,9 @@ class MetadataHeader(BookHeader):
class MobiReader(object):
PAGE_BREAK_PAT = re.compile(r'(<[/]{0,1}mbp:pagebreak\s*[/]{0,1}>)+', re.IGNORECASE)
PAGE_BREAK_PAT = re.compile(
r'<\s*/{0,1}\s*mbp:pagebreak((?:\s+[^/>]*){0,1})/{0,1}\s*>\s*(?:<\s*/{0,1}\s*mbp:pagebreak\s*/{0,1}\s*>)*',
re.IGNORECASE)
IMAGE_ATTRS = ('lowrecindex', 'recindex', 'hirecindex')
def __init__(self, filename_or_stream, log, user_encoding=None, debug=None,
@ -539,6 +541,9 @@ class MobiReader(object):
x.getparent().remove(x)
svg_tags = []
forwardable_anchors = []
pagebreak_anchors = []
BLOCK_TAGS = {'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
'div', 'p'}
for i, tag in enumerate(root.iter(etree.Element)):
tag.attrib.pop('xmlns', '')
for x in tag.attrib:
@ -657,6 +662,10 @@ class MobiReader(object):
if not tag.text:
tag.tag = 'div'
if (attrib.get('class', None) == 'mbp_pagebreak' and tag.tag ==
'div' and 'filepos-id' in attrib):
pagebreak_anchors.append(tag)
if 'filepos-id' in attrib:
attrib['id'] = attrib.pop('filepos-id')
if 'name' in attrib and attrib['name'] != attrib['id']:
@ -670,8 +679,7 @@ class MobiReader(object):
if (tag.tag == 'a' and attrib.get('id', '').startswith('filepos')
and not tag.text and (tag.tail is None or not
tag.tail.strip()) and getattr(tag.getnext(), 'tag',
None) in ('h1', 'h2', 'h3', 'h4', 'h5', 'h6',
'div', 'p')):
None) in BLOCK_TAGS):
# This is an empty anchor immediately before a block tag, move
# the id onto the block tag instead
forwardable_anchors.append(tag)
@ -704,6 +712,18 @@ class MobiReader(object):
if hasattr(parent, 'remove'):
parent.remove(tag)
for tag in pagebreak_anchors:
anchor = tag.attrib['id']
del tag.attrib['id']
if 'name' in tag.attrib:
del tag.attrib['name']
p = tag.getparent()
a = p.makeelement('a')
a.attrib['id'] = anchor
p.insert(p.index(tag)+1, a)
if getattr(a.getnext(), 'tag', None) in BLOCK_TAGS:
forwardable_anchors.append(a)
for tag in forwardable_anchors:
block = tag.getnext()
tag.getparent().remove(tag)
@ -919,7 +939,7 @@ class MobiReader(object):
def replace_page_breaks(self):
self.processed_html = self.PAGE_BREAK_PAT.sub(
'<div class="mbp_pagebreak" />',
r'<div \1 class="mbp_pagebreak" />',
self.processed_html)
def add_anchors(self):
@ -1047,3 +1067,22 @@ def get_metadata(stream):
im.convert('RGB').save(obuf, format='JPEG')
mi.cover_data = ('jpg', obuf.getvalue())
return mi
def test_mbp_regex():
for raw, m in {
'<mbp:pagebreak></mbp:pagebreak>':'',
'<mbp:pagebreak xxx></mbp:pagebreak>yyy':' xxxyyy',
'<mbp:pagebreak> </mbp:pagebreak>':'',
'<mbp:pagebreak>xxx':'xxx',
'<mbp:pagebreak/>xxx':'xxx',
'<mbp:pagebreak sdf/ >xxx':' sdfxxx',
'<mbp:pagebreak / >':' ',
'</mbp:pagebreak>':'',
'</mbp:pagebreak sdf>':' sdf',
'</mbp:pagebreak><mbp:pagebreak></mbp:pagebreak>xxx':'xxx',
}.iteritems():
ans = MobiReader.PAGE_BREAK_PAT.sub(r'\1', raw)
if ans != m:
raise Exception('%r != %r for %r'%(ans, m, raw))

Binary file not shown.

View File

@ -32,6 +32,11 @@ window_ypos = (pos=null) ->
mark_and_reload = (evt) ->
# Remove image in case the click was on the image itself, we want the cfi to
# be on the underlying element
if evt.button == 2
return # Right mouse click, generated only in firefox
reset = document.getElementById('reset')
if document.elementFromPoint(evt.clientX, evt.clientY) == reset
return
ms = document.getElementById("marker")
if ms
ms.parentNode?.removeChild(ms)

View File

@ -71,7 +71,8 @@
righteous indignation and dislike men who are so beguiled and
demoralized by the charms of pleasure of the moment, so blinded
by desire, that they cannot foresee
<img src="marker.png" width="150" height="200" alt="Test Image" style="border: solid 1px black; display:block"/>
<img src="marker.png" width="150" height="200" alt="Test Image"
style="border: solid 1px black; display:block"/>
</div>
<h2>Some entities and comments</h2>
@ -103,7 +104,8 @@
they cannot foresee</p>
<h2>Lots of collapsed whitespace</h2>
<p>Try clicking the A character after the colon: A suffix</p>
<p>Try clicking the A character after the colon:
A suffix</p>
<h2>Lots of nested/sibling tags</h2>
<p>A <span>bunch of <span>nested<span> and</span> <span>sibling</span>
@ -111,20 +113,23 @@
over this paragraph to test<span> things.</span></p>
<h2>Images</h2>
<p>Try clicking at different points along the image. Also try changing the magnification and then hitting reload.</p>
<img src="marker.png" width="150" height="200" alt="Test Image" style="border: solid 1px black"/>
<p>Try clicking at different points along the image. Also try
changing the magnification and then hitting reload.</p>
<img src="marker.png" width="150" height="200" alt="Test Image"
style="border: solid 1px black"/>
<h2>Video</h2>
<p>Try clicking on this video while it is playing. The page should
reload with the video paused at the point it was at when you
clicked. To play the video you should right click on it and select
play (otherwise the click will cause a reload). This is currently
broken because of issues in the python server use to serve test
content. I lack the patience to track down the bug. </p>
<video width="320" height="240" controls="controls" preload="auto" src="birds.mp4" type="video/mp4" />
play (otherwise the click will cause a reload).
</p>
<video width="320" height="240" controls="controls" preload="auto"
src="birds.webm" type="video/webm" />
</div>
<img id="marker" style="position: absolute; display:none; z-index:10" src="marker.png" alt="Marker" />
<img id="marker" style="position: absolute; display:none; z-index:10"
src="marker.png" alt="Marker" />
</body>
</html>

View File

@ -214,6 +214,9 @@ class SchedulerDialog(QDialog, Ui_Dialog):
self.recipes.setModel(self.recipe_model)
self.detail_box.setVisible(False)
self.download_button = self.buttonBox.addButton(_('&Download now'),
self.buttonBox.ActionRole)
self.download_button.setIcon(QIcon(I('arrow-down.png')))
self.download_button.setVisible(False)
self.recipes.currentChanged = self.current_changed
for b, c in self.SCHEDULE_TYPES.iteritems():
@ -371,7 +374,8 @@ class SchedulerDialog(QDialog, Ui_Dialog):
'''%dict(title=recipe.get('title'), cb=_('Created by: '),
author=recipe.get('author', _('Unknown')),
description=recipe.get('description', '')))
self.download_button.setToolTip(
_('Downlod %s now')%recipe.get('title'))
scheduled = schedule_info is not None
self.schedule.setChecked(scheduled)
self.toggle_schedule_info()

View File

@ -53,8 +53,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>524</width>
<height>504</height>
<width>518</width>
<height>498</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
@ -318,13 +318,6 @@
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="download_button">
<property name="text">
<string>&amp;Download now</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>

View File

@ -158,7 +158,7 @@ def email_news(mi, remove, get_fmts, done, job_manager):
return sent_mails
plugboard_email_value = 'email'
plugboard_email_formats = ['epub']
plugboard_email_formats = ['epub', 'mobi']
class EmailMixin(object): # {{{

View File

@ -5,14 +5,14 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import functools, sys, os
import functools
from PyQt4.Qt import Qt, QStackedWidget, QMenu, \
QSize, QSizePolicy, QStatusBar, QLabel, QFont
from calibre.utils.config import prefs
from calibre.constants import isosx, __appname__, preferred_encoding, \
__version__
from calibre.constants import (isosx, __appname__, preferred_encoding,
get_version)
from calibre.gui2 import config, is_widescreen, gprefs
from calibre.gui2.library.views import BooksView, DeviceBooksView
from calibre.gui2.widgets import Splitter
@ -187,11 +187,7 @@ class StatusBar(QStatusBar): # {{{
self.clearMessage()
def get_version(self):
dv = os.environ.get('CALIBRE_DEVELOP_FROM', None)
v = __version__
if getattr(sys, 'frozen', False) and dv and os.path.abspath(dv) in sys.path:
v += '*'
return v
return get_version()
def show_message(self, msg, timeout=0):
self.showMessage(msg, timeout)

View File

@ -466,7 +466,7 @@ class BooksModel(QAbstractTableModel): # {{{
if cpb:
newmi = mi.deepcopy_metadata()
newmi.template_to_attribute(mi, cpb)
if newmi:
if newmi is not None:
_set_metadata(pt, newmi, format)
else:
_set_metadata(pt, mi, format)

View File

@ -11,7 +11,7 @@ SHORTCUTS = {
'Next Page' : (['PgDown', 'Space'],
_('Scroll to the next page')),
'Previous Page' : (['PgUp', 'Backspace'],
'Previous Page' : (['PgUp', 'Backspace', 'Shift+Space'],
_('Scroll to the previous page')),
'Next Section' : (['Ctrl+PgDown', 'Ctrl+Down'],

View File

@ -546,7 +546,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
authors = self.authors(id, index_is_id=True)
if not authors:
authors = _('Unknown')
author = ascii_filename(authors.split(',')[0]
author = ascii_filename(authors.split(',')[0].replace('|', ',')
)[:self.PATH_LIMIT].decode('ascii', 'replace')
title = ascii_filename(self.title(id, index_is_id=True)
)[:self.PATH_LIMIT].decode('ascii', 'replace')
@ -565,7 +565,7 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
authors = self.authors(id, index_is_id=True)
if not authors:
authors = _('Unknown')
author = ascii_filename(authors.split(',')[0]
author = ascii_filename(authors.split(',')[0].replace('|', ',')
)[:self.PATH_LIMIT].decode('ascii', 'replace')
title = ascii_filename(self.title(id, index_is_id=True)
)[:self.PATH_LIMIT].decode('ascii', 'replace')

View File

@ -65,7 +65,8 @@ to the latest code, use the command::
bzr merge
You can also download the source code as a tarball (archive) from `here <http://status.calibre-ebook.com/dist/src>`_.
The calibre repository is huge so the branch operation above takes along time (about an hour). If you want to get the code faster, the sourcecode for the latest release is always available as an
`archive <http://status.calibre-ebook.com/dist/src>`_.
Submitting your changes to be included
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -66,6 +66,7 @@ class Worker(object):
if isfrozen:
return os.path.join(sys.executables_location, e)
if hasattr(sys, 'executables_location'):
c = os.path.join(sys.executables_location, e)
if os.access(c, os.X_OK):
return c

View File

@ -0,0 +1,150 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import os, cPickle, traceback, time, importlib
from binascii import hexlify, unhexlify
from multiprocessing.connection import Listener, arbitrary_address, Client
from threading import Thread
from contextlib import closing
from calibre.constants import iswindows
from calibre.utils.ipc.launch import Worker
class WorkerError(Exception):
def __init__(self, msg, orig_tb=''):
Exception.__init__(self, msg)
self.org_tb = orig_tb
class ConnectedWorker(Thread):
def __init__(self, listener, args):
Thread.__init__(self)
self.daemon = True
self.listener = listener
self.args = args
self.accepted = False
self.tb = None
self.res = None
def run(self):
conn = tb = None
for i in range(2):
# On OS X an EINTR can interrupt the accept() call
try:
conn = self.listener.accept()
break
except:
tb = traceback.format_exc()
pass
if conn is None:
self.tb = tb
return
self.accepted = True
with closing(conn):
try:
try:
conn.send(self.args)
except:
# Maybe an EINTR
conn.send(self.args)
try:
self.res = conn.recv()
except:
# Maybe an EINTR
self.res = conn.recv()
except:
self.tb = traceback.format_exc()
def communicate(ans, worker, listener, args, timeout=300):
cw = ConnectedWorker(listener, args)
cw.start()
st = time.time()
while worker.is_alive and cw.is_alive():
cw.join(0.01)
delta = time.time() - st
if not cw.accepted and delta > min(10, timeout):
break
if delta > timeout:
raise WorkerError('Worker appears to have hung')
if not cw.accepted:
if not cw.tb:
raise WorkerError('Failed to connect to worker process')
raise WorkerError('Failed to connect to worker process', cw.tb)
if cw.tb:
raise WorkerError('Failed to communicate with worker process')
if cw.res.get('tb', None):
raise WorkerError('Worker failed', cw.res['tb'])
ans['result'] = cw.res['result']
def fork_job(mod_name, func_name, args=(), kwargs={}, timeout=300, # seconds
cwd=None, priority='normal', env={}, no_output=False):
ans = {'result':None, 'stdout_stderr':None}
address = arbitrary_address('AF_PIPE' if iswindows else 'AF_UNIX')
if iswindows and address[1] == ':':
address = address[2:]
auth_key = os.urandom(32)
listener = Listener(address=address, authkey=auth_key)
env = dict(env)
env.update({
'CALIBRE_WORKER_ADDRESS' :
hexlify(cPickle.dumps(listener.address, -1)),
'CALIBRE_WORKER_KEY' : hexlify(auth_key),
'CALIBRE_SIMPLE_WORKER':
'calibre.utils.ipc.simple_worker:main',
})
w = Worker(env)
w(cwd=cwd, priority=priority)
try:
communicate(ans, w, listener, (mod_name, func_name, args, kwargs),
timeout=timeout)
finally:
t = Thread(target=w.kill)
t.daemon=True
t.start()
if no_output:
try:
os.remove(w.log_path)
except:
pass
if not no_output:
ans['stdout_stderr'] = w.log_path
return ans
def main():
# The entry point for the simple worker process
address = cPickle.loads(unhexlify(os.environ['CALIBRE_WORKER_ADDRESS']))
key = unhexlify(os.environ['CALIBRE_WORKER_KEY'])
with closing(Client(address, authkey=key)) as conn:
try:
args = conn.recv()
except:
# Maybe EINTR
args = conn.recv()
try:
mod, func, args, kwargs = args
mod = importlib.import_module(mod)
func = getattr(mod, func)
res = {'result':func(*args, **kwargs)}
except:
res = {'tb': traceback.format_exc()}
try:
conn.send(res)
except:
# Maybe EINTR
conn.send(res)

View File

@ -167,9 +167,13 @@ def main():
# so launch the gui as usual
from calibre.gui2.main import main as gui_main
return gui_main(['calibre'])
if 'CALIBRE_LAUNCH_INTERPRETER' in os.environ:
from calibre.utils.pyconsole.interpreter import main
return main()
csw = os.environ.get('CALIBRE_SIMPLE_WORKER', None)
if csw:
mod, _, func = csw.partition(':')
mod = importlib.import_module(mod)
func = getattr(mod, func)
func()
return
address = cPickle.loads(unhexlify(os.environ['CALIBRE_WORKER_ADDRESS']))
key = unhexlify(os.environ['CALIBRE_WORKER_KEY'])
resultf = unhexlify(os.environ['CALIBRE_WORKER_RESULT'])

View File

@ -0,0 +1,113 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import (unicode_literals, division, absolute_import,
print_function)
__license__ = 'GPL v3'
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'
import sys, os
from calibre.constants import iswindows, config_dir, get_version
ipydir = os.path.join(config_dir, ('_' if iswindows else '.')+'ipython')
def old_ipython(user_ns=None): # {{{
old_argv = sys.argv
sys.argv = ['ipython']
if user_ns is None:
user_ns = locals()
os.environ['IPYTHONDIR'] = ipydir
if not os.path.exists(ipydir):
os.makedirs(ipydir)
for x in ('', '.ini'):
rc = os.path.join(ipydir, 'ipythonrc'+x)
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()
sys.argv = old_argv
# }}}
def ipython(user_ns=None):
try:
import IPython
from IPython.config.loader import Config
except ImportError:
return old_ipython(user_ns=user_ns)
if not user_ns:
user_ns = {}
c = Config()
c.InteractiveShellApp.exec_lines = [
'from __future__ import division, absolute_import, unicode_literals, print_function',
]
c.TerminalInteractiveShell.confirm_exit = False
c.PromptManager.in_template = (r'{color.LightGreen}calibre '
'{color.LightBlue}[{color.LightCyan}%s{color.LightBlue}]'
r'{color.Green}|\#> '%get_version())
c.PromptManager.in2_template = r'{color.Green}|{color.LightGreen}\D{color.Green}> '
c.PromptManager.out_template = r'<\#> '
c.TerminalInteractiveShell.banner1 = ('Welcome to the interactive calibre'
' shell!\n\n')
c.PromptManager.justify = True
c.TerminalIPythonApp.ipython_dir = ipydir
os.environ['IPYTHONDIR'] = ipydir
c.InteractiveShell.separate_in = ''
c.InteractiveShell.separate_out = ''
c.InteractiveShell.separate_out2 = ''
c.PrefilterManager.multi_line_specials = True
IPython.embed(config=c, user_ns=user_ns)

View File

@ -39,7 +39,8 @@ class Controller(QThread):
authkey=self.auth_key, backlog=4)
self.env = {
'CALIBRE_LAUNCH_INTERPRETER': '1',
'CALIBRE_SIMPLE_WORKER':
'calibre.utils.pyconsole.interpreter:main',
'CALIBRE_WORKER_ADDRESS':
hexlify(cPickle.dumps(self.listener.address, -1)),
'CALIBRE_WORKER_KEY': hexlify(self.auth_key)

File diff suppressed because one or more lines are too long

View File

@ -1158,7 +1158,7 @@ ol, ul { padding-left: 2em; }
""" Anchors start """
self.writedata()
href = attrs[(XLINKNS,"href")].split("|")[0]
if href[0] == "#":
if href[:1] == "#": # Changed by Kovid
href = "#" + self.get_anchor(href[1:])
self.opentag('a', {'href':href})
self.purgedata()