From 1ba821eb0d2369e5333d4cf35bf3d21f7a02c933 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 11 Apr 2014 22:56:36 +0530 Subject: [PATCH] Port coffeescript compiler --- src/calibre/utils/serve_coffee.py | 100 +++++++++++++++++------------- 1 file changed, 56 insertions(+), 44 deletions(-) diff --git a/src/calibre/utils/serve_coffee.py b/src/calibre/utils/serve_coffee.py index 35ce82a26c..2698282155 100644 --- a/src/calibre/utils/serve_coffee.py +++ b/src/calibre/utils/serve_coffee.py @@ -22,13 +22,12 @@ import time, BaseHTTPServer, os, sys, re, SocketServer from threading import Lock from SimpleHTTPServer import SimpleHTTPRequestHandler -from PyQt5.Qt import QCoreApplication # Compiler {{{ try: - from PyQt5.QtScript import QScriptEngine, QScriptValue + from PyQt5.Qt import QJSEngine, QJSValue - class Compiler(QScriptEngine): + class Compiler(QJSEngine): ''' You can use this class in any thread, but make sure you instantiate it in @@ -38,14 +37,15 @@ try: ''' def __init__(self): + from PyQt5.Qt import QCoreApplication if QCoreApplication.instance() is None: self.__app_ = QCoreApplication([]) - QScriptEngine.__init__(self) + QJSEngine.__init__(self) res = self.evaluate(CS_JS, 'coffee-script.js') if res.isError(): raise Exception('Failed to run the coffee script compiler: %s'% - unicode(res.toString())) + res.toString()) self.lock = Lock() def __call__(self, raw, filename=None): @@ -55,50 +55,59 @@ try: if not filename: filename = '' go = self.globalObject() - go.setProperty('coffee_src', QScriptValue(raw), - go.ReadOnly|go.Undeletable) + go.setProperty('coffee_src', QJSValue(raw)) res = self.evaluate('this.CoffeeScript.compile(this.coffee_src)', filename) if res.isError(): - return '', [unicode(res.toString())] - return unicode(res.toString()), [] + return '', [res.toString()] + return res.toString(), [] except ImportError: + pass - def do_compile(raw): - from PyQt5.QtWebKit import QWebPage - from PyQt5.Qt import QApplication - import json - app = QApplication([]) +def do_compile(raw, filename=None): + from calibre.gui2 import must_use_qt + must_use_qt() + from PyQt5.Qt import QWebPage, QApplication + import json + app = QApplication([]) - class C(QWebPage): - def __init__(self): - QWebPage.__init__(self) - self.msgs = [] - def javaScriptConsoleMessage(self, msg, *args): - self.msgs.append(unicode(msg)) + class C(QWebPage): - compiler = C() - evaljs = compiler.mainFrame().evaluateJavaScript - raw = json.dumps(raw) - ans = unicode((evaljs(CS_JS + '\n\n;\nCoffeeScript.compile(%s)'%raw).toString())) - if not ans.strip(): - ans = u'', tuple(compiler.msgs) - else: - ans = ans, () - app.processEvents() - del compiler - app.processEvents() - return ans + def __init__(self): + QWebPage.__init__(self) + self.msgs = [] + def javaScriptConsoleMessage(self, msg, *args): + self.msgs.append(unicode(msg)) + + compiler = C() + evaljs = compiler.mainFrame().evaluateJavaScript + raw = json.dumps(raw) + ans = evaljs(CS_JS + '\n\n;\nCoffeeScript.compile(%s)'%raw) + if not ans or not ans.strip(): + ans = u'', tuple(compiler.msgs) + else: + ans = ans, () + app.processEvents() + del compiler + app.processEvents() + return ans # }}} def compile_coffeescript(raw, filename=None): + from calibre.gui2 import is_ok_to_use_qt try: + if is_ok_to_use_qt(): + raise NameError('The WebKit based compiler is much faster than QJSEngine') return Compiler()(raw, filename) except NameError: - from calibre.utils.ipc.simple_worker import fork_job - return fork_job('calibre.utils.serve_coffee', 'do_compile', - args=(raw,), no_output=True)['result'] + from calibre.utils.ipc.simple_worker import fork_job, WorkerError + try: + return fork_job('calibre.utils.serve_coffee', 'do_compile', + args=(raw,), no_output=True)['result'] + except WorkerError as err: + print (err.orig_tb) + raise def check_coffeescript(filename): with open(filename, 'rb') as f: @@ -108,7 +117,8 @@ def check_coffeescript(filename): print('\n'.join(errs)) raise Exception('Compilation failed') -class HTTPRequestHandler(SimpleHTTPRequestHandler): # {{{ +class HTTPRequestHandler(SimpleHTTPRequestHandler): # {{{ + ''' Handle Range headers, as browsers insist on using range for