diff --git a/bin/secop-convert b/bin/secop-convert new file mode 100755 index 0000000..3d2fc8b --- /dev/null +++ b/bin/secop-convert @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +# pylint: disable=invalid-name +# -*- coding: utf-8 -*- +# ***************************************************************************** +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Module authors: +# Enrico Faulhaber +# Alexander Lenz +# +# ***************************************************************************** + +import sys +from os import path + +# Add import path for inplace usage +sys.path.insert(0, path.abspath(path.join(path.dirname(__file__), '..'))) + +from secop.lib import generalConfig +from secop.logging import logger +from secop.server import Server +from secop.core import Attached +from secop.lib.enum import EnumMember + + +def rep(value): + if isinstance(value, EnumMember): + return repr(value.name) + return repr(value) + + +def guess(value): + try: + return '%.16g' % float(value) + except (TypeError, ValueError): + return rep(value) + + +def triplequote(description): + if '\n' in description: + return "'''%s'''" % '\n '.join(description.split('\n')) + else: + return repr(description) + + +def get_value(modobj, pname, value): + prop = modobj.propertyDict.get(pname) + if isinstance(prop, Attached): + return value + clsname = type(modobj).__qualname__ + if pname in {'extra_modules', 'single_module', 'rel_paths', 'json_file'} and clsname.startswith('Sea'): + return value.split() + if pname == 'extra_params' and clsname.startswith('Sim'): + return [v.strip() for v in value.split(',')] + if pname == 'remote_class' and type(modobj).__bases__[0].__name__.startswith('Proxy'): + return value + return getattr(modobj, pname) + + +generalConfig.defaults = {k: True for k in ( + 'lazy_number_validation', 'disable_value_range_check', 'legacy_hasiodev', 'tolerate_poll_property')} +generalConfig.init() +logger.init('off') + + +def main(cfgs): + stats = {} + for name in cfgs: + try: + content = [] + srv = Server(name, logger.log, cfgfiles=name, interface=5000, testonly=True) + if srv.node_cfg.get('class') is not None: + stats[name] = 'skip router' + continue + if 'FRAPPY' in srv.module_cfg: + stats[name] = 'skip genconfig' + continue + for modname, params in srv.module_cfg.items(): + classname = params['class'] + if classname == 'secop_psi.sea.SeaClient': + params['uri'] = 'none' + if 'iodev' in params: + params['io'] = params.pop('iodev') + if '.iodev' in params: + params['io'] = params.pop('.iodev') + node = dict(srv.node_cfg) + if 'description' in node: + content.append('Node(%r,\n %s,' % (node.pop('id'), triplequote(node.pop('description')))) + interface = srv.interface_cfg.get('uri') + if interface: + content.append(' interface=%r,' % interface) + for k, v in node.items(): + content.append(' %s=%s,' % (k, guess(v))) + content.append(')\n') + errors = srv._processCfg() + if errors: + content = ['# %s' % e[:120] for e in errors] + content + stats[name] = ', '.join(errors[:2]) + for modname, modcfg in srv.module_cfg.items(): + modobj = srv.dispatcher._modules.get(modname) + classname = modcfg.pop('class') + content.append('Mod(%r,\n %r,' % (modname, classname)) + description = modcfg.pop('description', None) + if description is not None: + content.append(' %s,' % triplequote(description)) + result = {} + for key, value in modcfg.items(): + pname, _, prop = key.partition('.') + if not pname: + pname, prop = prop, '' + elif pname == 'uri' and value == 'none': + continue + if prop: + pobj = modobj.parameters[pname] if modobj else None + if pobj: + try: + propvalue = rep(getattr(pobj, prop)) + except AttributeError: + propvalue = rep(getattr(pobj.datatype, prop)) + else: + propvalue = guess(value) + else: + prop = 'value' + if modobj: + propvalue = rep(get_value(modobj, pname, value)) + else: + propvalue = guess(value) + result.setdefault(pname, {})[prop] = propvalue + undef = object() + for pname, cfg in result.items(): + value = cfg.pop('value', undef) + if not cfg: + content.append(' %s=%s,' % (pname, value)) + else: + args = ['%s=%s' % kv for kv in cfg.items()] + if value is not undef: + args.insert(0, value) + joined = ' '.join(args) + head = ' %s=Param(' % pname + if len(joined) < 8: + content.append('%s%s),' % (head, ', '.join(args))) + else: + content.append('%s\n %s,\n ),' % (head, ',\n '.join(args))) + content.append(')\n') + with open('%s' % name.replace('.cfg', '_cfg.py'), 'w') as f: + f.write('\n'.join(content)) + stats[name] = '*' if name in stats else '' + except KeyboardInterrupt: + break + except BaseException as e: + stats[name] = repr(e) + if len(cfgs) == 1: + raise + + if len(cfgs) > 1: + with open('convert.log', 'w') as f: + f.write('\n'.join('%s: %s' % kv for kv in stats.items())+'\n') + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/secop/server.py b/secop/server.py index c46a5e0..2d64081 100644 --- a/secop/server.py +++ b/secop/server.py @@ -328,10 +328,12 @@ class Server: sys.stderr.write('\n') if failure_traceback: sys.stderr.write(failure_traceback) + if self._testonly: + return errors sys.exit(1) - if self._testonly: return + self.log.info('waiting for modules being started') start_events.name = None if not start_events.wait(): diff --git a/secop_demo/cryo.py b/secop_demo/cryo.py index 20533af..1fe1a5a 100644 --- a/secop_demo/cryo.py +++ b/secop_demo/cryo.py @@ -31,7 +31,8 @@ from secop.modules import Command, Drivable, Parameter # test custom property (value.test can be changed in config file) from secop.properties import Property -Parameter.propertyDict['test'] = Property('A Property for testing purposes', StringType(), default='', export=True) +class TestParameter(Parameter): + test = Property('A Property for testing purposes', StringType(), default='', export=True) class CryoBase(Drivable): @@ -73,7 +74,7 @@ class Cryostat(CryoBase): target = Parameter("target temperature", datatype=FloatRange(0), default=0, unit="K", readonly=False,) - value = Parameter("regulation temperature", + value = TestParameter("regulation temperature", datatype=FloatRange(0), default=0, unit="K", test='TEST') pid = Parameter("regulation coefficients",