improve interactive client

- remove irrelevant traceback on remote errors
- add run() function to execute scripts
- when started with bin/frappy-cli, use separate namespace

Change-Id: Ic808a76fa76ecd8d814d52b15a6d7d2203c6a2f3
Reviewed-on: https://forge.frm2.tum.de/review/c/secop/frappy/+/30957
Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de>
Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
This commit is contained in:
2023-04-13 16:02:43 +02:00
parent 5784aa0f5d
commit 748ea1400a
3 changed files with 110 additions and 65 deletions

View File

@ -23,8 +23,6 @@
#
# *****************************************************************************
from __future__ import print_function
import sys
import argparse
from os import path
@ -32,7 +30,7 @@ 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 Client, watch, Console
from frappy.client.interactive import Client, Console, clientenv, run
def parseArgv(argv):
@ -49,58 +47,56 @@ def parseArgv(argv):
return parser.parse_args(argv)
_USAGE = """
USAGE = """
Usage:
%s
{client_assign}
# for all SECoP modules objects are created in the main namespace
<module> # list all parameters
<module>.<param> = <value> # change parameter
<module>(<target>) # set target and wait until not busy
# 'status' and 'value' changes are shown every 1 sec
%s.mininterval = 0.2 # change minimal update interval to 0.2 sec (default is 1 second)
watch(T) # watch changes of T.status and T.value (stop with ctrl-C)
watch(T='status target') # watch status and target parameters
watch(io, T=True) # watch io and all parameters of T
"""
_CLIENT_USAGE = """
c = Client('localhost:5000')
"""
Client.show_usage = False
<module> # list all parameters
<module>.<param> = <value> # change parameter
<module>(<target>) # set target and wait until not busy
# 'status' and 'value' changes are shown every 1 sec
{client_name}.mininterval = 0.2 # change minimal update interval to 0.2 s (default is 1 s)
watch(T) # watch changes of T.status and T.value (stop with ctrl-C)
watch(T='status target') # watch status and target parameters
watch(io, T=True) # watch io and all parameters of T
{tail}"""
args = parseArgv(sys.argv[1:])
if not args.node:
_usage_args = ("\ncli = Client('localhost:5000')\n", 'cli')
usage_args = {
'client_assign': "\ncli = Client('localhost:5000')\n",
'client_name': 'cli'}
success = True
else:
_usage_args = ('', '_c0')
usage_args = {
'client_assign': '',
'client_name': '_c0'}
success = False
for _idx, _node in enumerate(args.node):
_client_name = '_c%d' % _idx
clientenv.init()
for idx, node in enumerate(args.node):
client_name = '_c%d' % idx
try:
setattr(sys.modules['__main__'], _client_name, Client(_node, name=_client_name))
clientenv.namespace[client_name] = Client(node, name=client_name)
success = True
except Exception as e:
print(repr(e))
run_error = ''
file_success = False
try:
for file in args.include:
with open(file, 'r') as f:
exec(f.read())
run(file)
file_success = True
except Exception as e:
print('Error while executing %s: %s' % (file, e))
run_error = f'\n{clientenv.short_traceback()}'
if success:
if args.include and file_success and args.only_execute:
print('skipping interactive mode')
exit()
print(_USAGE % _usage_args)
Console(sys.modules['__main__'].__dict__)
print(USAGE.format(tail=run_error, **usage_args))
Console()

View File

@ -36,4 +36,4 @@ if len(sys.argv) > 1:
else:
print(USAGE)
Console(sys.modules['__main__'].__dict__, 'play')
Console('play', sys.modules['__main__'].__dict__)