Drop dependency on running X server when compiling coffeescript on linux

This commit is contained in:
Kovid Goyal 2012-01-17 09:10:06 +05:30
parent 0411a32344
commit 41a31b4c48

View File

@ -22,8 +22,7 @@ import time, BaseHTTPServer, os, sys, re, SocketServer
from threading import Lock from threading import Lock
from SimpleHTTPServer import SimpleHTTPRequestHandler from SimpleHTTPServer import SimpleHTTPRequestHandler
from PyQt4.QtWebKit import QWebPage from PyQt4.Qt import QCoreApplication, QScriptEngine, QScriptValue
from PyQt4.Qt import QThread, QApplication
# Infrastructure {{{ # Infrastructure {{{
def import_from_calibre(mod): def import_from_calibre(mod):
@ -35,23 +34,6 @@ def import_from_calibre(mod):
return importlib.import_module(mod) return importlib.import_module(mod)
_store_app = gui_thread = None _store_app = gui_thread = None
def check_qt():
global gui_thread, _store_app
_plat = sys.platform.lower()
iswindows = 'win32' in _plat or 'win64' in _plat
isosx = 'darwin' in _plat
islinux = not (iswindows or isosx)
if islinux and ':' not in os.environ.get('DISPLAY', ''):
raise RuntimeError('X server required. If you are running on a'
' headless machine, use xvfb')
if _store_app is None and QApplication.instance() is None:
_store_app = QApplication([])
if gui_thread is None:
gui_thread = QThread.currentThread()
if gui_thread is not QThread.currentThread():
raise RuntimeError('Cannot use Qt in non GUI thread')
def fork_job(*args, **kwargs): def fork_job(*args, **kwargs):
try: try:
return import_from_calibre('calibre.utils.ipc.simple_worker').fork_job(*args, return import_from_calibre('calibre.utils.ipc.simple_worker').fork_job(*args,
@ -77,48 +59,33 @@ def fork_job(*args, **kwargs):
# }}} # }}}
class Compiler(QWebPage): # {{{ class Compiler(QScriptEngine): # {{{
'''
Never use this class in anything except the main thread. If you want to use
it from other threads, use the forked_compile method instead.
'''
def __init__(self): def __init__(self):
check_qt() if QCoreApplication.instance() is None:
QWebPage.__init__(self) self.__app_ = QCoreApplication([])
self.frame = self.mainFrame()
self.filename = self._src = ''
self.frame.evaluateJavaScript(CS_JS)
self.frame.addToJavaScriptWindowObject("cs_compiler", self)
self.errors = []
def shouldInterruptJavaScript(self): QScriptEngine.__init__(self)
return True res = self.evaluate(CS_JS, 'coffee-script.js')
if res.isError():
def javaScriptConsoleMessage(self, msg, lineno, sourceid): raise Exception('Failed to run the coffee script compiler: %s'%
sourceid = sourceid or self.filename or '<script>' unicode(res.toString()))
self.errors.append('%s:%s'%(sourceid, msg)) self.lock = Lock()
def __evalcs(self, raw, filename):
# This method is NOT thread safe
self.filename = filename
self.setProperty('source', raw)
self.errors = []
res = self.frame.evaluateJavaScript('''
raw = document.getElementById("raw");
raw = cs_compiler.source;
CoffeeScript.compile(raw);
''')
ans = ''
if res.type() == res.String:
ans = unicode(res.toString())
return ans, list(self.errors)
def __call__(self, raw, filename=None): def __call__(self, raw, filename=None):
if not isinstance(raw, unicode): with self.lock:
raw = raw.decode('utf-8') if not isinstance(raw, unicode):
return self.__evalcs(raw, filename) raw = raw.decode('utf-8')
if not filename:
filename = '<string>'
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()), []
def forked_compile(raw, fname): def forked_compile(raw, fname):
# Entry point for the compile worker # Entry point for the compile worker