mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Content server: Handle books with # in their title/authors correctly. Fixes #7354 (Having problems with calibre server)
This commit is contained in:
parent
39e102e3f8
commit
20e015ed74
@ -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()
|
||||||
|
|
||||||
|
@ -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')
|
||||||
|
@ -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:])
|
||||||
|
@ -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(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user