forked from M-Labs/artiq
worker: display compile warnings and errors nicely (#227).
This commit is contained in:
parent
95470a59e5
commit
67d2e7a828
|
@ -13,15 +13,16 @@ from artiq.compiler.targets import OR1KTarget
|
||||||
# Import for side effects (creating the exception classes).
|
# Import for side effects (creating the exception classes).
|
||||||
from artiq.coredevice import exceptions
|
from artiq.coredevice import exceptions
|
||||||
|
|
||||||
def _render_diagnostic(diagnostic):
|
|
||||||
|
def _render_diagnostic(diagnostic, colored):
|
||||||
def shorten_path(path):
|
def shorten_path(path):
|
||||||
return path.replace(os.path.normpath(os.path.join(__file__, "..", "..")), "<artiq>")
|
return path.replace(os.path.normpath(os.path.join(__file__, "..", "..")), "<artiq>")
|
||||||
lines = [shorten_path(path) for path in diagnostic.render(colored=True)]
|
lines = [shorten_path(path) for path in diagnostic.render(colored)]
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
class _DiagnosticEngine(diagnostic.Engine):
|
class _DiagnosticEngine(diagnostic.Engine):
|
||||||
def render_diagnostic(self, diagnostic):
|
def render_diagnostic(self, diagnostic):
|
||||||
sys.stderr.write(_render_diagnostic(diagnostic) + "\n")
|
sys.stderr.write(_render_diagnostic(diagnostic, colored=True) + "\n")
|
||||||
|
|
||||||
class CompileError(Exception):
|
class CompileError(Exception):
|
||||||
def __init__(self, diagnostic):
|
def __init__(self, diagnostic):
|
||||||
|
@ -30,7 +31,7 @@ class CompileError(Exception):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# Prepend a newline so that the message shows up on after
|
# Prepend a newline so that the message shows up on after
|
||||||
# exception class name printed by Python.
|
# exception class name printed by Python.
|
||||||
return "\n" + _render_diagnostic(self.diagnostic)
|
return "\n" + _render_diagnostic(self.diagnostic, colored=True)
|
||||||
|
|
||||||
|
|
||||||
@syscall
|
@syscall
|
||||||
|
|
|
@ -4,12 +4,13 @@ import os
|
||||||
import logging
|
import logging
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
import artiq
|
||||||
from artiq.protocols import pyon
|
from artiq.protocols import pyon
|
||||||
from artiq.tools import file_import
|
from artiq.tools import file_import
|
||||||
from artiq.master.worker_db import DeviceManager, DatasetManager, get_hdf5_output
|
from artiq.master.worker_db import DeviceManager, DatasetManager, get_hdf5_output
|
||||||
from artiq.language.environment import is_experiment
|
from artiq.language.environment import is_experiment
|
||||||
from artiq.language.core import set_watchdog_factory, TerminationRequested
|
from artiq.language.core import set_watchdog_factory, TerminationRequested
|
||||||
from artiq.coredevice.core import CompileError, host_only
|
from artiq.coredevice.core import CompileError, host_only, _render_diagnostic
|
||||||
from artiq import __version__ as artiq_version
|
from artiq import __version__ as artiq_version
|
||||||
|
|
||||||
|
|
||||||
|
@ -169,6 +170,26 @@ def string_to_hdf5(f, key, value):
|
||||||
dataset[()] = value.encode()
|
dataset[()] = value.encode()
|
||||||
|
|
||||||
|
|
||||||
|
def setup_diagnostics(experiment_file, repository_path):
|
||||||
|
def render_diagnostic(self, diagnostic):
|
||||||
|
message = "Cannot compile {}\n".format(experiment_file) + \
|
||||||
|
_render_diagnostic(diagnostic, colored=False)
|
||||||
|
if repository_path is not None:
|
||||||
|
message = message.replace(repository_path, "<repository>")
|
||||||
|
logging.error(message)
|
||||||
|
|
||||||
|
# This is kind of gross, but 1) we do not have any explicit connection
|
||||||
|
# between the worker and a coredevice.core.Core instance at all,
|
||||||
|
# and 2) the diagnostic engine really ought to be per-Core, since
|
||||||
|
# that's what uses it and the repository path is per-Core.
|
||||||
|
# So I don't know how to implement this properly for now.
|
||||||
|
#
|
||||||
|
# This hack is as good or bad as any other solution that involves
|
||||||
|
# putting inherently local objects (the diagnostic engine) into
|
||||||
|
# global slots, and there isn't any point in making it prettier by
|
||||||
|
# wrapping it in layers of indirection.
|
||||||
|
artiq.coredevice.core._DiagnosticEngine.render_diagnostic = render_diagnostic
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
sys.stdout = LogForwarder()
|
sys.stdout = LogForwarder()
|
||||||
sys.stderr = LogForwarder()
|
sys.stderr = LogForwarder()
|
||||||
|
@ -199,6 +220,8 @@ def main():
|
||||||
repository_path = obj["wd"]
|
repository_path = obj["wd"]
|
||||||
else:
|
else:
|
||||||
experiment_file = expid["file"]
|
experiment_file = expid["file"]
|
||||||
|
repository_path = None
|
||||||
|
setup_diagnostics(experiment_file, repository_path)
|
||||||
exp = get_exp(experiment_file, expid["class_name"])
|
exp = get_exp(experiment_file, expid["class_name"])
|
||||||
device_mgr.virtual_devices["scheduler"].set_run_info(
|
device_mgr.virtual_devices["scheduler"].set_run_info(
|
||||||
rid, obj["pipeline_name"], expid, obj["priority"])
|
rid, obj["pipeline_name"], expid, obj["priority"])
|
||||||
|
@ -230,12 +253,8 @@ def main():
|
||||||
put_object({"action": "completed"})
|
put_object({"action": "completed"})
|
||||||
elif action == "terminate":
|
elif action == "terminate":
|
||||||
break
|
break
|
||||||
except CompileError as exc:
|
except CompileError:
|
||||||
# TODO: This should be replaced with a proper DiagnosticEngine.
|
pass
|
||||||
message = "Cannot compile {}\n".format(experiment_file) + exc.render_string()
|
|
||||||
if repository_path is not None:
|
|
||||||
message = message.replace(repository_path, "<repository>")
|
|
||||||
logging.error(message)
|
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
short_exc_info = type(exc).__name__
|
short_exc_info = type(exc).__name__
|
||||||
exc_str = str(exc)
|
exc_str = str(exc)
|
||||||
|
|
Loading…
Reference in New Issue