frappy_psi.sea: avoid error on import

the previous code raised an error when generalConfig.init() was
not called before importing. defer evaluation of seaconfdir to
the time it is used

+ use updateItem instead of updateEvent to avoid pylint complaint

Change-Id: I0da0891a8d4091102d2a149705f5546e2f6fd187
Reviewed-on: https://forge.frm2.tum.de/review/c/secop/frappy/+/34813
Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de>
Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
zolliker 2024-10-16 10:30:23 +02:00
parent 025eb5fff5
commit 73a54dfc44

View File

@ -41,7 +41,7 @@ from frappy.datatypes import ArrayOf, BoolType, \
EnumType, FloatRange, IntRange, StringType, StatusType EnumType, FloatRange, IntRange, StringType, StatusType
from frappy.core import IDLE, BUSY, WARN, ERROR, DISABLED from frappy.core import IDLE, BUSY, WARN, ERROR, DISABLED
from frappy.errors import ConfigError, HardwareError, ReadFailedError, CommunicationFailedError from frappy.errors import ConfigError, HardwareError, ReadFailedError, CommunicationFailedError
from frappy.lib import generalConfig, mkthread from frappy.lib import generalConfig, mkthread, lazy_property
from frappy.lib.asynconn import AsynConn, ConnectionClosed from frappy.lib.asynconn import AsynConn, ConnectionClosed
from frappy.modulebase import Done from frappy.modulebase import Done
from frappy.modules import Attached, Command, Drivable, \ from frappy.modules import Attached, Command, Drivable, \
@ -72,15 +72,8 @@ SERVICE_NAMES = {
'addon': 'addons', 'addon': 'addons',
} }
SEA_DIR = Path('~/sea').expanduser() SEA_DIR = Path('~/sea').expanduser()
seaconfdir = os.environ.get('FRAPPY_SEA_DIR')
if seaconfdir is None or not Path(seaconfdir).expanduser().absolute().exists():
for confdir in generalConfig.confdir:
seaconfdir = confdir / 'sea'
if seaconfdir.exists():
break
else:
seaconfdir = Path(seaconfdir).expanduser().absolute()
def get_sea_port(instance): def get_sea_port(instance):
@ -98,6 +91,23 @@ def get_sea_port(instance):
return None return None
class SeaConfig:
@lazy_property
def dir(self):
seaconfdir = os.environ.get('FRAPPY_SEA_DIR')
if seaconfdir is None or not Path(seaconfdir).expanduser().absolute().exists():
for confdir in generalConfig.confdir:
seaconfdir = confdir / 'sea'
if seaconfdir.exists():
break
else:
seaconfdir = Path(seaconfdir).expanduser().absolute()
return seaconfdir
seaconfig = SeaConfig()
class SeaClient(ProxyClient, Module): class SeaClient(ProxyClient, Module):
"""connection to SEA""" """connection to SEA"""
@ -151,7 +161,7 @@ class SeaClient(ProxyClient, Module):
self.objects.add(obj) self.objects.add(obj)
for k, v in module.path2param.items(): for k, v in module.path2param.items():
self.path2param.setdefault(k, []).extend(v) self.path2param.setdefault(k, []).extend(v)
self.register_callback(module.name, module.updateEvent) self.register_callback(module.name, module.updateItem)
def _connect(self): def _connect(self):
try: try:
@ -377,7 +387,7 @@ class SeaConfigCreator(SeaClient):
stripped, _, ext = filename.rpartition('.') stripped, _, ext = filename.rpartition('.')
service = SERVICE_NAMES[ext] service = SERVICE_NAMES[ext]
seaconn = 'sea_' + service seaconn = 'sea_' + service
cfgfile = seaconfdir / (stripped + '_cfg.py') cfgfile = seaconfig.dir / (stripped + '_cfg.py')
with cfgfile.open('w', encoding='utf-8') as fp: with cfgfile.open('w', encoding='utf-8') as fp:
fp.write(CFG_HEADER % {'config': filename, 'seaconn': seaconn, 'service': service, fp.write(CFG_HEADER % {'config': filename, 'seaconn': seaconn, 'service': service,
'nodedescr': description.get(filename, filename)}) 'nodedescr': description.get(filename, filename)})
@ -385,7 +395,7 @@ class SeaConfigCreator(SeaClient):
fp.write(CFG_MODULE % {'modcls': modcls[obj], 'module': obj, 'seaconn': seaconn}) fp.write(CFG_MODULE % {'modcls': modcls[obj], 'module': obj, 'seaconn': seaconn})
content = json.dumps(descr).replace('}, {', '},\n{').replace('[{', '[\n{').replace('}]}, ', '}]},\n\n') content = json.dumps(descr).replace('}, {', '},\n{').replace('[{', '[\n{').replace('}]}, ', '}]},\n\n')
result.append('%s\n' % cfgfile) result.append('%s\n' % cfgfile)
fpath = seaconfdir / (filename + '.json') fpath = seaconfig.dir / (filename + '.json')
fpath.write_text(content + '\n', encoding='utf-8') fpath.write_text(content + '\n', encoding='utf-8')
result.append('%s: %s' % (filename, ','.join(n for n in descr))) result.append('%s: %s' % (filename, ','.join(n for n in descr)))
raise SystemExit('; '.join(result)) raise SystemExit('; '.join(result))
@ -484,7 +494,7 @@ class SeaModule(Module):
cfgdict['description'] = '%s@%s%s' % ( cfgdict['description'] = '%s@%s%s' % (
name, json_file, '' if rel_paths == '.' else f' (rel_paths={rel_paths})') name, json_file, '' if rel_paths == '.' else f' (rel_paths={rel_paths})')
with (seaconfdir / json_file).open(encoding='utf-8') as fp: with (seaconfig.dir / json_file).open(encoding='utf-8') as fp:
content = json.load(fp) content = json.load(fp)
descr = content[sea_object] descr = content[sea_object]
if rel_paths == '*' or not rel_paths: if rel_paths == '*' or not rel_paths:
@ -653,12 +663,12 @@ class SeaModule(Module):
result = Module.__new__(newcls) result = Module.__new__(newcls)
return result return result
def updateEvent(self, module, parameter, value, timestamp, readerror): def updateItem(self, module, parameter, item):
upd = getattr(self, 'update_' + parameter, None) upd = getattr(self, 'update_' + parameter, None)
if upd: if upd:
upd(value, timestamp, readerror) upd(*item)
return return
self.announceUpdate(parameter, value, readerror, timestamp) self.announceUpdate(parameter, *item)
def initModule(self): def initModule(self):
self.io.register_obj(self, self.sea_object) self.io.register_obj(self, self.sea_object)
@ -768,9 +778,10 @@ class SeaDrivable(SeaReadable, Drivable):
return IDLE, f'started, but not running' return IDLE, f'started, but not running'
return IDLE, '' return IDLE, ''
def updateTarget(self, module, parameter, value, timestamp, readerror): def update_target(self, module, parameter, item):
if value is not None: # TODO: check if this is needed
self.target = value if item.value is not None:
self.target = item.value
@Command() @Command()
def stop(self): def stop(self):