From 1b122dd8876a4449fa5fc053f07cf7048cfbe891 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 4 Feb 2015 15:06:25 +0800 Subject: [PATCH] sync_struct,gui: refactor Subscriber data distribution to support access to parameter DB from GUI file --- artiq/frontend/artiq_gui.py | 8 ++++++++ artiq/gui/explorer.py | 15 +++++++++------ artiq/gui/parameters.py | 14 +++----------- artiq/gui/tools.py | 6 +----- artiq/protocols/sync_struct.py | 14 ++++++++++---- 5 files changed, 31 insertions(+), 26 deletions(-) diff --git a/artiq/frontend/artiq_gui.py b/artiq/frontend/artiq_gui.py index bf0e006b1..e4e9c0a36 100755 --- a/artiq/frontend/artiq_gui.py +++ b/artiq/frontend/artiq_gui.py @@ -9,6 +9,7 @@ from gi.repository import Gtk from artiq.protocols.file_db import FlatFileDB from artiq.protocols.pc_rpc import AsyncioClient +from artiq.protocols.sync_struct import Subscriber from artiq.gui.tools import LayoutManager from artiq.gui.scheduler import SchedulerWindow from artiq.gui.parameters import ParametersWindow @@ -67,6 +68,13 @@ def main(): atexit.register( lambda: loop.run_until_complete(parameters_win.sub_close())) + parameters_sub = Subscriber("parameters", + parameters_win.init_parameters_store) + loop.run_until_complete( + parameters_sub.connect(args.server, args.port_notify)) + atexit.register( + lambda: loop.run_until_complete(parameters_sub.close())) + def exit(*args): lmgr.save() Gtk.main_quit(*args) diff --git a/artiq/gui/explorer.py b/artiq/gui/explorer.py index 401e3586f..6cb7bf18a 100644 --- a/artiq/gui/explorer.py +++ b/artiq/gui/explorer.py @@ -88,7 +88,8 @@ class ExplorerWindow(Window): @asyncio.coroutine def sub_connect(self, host, port): self.explist_subscriber = Subscriber("explist", - self.init_explist_store) + [self.init_explist_store, + self.init_explist_data]) yield from self.explist_subscriber.connect(host, port) @asyncio.coroutine @@ -102,14 +103,16 @@ class ExplorerWindow(Window): self.pane_contents.show_all() def init_explist_store(self, init): - self.explist_syncer = _ExplistStoreSyncer(self.explist_store, init, - keep_data=True) - return self.explist_syncer + return _ExplistStoreSyncer(self.explist_store, init) + + def init_explist_data(self, init): + self.explist_data = init + return init def explist_row_activated(self, widget, index, column): self.controls = None name = self.explist_store[index][0] - gui_file = self.explist_syncer.data[name]["gui_file"] + gui_file = self.explist_data[name]["gui_file"] if gui_file is None: self.set_pane_contents(Gtk.Label("No GUI controls")) else: @@ -128,7 +131,7 @@ class ExplorerWindow(Window): store, selected = self.explist_tree.get_selection().get_selected() if selected is not None: name = store[selected][0] - data = self.explist_syncer.data[name] + data = self.explist_data[name] if self.controls is None: arguments = {} else: diff --git a/artiq/gui/parameters.py b/artiq/gui/parameters.py index 62604ad92..3e4800ff8 100644 --- a/artiq/gui/parameters.py +++ b/artiq/gui/parameters.py @@ -59,21 +59,13 @@ class ParametersWindow(Window): @asyncio.coroutine def sub_connect(self, host, port): - self.parameters_subscriber = Subscriber("parameters", - self.init_parameters_store) - yield from self.parameters_subscriber.connect(host, port) - try: - self.lastchanges_subscriber = Subscriber( - "parameters_simplehist", self.init_lastchanges_store) - yield from self.lastchanges_subscriber.connect(host, port) - except: - yield from self.parameters_subscriber.close() - raise + self.lastchanges_subscriber = Subscriber( + "parameters_simplehist", self.init_lastchanges_store) + yield from self.lastchanges_subscriber.connect(host, port) @asyncio.coroutine def sub_close(self): yield from self.lastchanges_subscriber.close() - yield from self.parameters_subscriber.close() def init_parameters_store(self, init): return _ParameterStoreSyncer(self.parameters_store, init) diff --git a/artiq/gui/tools.py b/artiq/gui/tools.py index d199498e8..0e6d96b02 100644 --- a/artiq/gui/tools.py +++ b/artiq/gui/tools.py @@ -79,9 +79,7 @@ class ListSyncer: class DictSyncer: - def __init__(self, store, init, keep_data=False): - if keep_data: - self.data = init + def __init__(self, store, init): self.store = store self.store.clear() self.order = [] @@ -115,8 +113,6 @@ class DictSyncer: self.order.insert(j, (key, ord_el)) def __delitem__(self, key): - if hasattr(self, "data"): - del self.data[key] i = self._find_index(key) del self.store[i] del self.order[i] diff --git a/artiq/protocols/sync_struct.py b/artiq/protocols/sync_struct.py index ab1afcd78..b85397d69 100644 --- a/artiq/protocols/sync_struct.py +++ b/artiq/protocols/sync_struct.py @@ -49,13 +49,18 @@ class Subscriber: :param target_builder: A function called during initialization that takes the object received from the publisher and returns the corresponding local structure to use. Can be identity. + Multiple functions can be specified in a list for the ``Subscriber`` + to update several local objects simultaneously. :param notify_cb: An optional function called every time a mod is received from the publisher. The mod is passed as parameter. """ def __init__(self, notifier_name, target_builder, notify_cb=None): self.notifier_name = notifier_name - self.target_builder = target_builder + if isinstance(target_builder, list): + self.target_builders = target_builder + else: + self.target_builders = [target_builder] self.notify_cb = notify_cb @asyncio.coroutine @@ -87,7 +92,7 @@ class Subscriber: @asyncio.coroutine def _receive_cr(self): - target = None + targets = [] while True: line = yield from self._reader.readline() if not line: @@ -95,9 +100,10 @@ class Subscriber: mod = pyon.decode(line.decode()) if mod["action"] == "init": - target = self.target_builder(mod["struct"]) + targets = [tb(mod["struct"]) for tb in self.target_builders] else: - process_mod(target, mod) + for target in targets: + process_mod(target, mod) if self.notify_cb is not None: self.notify_cb(mod)