When auto-reloading server, handle RS compilation failures better

This commit is contained in:
Kovid Goyal 2015-10-19 17:53:44 +05:30
parent 928722690f
commit 7fa3db93af
2 changed files with 42 additions and 21 deletions

View File

@ -212,18 +212,26 @@ class Worker(object):
self.p = None self.p = None
def restart(self): def restart(self):
from calibre.utils.rapydscript import compile_srv from calibre.utils.rapydscript import compile_srv, CompileFailure
self.clean_kill() self.clean_kill()
try: while True:
compile_srv() try:
except EnvironmentError as e: compile_srv()
# Happens if the editor deletes and replaces a file being edited except EnvironmentError as e:
if e.errno != errno.ENOENT or not getattr(e, 'filename', False): # Happens if the editor deletes and replaces a file being edited
raise if e.errno != errno.ENOENT or not getattr(e, 'filename', False):
st = time.time() raise
while not os.path.exists(e.filename) and time.time() - st < 3: st = time.time()
time.sleep(0.01) while not os.path.exists(e.filename) and time.time() - st < 3:
compile_srv() time.sleep(0.01)
compile_srv()
except CompileFailure as e:
print(e.message, file=sys.stderr)
print('Retrying in two seconds')
time.sleep(2)
continue
break
self.p = subprocess.Popen(self.cmd, creationflags=getattr(subprocess, 'CREATE_NEW_PROCESS_GROUP', 0)) self.p = subprocess.Popen(self.cmd, creationflags=getattr(subprocess, 'CREATE_NEW_PROCESS_GROUP', 0))
def auto_reload(log, dirs=frozenset(), cmd=None, add_default_dirs=True): def auto_reload(log, dirs=frozenset(), cmd=None, add_default_dirs=True):

View File

@ -58,11 +58,8 @@ def compiler():
c.eval(buf.getvalue(), fname=COMPILER_PATH, noreturn=True) c.eval(buf.getvalue(), fname=COMPILER_PATH, noreturn=True)
return c return c
class PYJError(Exception): class CompileFailure(ValueError):
pass
def __init__(self, errors):
Exception.__init__(self, '')
self.errors = errors
def compile_pyj(data, filename='<stdin>', beautify=True, private_scope=True, libdir=None, omit_baselib=False): def compile_pyj(data, filename='<stdin>', beautify=True, private_scope=True, libdir=None, omit_baselib=False):
if isinstance(data, bytes): if isinstance(data, bytes):
@ -77,7 +74,25 @@ def compile_pyj(data, filename='<stdin>', beautify=True, private_scope=True, lib
'filename': filename, 'filename': filename,
} }
c.g.rs_source_code = data c.g.rs_source_code = data
return c.eval('exports["compile"](rs_source_code, %s, current_options)' % json.dumps(filename)) ok, result = c.eval(
'''
ans = [null, null];
try {
ans = [true, exports["compile"](rs_source_code, %s, current_options)];
} catch(e) {
ans = [false, e]
}
ans;
''' % json.dumps(filename))
if ok:
return result
result = to_python(result)
if 'message' in result:
msg = result['message']
if 'filename' in result and 'line' in result:
msg = '%s:%s:%s' % (result['filename'], result['line'], msg)
raise CompileFailure(msg)
raise CompileFailure(repr(result))
def compile_srv(): def compile_srv():
d = os.path.dirname d = os.path.dirname
@ -295,12 +310,10 @@ def main(args=sys.argv):
enc = getattr(sys.stdin, 'encoding', 'utf-8') or 'utf-8' enc = getattr(sys.stdin, 'encoding', 'utf-8') or 'utf-8'
data = compile_pyj(sys.stdin.read().decode(enc), libdir=libdir, private_scope=not args.no_private_scope, omit_baselib=args.omit_baselib) data = compile_pyj(sys.stdin.read().decode(enc), libdir=libdir, private_scope=not args.no_private_scope, omit_baselib=args.omit_baselib)
print(data.encode(enc)) print(data.encode(enc))
except PYJError as e:
for e in e.errors:
print(format_error(e), file=sys.stderr)
raise SystemExit(1)
except JSError as e: except JSError as e:
raise SystemExit(e.message) raise SystemExit(e.message)
except CompileFailure as e:
raise SystemExit(e.message)
def entry(): def entry():
main(sys.argv[1:]) main(sys.argv[1:])