From 7f9a18094678f42f1292b273a5f0b6832cd18cec Mon Sep 17 00:00:00 2001 From: whitequark Date: Tue, 26 Jan 2016 23:23:35 +0000 Subject: [PATCH 01/19] Fix typo. --- artiq/coredevice/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/coredevice/core.py b/artiq/coredevice/core.py index 0cf49b27c..3705e5155 100644 --- a/artiq/coredevice/core.py +++ b/artiq/coredevice/core.py @@ -19,7 +19,7 @@ from artiq.coredevice import exceptions def _render_diagnostic(diagnostic, colored): def shorten_path(path): return path.replace(artiq_dir, "") - lines = [shorten_path(path) for path in diagnostic.render(colored)] + lines = [shorten_path(path) for path in diagnostic.render(colored=colored)] return "\n".join(lines) class _DiagnosticEngine(diagnostic.Engine): From 0acc86b3b39a8169dfb6fc5094858cd34aef017f Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 27 Jan 2016 02:10:15 +0000 Subject: [PATCH 02/19] transforms.iodelay_estimator: make diagnostics much more clear. --- .../compiler/transforms/iodelay_estimator.py | 44 ++++++++++++------- artiq/test/lit/iodelay/error_argument.py | 12 +++++ artiq/test/lit/iodelay/error_arith.py | 10 ++--- artiq/test/lit/iodelay/error_builtinfn.py | 4 +- artiq/test/lit/iodelay/error_call_nested.py | 2 +- artiq/test/lit/iodelay/error_call_subst.py | 2 +- artiq/test/lit/iodelay/error_for.py | 2 +- artiq/test/lit/iodelay/error_goto.py | 4 +- artiq/test/lit/iodelay/error_iterable.py | 10 +++++ 9 files changed, 63 insertions(+), 27 deletions(-) create mode 100644 artiq/test/lit/iodelay/error_argument.py create mode 100644 artiq/test/lit/iodelay/error_iterable.py diff --git a/artiq/compiler/transforms/iodelay_estimator.py b/artiq/compiler/transforms/iodelay_estimator.py index 163093bb9..5ba867cc8 100644 --- a/artiq/compiler/transforms/iodelay_estimator.py +++ b/artiq/compiler/transforms/iodelay_estimator.py @@ -24,11 +24,11 @@ class IODelayEstimator(algorithm.Visitor): self.current_goto = None self.current_return = None - def evaluate(self, node, abort): + def evaluate(self, node, abort, context): if isinstance(node, asttyped.NumT): return iodelay.Const(node.n) elif isinstance(node, asttyped.CoerceT): - return self.evaluate(node.value, abort) + return self.evaluate(node.value, abort, context) elif isinstance(node, asttyped.NameT): if self.current_args is None: note = diagnostic.Diagnostic("note", @@ -48,8 +48,8 @@ class IODelayEstimator(algorithm.Visitor): ] abort(notes) elif isinstance(node, asttyped.BinOpT): - lhs = self.evaluate(node.left, abort) - rhs = self.evaluate(node.right, abort) + lhs = self.evaluate(node.left, abort, context) + rhs = self.evaluate(node.right, abort, context) if isinstance(node.op, ast.Add): return lhs + rhs elif isinstance(node.op, ast.Sub): @@ -62,12 +62,14 @@ class IODelayEstimator(algorithm.Visitor): return lhs // rhs else: note = diagnostic.Diagnostic("note", - "this operator is not supported", {}, + "this operator is not supported {context}", + {"context": context}, node.op.loc) abort([note]) else: note = diagnostic.Diagnostic("note", - "this expression is not supported", {}, + "this expression is not supported {context}", + {"context": context}, node.loc) abort([note]) @@ -143,14 +145,14 @@ class IODelayEstimator(algorithm.Visitor): def visit_LambdaT(self, node): self.visit_function(node.args, node.body, node.type.find(), node.loc) - def get_iterable_length(self, node): + def get_iterable_length(self, node, context): def abort(notes): self.abort("for statement cannot be interleaved because " - "trip count is indeterminate", + "iteration count is indeterminate", node.loc, notes) def evaluate(node): - return self.evaluate(node, abort) + return self.evaluate(node, abort, context) if isinstance(node, asttyped.CallT) and types.is_builtin(node.func.type, "range"): range_min, range_max, range_step = iodelay.Const(0), None, iodelay.Const(1) @@ -177,10 +179,11 @@ class IODelayEstimator(algorithm.Visitor): self.current_delay = old_delay else: if self.current_goto is not None: - self.abort("loop trip count is indeterminate because of control flow", + self.abort("loop iteration count is indeterminate because of control flow", self.current_goto.loc) - node.trip_count = self.get_iterable_length(node.iter).fold() + context = "in an iterable used in a for loop that is being interleaved" + node.trip_count = self.get_iterable_length(node.iter, context).fold() node.trip_interval = self.current_delay.fold() self.current_delay = old_delay + node.trip_interval * node.trip_count self.current_goto = old_goto @@ -231,6 +234,10 @@ class IODelayEstimator(algorithm.Visitor): # Interleave failures inside `with` statements are hard failures, # since there's no chance that the code will never actually execute # inside a `with` statement after all. + note = diagnostic.Diagnostic("note", + "while interleaving this 'with parallel:' statement", {}, + node.loc) + error.cause.notes += [note] self.engine.process(error.cause) flow_stmt = None @@ -258,15 +265,17 @@ class IODelayEstimator(algorithm.Visitor): def visit_CallT(self, node): typ = node.func.type.find() def abort(notes): - self.abort("this call cannot be interleaved because " + self.abort("call cannot be interleaved because " "an argument cannot be statically evaluated", node.loc, notes) if types.is_builtin(typ, "delay"): - value = self.evaluate(node.args[0], abort=abort) + value = self.evaluate(node.args[0], abort=abort, + context="as an argument for delay()") call_delay = iodelay.SToMU(value, ref_period=self.ref_period) elif types.is_builtin(typ, "delay_mu"): - value = self.evaluate(node.args[0], abort=abort) + value = self.evaluate(node.args[0], abort=abort, + context="as an argument for delay_mu()") call_delay = value elif not types.is_builtin(typ): if types.is_function(typ): @@ -297,7 +306,12 @@ class IODelayEstimator(algorithm.Visitor): args[arg_name] = arg_node free_vars = delay.duration.free_vars() - node.arg_exprs = { arg: self.evaluate(args[arg], abort=abort) for arg in free_vars } + node.arg_exprs = { + arg: self.evaluate(args[arg], abort=abort, + context="in the expression for argument '{}' " + "that affects I/O delay".format(arg)) + for arg in free_vars + } call_delay = delay.duration.fold(node.arg_exprs) else: assert False diff --git a/artiq/test/lit/iodelay/error_argument.py b/artiq/test/lit/iodelay/error_argument.py new file mode 100644 index 000000000..f92dd559d --- /dev/null +++ b/artiq/test/lit/iodelay/error_argument.py @@ -0,0 +1,12 @@ +# RUN: %python -m artiq.compiler.testbench.signature +diag +delay %s >%t +# RUN: OutputCheck %s --file-to-check=%t + +def f(x): + delay_mu(x) + +x = 1 + +def g(): + # CHECK-L: ${LINE:+2}: error: call cannot be interleaved because an argument cannot be statically evaluated + # CHECK-L: ${LINE:+1}: note: this expression is not supported in the expression for argument 'x' that affects I/O delay + f(x if True else x) diff --git a/artiq/test/lit/iodelay/error_arith.py b/artiq/test/lit/iodelay/error_arith.py index 54e30aa24..6a4c9f0c1 100644 --- a/artiq/test/lit/iodelay/error_arith.py +++ b/artiq/test/lit/iodelay/error_arith.py @@ -3,19 +3,19 @@ def f(a): b = 1.0 - # CHECK-L: ${LINE:+3}: error: this call cannot be interleaved + # CHECK-L: ${LINE:+3}: error: call cannot be interleaved # CHECK-L: ${LINE:+2}: note: this variable is not an argument of the innermost function # CHECK-L: ${LINE:-4}: note: only these arguments are in scope of analysis delay(b) def g(): - # CHECK-L: ${LINE:+2}: error: this call cannot be interleaved - # CHECK-L: ${LINE:+1}: note: this operator is not supported + # CHECK-L: ${LINE:+2}: error: call cannot be interleaved + # CHECK-L: ${LINE:+1}: note: this operator is not supported as an argument for delay() delay(2.0**2) def h(): - # CHECK-L: ${LINE:+2}: error: this call cannot be interleaved - # CHECK-L: ${LINE:+1}: note: this expression is not supported + # CHECK-L: ${LINE:+2}: error: call cannot be interleaved + # CHECK-L: ${LINE:+1}: note: this expression is not supported as an argument for delay_mu() delay_mu(1 if False else 2) f(1) diff --git a/artiq/test/lit/iodelay/error_builtinfn.py b/artiq/test/lit/iodelay/error_builtinfn.py index ad44c972c..b1b89a78f 100644 --- a/artiq/test/lit/iodelay/error_builtinfn.py +++ b/artiq/test/lit/iodelay/error_builtinfn.py @@ -3,12 +3,12 @@ def f(): x = 1 - # CHECK-L: ${LINE:+1}: error: this call cannot be interleaved because an argument cannot be statically evaluated + # CHECK-L: ${LINE:+1}: error: call cannot be interleaved because an argument cannot be statically evaluated delay_mu(x) def g(): x = 1.0 - # CHECK-L: ${LINE:+1}: error: this call cannot be interleaved + # CHECK-L: ${LINE:+1}: error: call cannot be interleaved delay(x) diff --git a/artiq/test/lit/iodelay/error_call_nested.py b/artiq/test/lit/iodelay/error_call_nested.py index b283c0917..2c12af9bd 100644 --- a/artiq/test/lit/iodelay/error_call_nested.py +++ b/artiq/test/lit/iodelay/error_call_nested.py @@ -2,7 +2,7 @@ # RUN: OutputCheck %s --file-to-check=%t def f(): - # CHECK-L: ${LINE:+1}: error: this call cannot be interleaved + # CHECK-L: ${LINE:+1}: error: call cannot be interleaved delay(1.0**2) def g(): diff --git a/artiq/test/lit/iodelay/error_call_subst.py b/artiq/test/lit/iodelay/error_call_subst.py index 62c6bb29a..0d1ba0843 100644 --- a/artiq/test/lit/iodelay/error_call_subst.py +++ b/artiq/test/lit/iodelay/error_call_subst.py @@ -9,5 +9,5 @@ def pulse(len): def f(): a = 100 - # CHECK-L: ${LINE:+1}: error: this call cannot be interleaved + # CHECK-L: ${LINE:+1}: error: call cannot be interleaved pulse(a) diff --git a/artiq/test/lit/iodelay/error_for.py b/artiq/test/lit/iodelay/error_for.py index 5c5b10ffc..aae5d47f3 100644 --- a/artiq/test/lit/iodelay/error_for.py +++ b/artiq/test/lit/iodelay/error_for.py @@ -3,7 +3,7 @@ def f(): r = range(10) - # CHECK-L: ${LINE:+2}: error: for statement cannot be interleaved because trip count is indeterminate + # CHECK-L: ${LINE:+2}: error: for statement cannot be interleaved because iteration count is indeterminate # CHECK-L: ${LINE:+1}: note: this value is not a constant range literal for _ in r: delay_mu(1) diff --git a/artiq/test/lit/iodelay/error_goto.py b/artiq/test/lit/iodelay/error_goto.py index 02686cd86..714db7610 100644 --- a/artiq/test/lit/iodelay/error_goto.py +++ b/artiq/test/lit/iodelay/error_goto.py @@ -4,11 +4,11 @@ def f(): for _ in range(10): delay_mu(10) - # CHECK-L: ${LINE:+1}: error: loop trip count is indeterminate because of control flow + # CHECK-L: ${LINE:+1}: error: loop iteration count is indeterminate because of control flow break def g(): for _ in range(10): delay_mu(10) - # CHECK-L: ${LINE:+1}: error: loop trip count is indeterminate because of control flow + # CHECK-L: ${LINE:+1}: error: loop iteration count is indeterminate because of control flow continue diff --git a/artiq/test/lit/iodelay/error_iterable.py b/artiq/test/lit/iodelay/error_iterable.py new file mode 100644 index 000000000..6429236db --- /dev/null +++ b/artiq/test/lit/iodelay/error_iterable.py @@ -0,0 +1,10 @@ +# RUN: %python -m artiq.compiler.testbench.signature +diag +delay %s >%t +# RUN: OutputCheck %s --file-to-check=%t + +x = 1 + +def f(): + # CHECK-L: ${LINE:+2}: error: for statement cannot be interleaved because iteration count is indeterminate + # CHECK-L: ${LINE:+1}: note: this expression is not supported in an iterable used in a for loop that is being interleaved + for _ in range(x if True else x): + delay_mu(10) From 5bead8b83f8fb09529c87a024d3c8b134f7fb3b6 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 27 Jan 2016 09:24:54 +0000 Subject: [PATCH 03/19] conda: restrict binutils-or1k-linux dependency to linux. --- conda/artiq/meta.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conda/artiq/meta.yaml b/conda/artiq/meta.yaml index d4f447496..5ef780b86 100644 --- a/conda/artiq/meta.yaml +++ b/conda/artiq/meta.yaml @@ -54,7 +54,7 @@ requirements: - pyqtgraph - pygit2 - aiohttp - - binutils-or1k-linux + - binutils-or1k-linux # [linux] - pythonparser - levenshtein From 000794e7865e4a4459fcdbbc15b89dbde23b09c0 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 10:23:56 +0100 Subject: [PATCH 04/19] try debugging weird unittest failure --- foo | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 foo diff --git a/foo b/foo new file mode 100644 index 000000000..e69de29bb From 9f9a23b89bdc44885b8269b299ca39e1628068a8 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 10:25:15 +0100 Subject: [PATCH 05/19] Revert "try debugging weird unittest failure" This reverts commit 000794e7865e4a4459fcdbbc15b89dbde23b09c0. --- foo | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 foo diff --git a/foo b/foo deleted file mode 100644 index e69de29bb..000000000 From 83fd160614fbabc64009813407d2e7405d4f292a Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 10:26:53 +0100 Subject: [PATCH 06/19] Revert "Revert "test/pipe_ipc: temporarily skip test"" This reverts commit 7a9864b260bfa72ada732c56e516f80f7668094e. --- artiq/test/pipe_ipc.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/artiq/test/pipe_ipc.py b/artiq/test/pipe_ipc.py index b066d4276..971b2ecaa 100644 --- a/artiq/test/pipe_ipc.py +++ b/artiq/test/pipe_ipc.py @@ -6,6 +6,8 @@ import os from artiq.protocols import pipe_ipc +@unittest.skip("temporarily skip b/c buildbot is failing " + "and i would like packages") class IPCCase(unittest.TestCase): def setUp(self): if os.name == "nt": From dce2aac475149fc4e49a8ffc8e2061243f957d33 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 19:18:03 +0100 Subject: [PATCH 07/19] protocols/pipe_ipc: Windows support --- artiq/protocols/pipe_ipc.py | 96 +++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 4 deletions(-) diff --git a/artiq/protocols/pipe_ipc.py b/artiq/protocols/pipe_ipc.py index 910fe93c4..2955bcaf4 100644 --- a/artiq/protocols/pipe_ipc.py +++ b/artiq/protocols/pipe_ipc.py @@ -3,6 +3,9 @@ import asyncio from asyncio.streams import FlowControlMixin +__all__ = ["AsyncioParentComm", "AsyncioChildComm", "ChildComm"] + + class _BaseIO: def write(self, data): self.writer.write(data) @@ -92,10 +95,78 @@ if os.name != "nt": else: # windows - class AsyncioParentComm(_BaseIO): + import itertools + + + _pipe_count = itertools.count() + + + class AsyncioParentComm: + """Requires ProactorEventLoop""" + def __init__(self): + # We cannot use anonymous pipes on Windows, because we do not know + # in advance if the child process wants a handle open in overlapped + # mode or not. + self.address = "\\\\.\\pipe\\artiq-{}-{}".format(os.getpid(), + next(_pipe_count)) + self.server = None + self.ready = asyncio.Event() + self.write_buffer = b"" + + def get_address(self): + return self.address + async def _autoclose(self): await self.process.wait() - self.writer.close() + if self.server is not None: + self.server[0].close() + self.server = None + if self.ready.is_set(): + self.writer.close() + + async def create_subprocess(self, *args, **kwargs): + loop = asyncio.get_event_loop() + + def factory(): + reader = asyncio.StreamReader(loop=loop) + protocol = asyncio.StreamReaderProtocol(reader, + self._child_connected, + loop=loop) + return protocol + self.server = await loop.start_serving_pipe( + factory, self.address) + + self.process = await asyncio.create_subprocess_exec( + *args, **kwargs) + asyncio.ensure_future(self._autoclose()) + + def _child_connected(self, reader, writer): + self.server[0].close() + self.server = None + self.reader = reader + self.writer = writer + if self.write_buffer: + self.writer.write(self.write_buffer) + self.write_buffer = b"" + self.ready.set() + + def write(self, data): + if self.ready.is_set(): + self.writer.write(data) + else: + self.write_buffer += data + + async def drain(self): + await self.ready.wait() + await self.writer.drain() + + async def readline(self): + await self.ready.wait() + return await self.reader.readline() + + async def read(self, n): + await self.ready.wait() + return await self.reader.read(n) class AsyncioChildComm(_BaseIO): @@ -109,9 +180,26 @@ else: # windows reader_protocol = asyncio.StreamReaderProtocol( self.reader, loop=loop) transport, _ = await loop.create_pipe_connection( - self.address, lambda: reader_protocol) + lambda: reader_protocol, self.address) self.writer = asyncio.StreamWriter(transport, reader_protocol, self.reader, loop) + def close(self): + self.writer.close() + + class ChildComm: - pass + def __init__(self, address): + self.f = open(address, "a+b", 0) + + def read(self, n): + return self.f.read(n) + + def readline(self): + return self.f.readline() + + def write(self, data): + return self.f.write(data) + + def close(self): + self.f.close() From 79c0488ff1b3c7c773b6c933b82f38d5543c96de Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 19:19:47 +0100 Subject: [PATCH 08/19] protocols/asyncio_server: minor cleanup --- artiq/protocols/asyncio_server.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/artiq/protocols/asyncio_server.py b/artiq/protocols/asyncio_server.py index a2425137f..70b6eb194 100644 --- a/artiq/protocols/asyncio_server.py +++ b/artiq/protocols/asyncio_server.py @@ -7,7 +7,6 @@ class AsyncioServer: Users of this class must derive from it and define the ``_handle_connection_cr`` method and coroutine. - """ def __init__(self): self._client_tasks = set() @@ -23,15 +22,12 @@ class AsyncioServer: :param host: Bind address of the server (see ``asyncio.start_server`` from the Python standard library). :param port: TCP port to bind to. - """ self.server = await asyncio.start_server(self._handle_connection, host, port) async def stop(self): - """Stops the server. - - """ + """Stops the server.""" wait_for = copy(self._client_tasks) for task in self._client_tasks: task.cancel() @@ -48,6 +44,6 @@ class AsyncioServer: self._client_tasks.remove(task) def _handle_connection(self, reader, writer): - task = asyncio.Task(self._handle_connection_cr(reader, writer)) + task = asyncio.ensure_future(self._handle_connection_cr(reader, writer)) self._client_tasks.add(task) task.add_done_callback(self._client_done) From 3d9fc7a51f188e5ae192d4f1a84af178f1a2d3e5 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 19:20:04 +0100 Subject: [PATCH 09/19] test/pipe_ipc: re-enable --- artiq/test/pipe_ipc.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/artiq/test/pipe_ipc.py b/artiq/test/pipe_ipc.py index 971b2ecaa..b066d4276 100644 --- a/artiq/test/pipe_ipc.py +++ b/artiq/test/pipe_ipc.py @@ -6,8 +6,6 @@ import os from artiq.protocols import pipe_ipc -@unittest.skip("temporarily skip b/c buildbot is failing " - "and i would like packages") class IPCCase(unittest.TestCase): def setUp(self): if os.name == "nt": From 590354dbc84fc1c93844c17b4129136fbc6eee15 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 20:43:42 +0100 Subject: [PATCH 10/19] pyon: handle \r --- artiq/protocols/pyon.py | 5 ++++- artiq/test/serialization.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/artiq/protocols/pyon.py b/artiq/protocols/pyon.py index 8c4afbbdc..238ff2198 100644 --- a/artiq/protocols/pyon.py +++ b/artiq/protocols/pyon.py @@ -74,7 +74,10 @@ class _Encoder: def encode_str(self, x): # Do not use repr() for JSON compatibility. - tt = {ord("\""): "\\\"", ord("\\"): "\\\\", ord("\n"): "\\n"} + tt = { + ord("\""): "\\\"", ord("\\"): "\\\\", + ord("\n"): "\\n", ord("\r"): "\\r" + } return "\"" + x.translate(tt) + "\"" def encode_bytes(self, x): diff --git a/artiq/test/serialization.py b/artiq/test/serialization.py index 7bcbed5eb..88cf9b18e 100644 --- a/artiq/test/serialization.py +++ b/artiq/test/serialization.py @@ -26,7 +26,7 @@ class PYON(unittest.TestCase): _json_test_object = { "a": "b", "x": [1, 2, {}], - "foo\nbaz\\qux\"": ["bar", 1.2, {"x": "y"}], + "foo\nbaz\\qux\"\r2": ["bar", 1.2, {"x": "y"}], "bar": [True, False, None] } From 170b438b982632f5274aa0de9e2b15300e16e25c Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 20:45:04 +0100 Subject: [PATCH 11/19] protocols/logging/LogParser: handle Windows CRLF --- artiq/protocols/logging.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/protocols/logging.py b/artiq/protocols/logging.py index b6ddb9bb6..693e58f7d 100644 --- a/artiq/protocols/logging.py +++ b/artiq/protocols/logging.py @@ -78,7 +78,7 @@ class LogParser: entry = (await stream.readline()) if not entry: break - self.line_input(entry[:-1].decode()) + self.line_input(entry.decode().rstrip("\r\n")) except: logger.debug("exception in log forwarding", exc_info=True) break From dca44ef501db83f670243df9179e46f0e1e5804c Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 20:46:25 +0100 Subject: [PATCH 12/19] gui: reduce size of experiment dock --- artiq/gui/experiments.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/gui/experiments.py b/artiq/gui/experiments.py index 9412404b1..be53cb150 100644 --- a/artiq/gui/experiments.py +++ b/artiq/gui/experiments.py @@ -240,7 +240,7 @@ class _ArgumentEditor(QtGui.QTreeWidget): class _ExperimentDock(dockarea.Dock): def __init__(self, manager, expurl): dockarea.Dock.__init__(self, "Exp: " + expurl, closable=True) - self.setMinimumSize(QtCore.QSize(1100, 700)) + self.setMinimumSize(QtCore.QSize(740, 470)) self.layout.setSpacing(5) self.layout.setContentsMargins(5, 5, 5, 5) From cfa4f791e87e664d63d3592c1a0ce7faeba3d097 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 20:51:34 +0100 Subject: [PATCH 13/19] gui: reduce size of log dock --- artiq/gui/log.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/gui/log.py b/artiq/gui/log.py index 4e068f623..474d040c9 100644 --- a/artiq/gui/log.py +++ b/artiq/gui/log.py @@ -147,7 +147,7 @@ class _LogFilterProxyModel(QSortFilterProxyModel): class _LogDock(dockarea.Dock): def __init__(self, manager, name, log_sub): dockarea.Dock.__init__(self, name, label="Log") - self.setMinimumSize(QtCore.QSize(850, 450)) + self.setMinimumSize(QtCore.QSize(720, 250)) grid = LayoutWidget() self.addWidget(grid) From a4fb8f3e53c41ffcba7b29bda53065e9543268a5 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 21:12:22 +0100 Subject: [PATCH 14/19] protocol/sync_struct: Windows also raises ConnectionAbortedError on disconnection --- artiq/protocols/sync_struct.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/protocols/sync_struct.py b/artiq/protocols/sync_struct.py index c80555837..039fb2ac4 100644 --- a/artiq/protocols/sync_struct.py +++ b/artiq/protocols/sync_struct.py @@ -235,7 +235,7 @@ class Publisher(AsyncioServer): await writer.drain() finally: self._recipients[notifier_name].remove(queue) - except (ConnectionResetError, BrokenPipeError): + except (ConnectionResetError, ConnectionAbortedError, BrokenPipeError): # subscribers disconnecting are a normal occurence pass finally: From 5076c85ed63f071a3ca63872e4673bcc6a4ee6ed Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 21:15:22 +0100 Subject: [PATCH 15/19] worker: Windows VMs are slow, increase send_timeout --- artiq/master/worker.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/master/worker.py b/artiq/master/worker.py index c0c5c95a1..fb1752aed 100644 --- a/artiq/master/worker.py +++ b/artiq/master/worker.py @@ -42,7 +42,7 @@ def log_worker_exception(): class Worker: - def __init__(self, handlers=dict(), send_timeout=0.5): + def __init__(self, handlers=dict(), send_timeout=1.0): self.handlers = handlers self.send_timeout = send_timeout From 7aaeb636e4e51d75810cfb148904b6c4ea8047d4 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 21:18:47 +0100 Subject: [PATCH 16/19] gui: reduce size of schedule dock --- artiq/gui/schedule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/gui/schedule.py b/artiq/gui/schedule.py index 466b69098..1bac023c8 100644 --- a/artiq/gui/schedule.py +++ b/artiq/gui/schedule.py @@ -58,7 +58,7 @@ class Model(DictSyncModel): class ScheduleDock(dockarea.Dock): def __init__(self, status_bar, schedule_ctl, schedule_sub): dockarea.Dock.__init__(self, "Schedule") - self.setMinimumSize(QtCore.QSize(850, 300)) + self.setMinimumSize(QtCore.QSize(740, 200)) self.status_bar = status_bar self.schedule_ctl = schedule_ctl From 27c12a5bf447fcbefb0ba5ed8fab432c919944a5 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 21:23:22 +0100 Subject: [PATCH 17/19] protocols/logging,pc_rpc: do not print errors on Windows when clients disconnect --- artiq/protocols/logging.py | 3 +++ artiq/protocols/pc_rpc.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/artiq/protocols/logging.py b/artiq/protocols/logging.py index 693e58f7d..0c600e288 100644 --- a/artiq/protocols/logging.py +++ b/artiq/protocols/logging.py @@ -125,6 +125,9 @@ class Server(AsyncioServer): return source, remainder = linesplit parser.line_input(remainder) + except (ConnectionResetError, ConnectionAbortedError, BrokenPipeError): + # May happens on Windows when client disconnects + pass finally: writer.close() diff --git a/artiq/protocols/pc_rpc.py b/artiq/protocols/pc_rpc.py index 6d9feadb5..d1de343a9 100644 --- a/artiq/protocols/pc_rpc.py +++ b/artiq/protocols/pc_rpc.py @@ -502,6 +502,9 @@ class Server(_AsyncioServer): "message": traceback.format_exc()} line = pyon.encode(obj) + "\n" writer.write(line.encode()) + except (ConnectionResetError, ConnectionAbortedError, BrokenPipeError): + # May happens on Windows when client disconnects + pass finally: writer.close() From ebb959cd50690907abfc79559f9f8fb3cd8f3adf Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 21:25:42 +0100 Subject: [PATCH 18/19] gui: reduce size of console dock --- artiq/gui/console.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/gui/console.py b/artiq/gui/console.py index 99fba1fd6..0ec286d55 100644 --- a/artiq/gui/console.py +++ b/artiq/gui/console.py @@ -17,7 +17,7 @@ The following functions are available: class ConsoleDock(dockarea.Dock): def __init__(self, dataset_sub, dataset_ctl): dockarea.Dock.__init__(self, "Console") - self.setMinimumSize(QtCore.QSize(850, 300)) + self.setMinimumSize(QtCore.QSize(720, 300)) self.dataset_sub = dataset_sub self.dataset_ctl = dataset_ctl ns = { From 022a1ffd0905447e7052ea44852ad9a20744a112 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 27 Jan 2016 21:58:27 +0100 Subject: [PATCH 19/19] gui/experiments: float/bring into focus already open docks when opening experiments --- artiq/gui/experiments.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/artiq/gui/experiments.py b/artiq/gui/experiments.py index be53cb150..a90a06a4f 100644 --- a/artiq/gui/experiments.py +++ b/artiq/gui/experiments.py @@ -488,7 +488,9 @@ class ExperimentManager: def open_experiment(self, expurl): if expurl in self.open_experiments: - return self.open_experiments[expurl] + dock = self.open_experiments[expurl] + self.dock_area.floatDock(dock) + return dock dock = _ExperimentDock(self, expurl) self.open_experiments[expurl] = dock self.dock_area.floatDock(dock)