Content server: Handle books with # in their title/authors correctly. Fixes #7354 (Having problems with calibre server)

This commit is contained in:
Kovid Goyal 2010-10-30 22:40:13 -06:00
parent 39e102e3f8
commit 20e015ed74
4 changed files with 63 additions and 18 deletions

View File

@ -5,10 +5,37 @@ __license__ = 'GPL v3'
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>' __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import subprocess, tempfile, os, time import subprocess, tempfile, os, time, sys
from setup import Command from setup import Command
try:
from pyinotify import WatchManager, ThreadedNotifier, EventsCodes, ProcessEvent
except:
wm = None
else:
wm = WatchManager()
flags = EventsCodes.ALL_FLAGS
mask = flags['IN_MODIFY']
class ProcessEvents(ProcessEvent):
def __init__(self, command):
ProcessEvent.__init__(self)
self.command = command
def process_default(self, event):
name = getattr(event,
'name', None)
if name and os.path.splitext(name)[1].startswith('.py'):
print
print name, 'changed'
self.command.kill_server()
self.command.launch_server()
print self.command.prompt,
sys.stdout.flush()
class Server(Command): class Server(Command):
description = 'Run the calibre server in development mode conveniently' description = 'Run the calibre server in development mode conveniently'
@ -20,35 +47,51 @@ class Server(Command):
'-I', 'src', 'src/monocle.js'], '-I', 'src', 'src/monocle.js'],
stdout=open('resources/content_server/read/monocle.js', 'wb')) stdout=open('resources/content_server/read/monocle.js', 'wb'))
def launch_server(self, log): def launch_server(self):
print 'Starting server...\n'
self.rebuild_monocole() self.rebuild_monocole()
p = subprocess.Popen(['calibre-server', '--develop'], p = subprocess.Popen(['calibre-server', '--develop'],
stderr=subprocess.STDOUT, stdout=log) stderr=subprocess.STDOUT, stdout=self.server_log)
time.sleep(0.2) time.sleep(0.2)
if p.poll() is not None: if p.poll() is not None:
print 'Starting server failed' print 'Starting server failed'
raise SystemExit(1) raise SystemExit(1)
return p return p
def kill_server(self):
while self.server_proc.poll() is None:
self.server_proc.terminate()
time.sleep(0.1)
self.server_proc.kill()
def watch(self):
if wm is not None:
self.notifier = ThreadedNotifier(wm, ProcessEvents(self))
self.notifier.start()
self.wdd = wm.add_watch(os.path.abspath('src'), mask, rec=True)
def run(self, opts): def run(self, opts):
tdir = tempfile.gettempdir() tdir = tempfile.gettempdir()
logf = os.path.join(tdir, 'calibre-server.log') logf = os.path.join(tdir, 'calibre-server.log')
log = open(logf, 'ab') self.server_log = open(logf, 'ab')
self.prompt = 'Press Enter to kill/restart server. Ctrl+C to quit: '
print 'Server log available at:', logf print 'Server log available at:', logf
print
self.server_proc = None
self.watch()
while True: while True:
print 'Starting server...' self.server_proc = self.launch_server()
p = self.launch_server(log)
try: try:
raw_input('Press Enter to kill/restart server. Ctrl+C to quit: ') raw_input(self.prompt)
except: except:
if p.poll() is None: if self.server_proc.poll() is None:
p.kill() self.server_proc.kill()
break break
else: else:
while p.poll() is None: self.kill_server()
p.terminate()
time.sleep(0.1)
p.kill()
print print
if hasattr(self, 'notifier'):
self.notifier.stop()

View File

@ -566,7 +566,8 @@ class BrowseServer(object):
if not val: if not val:
val = '' val = ''
args[key] = xml(val, True) args[key] = xml(val, True)
fname = ascii_filename(args['title']) + ' - ' + ascii_filename(args['authors']) fname = quote(ascii_filename(args['title']) + ' - ' +
ascii_filename(args['authors']))
return args, fmt, fmts, fname return args, fmt, fmts, fname
@Endpoint(mimetype='application/json; charset=utf-8') @Endpoint(mimetype='application/json; charset=utf-8')

View File

@ -70,10 +70,10 @@ class ContentServer(object):
id = id.rpartition('_')[-1].partition('.')[0] id = id.rpartition('_')[-1].partition('.')[0]
match = re.search(r'\d+', id) match = re.search(r'\d+', id)
if not match: if not match:
raise cherrypy.HTTPError(400, 'id:%s not an integer'%id) raise cherrypy.HTTPError(404, 'id:%s not an integer'%id)
id = int(match.group()) id = int(match.group())
if not self.db.has_id(id): if not self.db.has_id(id):
raise cherrypy.HTTPError(400, 'id:%d does not exist in database'%id) raise cherrypy.HTTPError(404, 'id:%d does not exist in database'%id)
if what == 'thumb' or what.startswith('thumb_'): if what == 'thumb' or what.startswith('thumb_'):
try: try:
width, height = map(int, what.split('_')[1:]) width, height = map(int, what.split('_')[1:])

View File

@ -7,6 +7,7 @@ __docformat__ = 'restructuredtext en'
import re, os import re, os
import __builtin__ import __builtin__
from urllib import quote
import cherrypy import cherrypy
from lxml import html from lxml import html
@ -115,8 +116,8 @@ def build_index(books, num, search, sort, order, start, total, url_base, CKEYS,
data = TD() data = TD()
for fmt in book['formats'].split(','): for fmt in book['formats'].split(','):
a = ascii_filename(book['authors']) a = quote(ascii_filename(book['authors']))
t = ascii_filename(book['title']) t = quote(ascii_filename(book['title']))
s = SPAN( s = SPAN(
A( A(
fmt.lower(), fmt.lower(),