diff --git a/bin/frappy-play b/bin/frappy-play new file mode 100755 index 0000000..7cf1416 --- /dev/null +++ b/bin/frappy-play @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# ***************************************************************************** +# Copyright (c) 2015-2016 by the authors, see LICENSE +# +# 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: +# Markus Zolliker +# +# ***************************************************************************** + +import sys +from os import path + +# Add import path for inplace usage +sys.path.insert(0, path.abspath(path.join(path.dirname(__file__), '..'))) + +from frappy.client.interactive import Console +from frappy.playground import play, USAGE + +if len(sys.argv) > 1: + play(sys.argv[1]) +else: + print(USAGE) + +Console(sys.modules['__main__'].__dict__, 'play') diff --git a/frappy/client/interactive.py b/frappy/client/interactive.py index e400dff..6c92d75 100644 --- a/frappy/client/interactive.py +++ b/frappy/client/interactive.py @@ -409,12 +409,12 @@ class Client(SecopClient): class Console(code.InteractiveConsole): - def __init__(self, local): + def __init__(self, local, name='cli'): super().__init__(local) history = None if readline: try: - history = expanduser('~/.frappy-cli-history') + history = expanduser(f'~/.frappy-{name}-history') readline.read_history_file(history) except FileNotFoundError: pass diff --git a/frappy/playground.py b/frappy/playground.py new file mode 100644 index 0000000..4664ca5 --- /dev/null +++ b/frappy/playground.py @@ -0,0 +1,137 @@ +# -*- 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: +# Markus Zolliker +# +# ***************************************************************************** +"""playground dummy server + +a dummy server for testing drivers interactively + +Remarks: +- the poller is not started +""" + +import sys +from logging import DEBUG, INFO, addLevelName +import mlzlog +from frappy.errors import NoSuchModuleError +from frappy.server import Server +from frappy.config import load_config, Mod as ConfigMod +from frappy.lib import generalConfig + + +USAGE = """create config on the fly: + + Mod('io', ...) + Mod('mf', ...) + play() + +or use a config file: + + play('') + + +and then call methods for trying: + + io.communicate('...') + mf.read_value() + mf.write_target(...) +""" + +OFF = 99 +COMLOG = 15 +addLevelName(COMLOG, 'COMLOG') +assert DEBUG < COMLOG < INFO +LOG_LEVELS = dict(mlzlog.LOGLEVELS, off=OFF, comlog=COMLOG) +LEVEL_NAMES = {v: k for k, v in LOG_LEVELS.items()} + + +main = sys.modules['__main__'] + + +class MainLogger: + def __init__(self): + self.log = None + self.console_handler = None + mlzlog.setLoggerClass(mlzlog.MLZLogger) + assert self.log is None + self.log = mlzlog.log = mlzlog.MLZLogger('') + self.log.setLevel(mlzlog.DEBUG) + self.log.addHandler(mlzlog.ColoredConsoleHandler()) + self.log.handlers[0].setLevel(LOG_LEVELS['comlog']) + + +class Dispatcher: + def __init__(self, name, log, opts, srv): + self.log = log + self._modules = {} + + def announce_update(self, modulename, pname, pobj): + if pobj.readerror: + value = repr(pobj.readerror) + else: + value = pobj.value + self.log.info('%s:%s %r', modulename, pname, value) + + def register_module(self, moduleobj, modulename, export=True): + setattr(main, modulename, moduleobj) + self._modules[modulename] = moduleobj + + def get_module(self, modulename): + if modulename in self._modules: + return self._modules[modulename] + raise NoSuchModuleError(f'Module {modulename!r} does not exist on this SEC-Node!') + + +logger = MainLogger() + + +class Playground(Server): + def __init__(self, **kwds): # pylint: disable=super-init-not-called + for modname, cfg in kwds.items(): + cfg.setdefault('description', modname) + self.log = logger.log + self.node_cfg = {'cls': 'frappy.playground.Dispatcher', 'name': 'playground'} + self._testonly = True # stops before calling startModule + self._cfgfiles = 'main' + self.module_cfg = {} + + def __call__(self, cfgfiles=None): + if cfgfiles: + if not generalConfig.initialized: + generalConfig.init() + merged_cfg = load_config(cfgfiles, self.log) + merged_cfg.pop('node', None) + self.module_cfg = merged_cfg + self._processCfg() + + +play = Playground() + + +def Mod(name, cls, description=None, **kwds): + """like Mod() in config files, but description may be omitted""" + description = description or name # be lazy: fix missing description + mod = ConfigMod(name, cls, description, **kwds) + play.module_cfg[mod.pop('name')] = mod + + +def loglevel(level): + """set log level (COMLOG by default)""" + logger.log.handlers[0].setLevel(LOG_LEVELS.get(level, level)) diff --git a/frappy_psi/SR_7270.py b/frappy_psi/SR_7270.py index fea4f1c..0111e68 100644 --- a/frappy_psi/SR_7270.py +++ b/frappy_psi/SR_7270.py @@ -28,7 +28,7 @@ class SR7270(StringIO): end_of_line = b'\x00' def communicate(self, command): # remove dash from terminator - reply = StringIO.communicate(self, command) + reply = super().communicate(command) status = self._conn.readbytes(2, 0.1) # get the 2 status bytes return reply + ';%d;%d' % tuple(status)