From e58d17ae45e03da96197c1b959332cfb1bcb1999 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 20 Jun 2012 14:26:05 +0530 Subject: [PATCH] Allow dynamic compilation of coffeescript on platforms where QtScript is not available --- src/calibre/utils/resources.py | 2 + src/calibre/utils/serve_coffee.py | 96 +++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 31 deletions(-) diff --git a/src/calibre/utils/resources.py b/src/calibre/utils/resources.py index 11be8f049a..fdad08f5e7 100644 --- a/src/calibre/utils/resources.py +++ b/src/calibre/utils/resources.py @@ -28,12 +28,14 @@ class PathResolver(object): self.default_path = sys.resources_location dev_path = os.environ.get('CALIBRE_DEVELOP_FROM', None) + self.using_develop_from = False if dev_path is not None: dev_path = os.path.join(os.path.abspath( os.path.dirname(dev_path)), 'resources') if suitable(dev_path): self.locations.insert(0, dev_path) self.default_path = dev_path + self.using_develop_from = True user_path = os.path.join(config_dir, 'resources') self.user_path = None diff --git a/src/calibre/utils/serve_coffee.py b/src/calibre/utils/serve_coffee.py index 4e88eb5888..fa5d80a961 100644 --- a/src/calibre/utils/serve_coffee.py +++ b/src/calibre/utils/serve_coffee.py @@ -23,48 +23,82 @@ from threading import Lock from SimpleHTTPServer import SimpleHTTPRequestHandler from PyQt4.Qt import QCoreApplication -from PyQt4.QtScript import QScriptEngine, QScriptValue -class Compiler(QScriptEngine): # {{{ +# Compiler {{{ +try: + from PyQt4.QtScript import QScriptEngine, QScriptValue - ''' - You can use this class in any thread, but make sure you instantiate it in - the main thread. Alternatively, construct a QCoreApplication in the main - thread, after which you can instantiate this class and use it in any - thread. - ''' + class Compiler(QScriptEngine): - def __init__(self): - if QCoreApplication.instance() is None: - self.__app_ = QCoreApplication([]) + ''' + You can use this class in any thread, but make sure you instantiate it in + the main thread. Alternatively, construct a QCoreApplication in the main + thread, after which you can instantiate this class and use it in any + thread. + ''' - QScriptEngine.__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())) - self.lock = Lock() + def __init__(self): + if QCoreApplication.instance() is None: + self.__app_ = QCoreApplication([]) - def __call__(self, raw, filename=None): - with self.lock: - if not isinstance(raw, unicode): - raw = raw.decode('utf-8') - if not filename: - filename = '' - go = self.globalObject() - go.setProperty('coffee_src', QScriptValue(raw), - go.ReadOnly|go.Undeletable) - res = self.evaluate('this.CoffeeScript.compile(this.coffee_src)', - filename) + QScriptEngine.__init__(self) + res = self.evaluate(CS_JS, 'coffee-script.js') if res.isError(): - return '', [unicode(res.toString())] - return unicode(res.toString()), [] + raise Exception('Failed to run the coffee script compiler: %s'% + unicode(res.toString())) + self.lock = Lock() + def __call__(self, raw, filename=None): + with self.lock: + if not isinstance(raw, unicode): + raw = raw.decode('utf-8') + if not filename: + filename = '' + go = self.globalObject() + go.setProperty('coffee_src', QScriptValue(raw), + go.ReadOnly|go.Undeletable) + res = self.evaluate('this.CoffeeScript.compile(this.coffee_src)', + filename) + if res.isError(): + return '', [unicode(res.toString())] + return unicode(res.toString()), [] +except ImportError: + + def do_compile(raw): + from PyQt4.QtWebKit import QWebPage + from PyQt4.Qt import 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)) + + 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 compile_coffeescript(raw, filename=None): - return Compiler()(raw, filename) + try: + 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'] class HTTPRequestHandler(SimpleHTTPRequestHandler): # {{{ '''