sync_struct,gui: refactor Subscriber data distribution to support access to parameter DB from GUI file

This commit is contained in:
Sebastien Bourdeauducq 2015-02-04 15:06:25 +08:00
parent 186aa7fdb7
commit 1b122dd887
5 changed files with 31 additions and 26 deletions

View File

@ -9,6 +9,7 @@ from gi.repository import Gtk
from artiq.protocols.file_db import FlatFileDB from artiq.protocols.file_db import FlatFileDB
from artiq.protocols.pc_rpc import AsyncioClient from artiq.protocols.pc_rpc import AsyncioClient
from artiq.protocols.sync_struct import Subscriber
from artiq.gui.tools import LayoutManager from artiq.gui.tools import LayoutManager
from artiq.gui.scheduler import SchedulerWindow from artiq.gui.scheduler import SchedulerWindow
from artiq.gui.parameters import ParametersWindow from artiq.gui.parameters import ParametersWindow
@ -67,6 +68,13 @@ def main():
atexit.register( atexit.register(
lambda: loop.run_until_complete(parameters_win.sub_close())) 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): def exit(*args):
lmgr.save() lmgr.save()
Gtk.main_quit(*args) Gtk.main_quit(*args)

View File

@ -88,7 +88,8 @@ class ExplorerWindow(Window):
@asyncio.coroutine @asyncio.coroutine
def sub_connect(self, host, port): def sub_connect(self, host, port):
self.explist_subscriber = Subscriber("explist", 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) yield from self.explist_subscriber.connect(host, port)
@asyncio.coroutine @asyncio.coroutine
@ -102,14 +103,16 @@ class ExplorerWindow(Window):
self.pane_contents.show_all() self.pane_contents.show_all()
def init_explist_store(self, init): def init_explist_store(self, init):
self.explist_syncer = _ExplistStoreSyncer(self.explist_store, init, return _ExplistStoreSyncer(self.explist_store, init)
keep_data=True)
return self.explist_syncer def init_explist_data(self, init):
self.explist_data = init
return init
def explist_row_activated(self, widget, index, column): def explist_row_activated(self, widget, index, column):
self.controls = None self.controls = None
name = self.explist_store[index][0] 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: if gui_file is None:
self.set_pane_contents(Gtk.Label("No GUI controls")) self.set_pane_contents(Gtk.Label("No GUI controls"))
else: else:
@ -128,7 +131,7 @@ class ExplorerWindow(Window):
store, selected = self.explist_tree.get_selection().get_selected() store, selected = self.explist_tree.get_selection().get_selected()
if selected is not None: if selected is not None:
name = store[selected][0] name = store[selected][0]
data = self.explist_syncer.data[name] data = self.explist_data[name]
if self.controls is None: if self.controls is None:
arguments = {} arguments = {}
else: else:

View File

@ -59,21 +59,13 @@ class ParametersWindow(Window):
@asyncio.coroutine @asyncio.coroutine
def sub_connect(self, host, port): 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( self.lastchanges_subscriber = Subscriber(
"parameters_simplehist", self.init_lastchanges_store) "parameters_simplehist", self.init_lastchanges_store)
yield from self.lastchanges_subscriber.connect(host, port) yield from self.lastchanges_subscriber.connect(host, port)
except:
yield from self.parameters_subscriber.close()
raise
@asyncio.coroutine @asyncio.coroutine
def sub_close(self): def sub_close(self):
yield from self.lastchanges_subscriber.close() yield from self.lastchanges_subscriber.close()
yield from self.parameters_subscriber.close()
def init_parameters_store(self, init): def init_parameters_store(self, init):
return _ParameterStoreSyncer(self.parameters_store, init) return _ParameterStoreSyncer(self.parameters_store, init)

View File

@ -79,9 +79,7 @@ class ListSyncer:
class DictSyncer: class DictSyncer:
def __init__(self, store, init, keep_data=False): def __init__(self, store, init):
if keep_data:
self.data = init
self.store = store self.store = store
self.store.clear() self.store.clear()
self.order = [] self.order = []
@ -115,8 +113,6 @@ class DictSyncer:
self.order.insert(j, (key, ord_el)) self.order.insert(j, (key, ord_el))
def __delitem__(self, key): def __delitem__(self, key):
if hasattr(self, "data"):
del self.data[key]
i = self._find_index(key) i = self._find_index(key)
del self.store[i] del self.store[i]
del self.order[i] del self.order[i]

View File

@ -49,13 +49,18 @@ class Subscriber:
:param target_builder: A function called during initialization that takes :param target_builder: A function called during initialization that takes
the object received from the publisher and returns the corresponding the object received from the publisher and returns the corresponding
local structure to use. Can be identity. 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 :param notify_cb: An optional function called every time a mod is received
from the publisher. The mod is passed as parameter. from the publisher. The mod is passed as parameter.
""" """
def __init__(self, notifier_name, target_builder, notify_cb=None): def __init__(self, notifier_name, target_builder, notify_cb=None):
self.notifier_name = notifier_name 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 self.notify_cb = notify_cb
@asyncio.coroutine @asyncio.coroutine
@ -87,7 +92,7 @@ class Subscriber:
@asyncio.coroutine @asyncio.coroutine
def _receive_cr(self): def _receive_cr(self):
target = None targets = []
while True: while True:
line = yield from self._reader.readline() line = yield from self._reader.readline()
if not line: if not line:
@ -95,8 +100,9 @@ class Subscriber:
mod = pyon.decode(line.decode()) mod = pyon.decode(line.decode())
if mod["action"] == "init": if mod["action"] == "init":
target = self.target_builder(mod["struct"]) targets = [tb(mod["struct"]) for tb in self.target_builders]
else: else:
for target in targets:
process_mod(target, mod) process_mod(target, mod)
if self.notify_cb is not None: if self.notify_cb is not None: