parameter database writeback

This commit is contained in:
Sebastien Bourdeauducq 2015-01-07 17:50:05 +08:00
parent fa441eebda
commit c11708972d
4 changed files with 48 additions and 20 deletions

View File

@ -29,11 +29,14 @@ class Parameter(_AttributeKind):
"""Represents a parameter for ``AutoContext`` to process.
:param default: Default value of the parameter to be used if not found
in database.
in the database.
:param write_db: Writes any modification of the parameter back to the
database.
"""
def __init__(self, default=NoDefault):
def __init__(self, default=NoDefault, write_db=False):
self.default = default
self.write_db = write_db
class AutoContext:
@ -105,6 +108,10 @@ class AutoContext:
self.mvs = mvs
for k, v in kwargs.items():
if hasattr(self, k):
p = getattr(self, k)
if isinstance(p, Parameter) and p.write_db:
self.mvs.register_parameter_wb(self, k)
setattr(self, k, v)
for k in dir(self):
@ -119,6 +126,8 @@ class AutoContext:
" and no MVS present".format(k))
else:
value = self.mvs.get_missing_value(k, v, self)
if isinstance(v, Parameter) and v.write_db:
self.mvs.register_parameter_wb(self, k)
setattr(self, k, value)
self.build()

View File

@ -21,6 +21,8 @@ class DeviceParamSupplier:
self.req_device = req_device
self.req_parameter = req_parameter
self.active_devices = OrderedDict()
# list of (requester, name)
self.parameter_wb = []
def get_missing_value(self, name, kind, requester):
if isinstance(kind, Device):
@ -56,11 +58,20 @@ class DeviceParamSupplier:
else:
raise NotImplementedError
def register_parameter_wb(self, requester, name):
self.parameter_wb.append((requester, name))
def close(self):
"""Closes all active devices, in the opposite order as they were
requested.
Do not use the same ``DeviceParamSupplier`` again after calling
this function.
"""
for dev in reversed(list(self.active_devices.values())):
if hasattr(dev, "close"):
dev.close()
self.active_devices = OrderedDict()
class DeviceParamDB:

View File

@ -37,36 +37,43 @@ def put_object(obj):
sys.__stdout__.flush()
def req_device(name):
put_object({"action": "req_device", "name": name})
obj = get_object()
if obj["status"] == "ok":
return obj["data"]
else:
raise KeyError
class ParentActionError(Exception):
pass
def req_parameter(name):
put_object({"action": "req_parameter", "name": name})
obj = get_object()
if obj["status"] == "ok":
return obj["data"]
def make_parent_action(action, argnames, exception=ParentActionError):
argnames = argnames.split()
def parent_action(*args):
request = {"action": action}
for argname, arg in zip(argnames, args):
request[argname] = arg
put_object(request)
reply = get_object()
if reply["status"] == "ok":
return reply["data"]
else:
raise KeyError
raise exception
return parent_action
req_device = make_parent_action("req_device", "name", KeyError)
req_parameter = make_parent_action("req_parameter", "name", KeyError)
set_parameter = make_parent_action("set_parameter", "name value")
def main():
sys.stdout = sys.stderr
dps = DeviceParamSupplier(req_device, req_parameter)
while True:
obj = get_object()
put_object("ack")
dps = DeviceParamSupplier(req_device, req_parameter)
try:
try:
run(dps, **obj)
for requester, name in dps.parameter_wb:
set_parameter(name, getattr(requester, name))
except Exception:
put_object({"action": "report_completed",
"status": "failed",

View File

@ -36,7 +36,8 @@ def main():
scheduler = Scheduler({
"req_device": dpdb.req_device,
"req_parameter": dpdb.req_parameter
"req_parameter": dpdb.req_parameter,
"set_parameter": dpdb.set_parameter
})
loop.run_until_complete(scheduler.start())
atexit.register(lambda: loop.run_until_complete(scheduler.stop()))