Remove py2 support
Change-Id: Ieeaeb3b8efcae004e94aea6c1d2703c9782a8650 Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/21320 Tested-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de> Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
@@ -36,7 +36,6 @@ Interface to the modules:
|
||||
- remove_module(modulename_or_obj): removes the module (during shutdown)
|
||||
|
||||
"""
|
||||
from __future__ import division, print_function
|
||||
|
||||
import threading
|
||||
from collections import OrderedDict
|
||||
@@ -50,12 +49,6 @@ from secop.protocol.messages import COMMANDREPLY, DESCRIPTIONREPLY, \
|
||||
DISABLEEVENTSREPLY, ENABLEEVENTSREPLY, ERRORPREFIX, EVENTREPLY, \
|
||||
HEARTBEATREPLY, IDENTREPLY, IDENTREQUEST, READREPLY, WRITEREPLY
|
||||
|
||||
try:
|
||||
unicode
|
||||
except NameError:
|
||||
# no unicode on py3
|
||||
unicode = str # pylint: disable=redefined-builtin
|
||||
|
||||
|
||||
class Dispatcher(object):
|
||||
|
||||
@@ -101,7 +94,7 @@ class Dispatcher(object):
|
||||
"""called by modules param setters to notify subscribers of new values
|
||||
"""
|
||||
# argument pname is no longer used here - should we remove it?
|
||||
msg = (EVENTREPLY, u'%s:%s' % (moduleobj.name, pobj.export),
|
||||
msg = (EVENTREPLY, '%s:%s' % (moduleobj.name, pobj.export),
|
||||
[pobj.export_value(), dict(t=pobj.timestamp)])
|
||||
self.broadcast_event(msg)
|
||||
|
||||
@@ -113,7 +106,7 @@ class Dispatcher(object):
|
||||
# argument pname is no longer used here - should we remove it?
|
||||
if not isinstance(err, SECoPError):
|
||||
err = InternalError(err)
|
||||
msg = (ERRORPREFIX + EVENTREPLY, u'%s:%s' % (moduleobj.name, pobj.export),
|
||||
msg = (ERRORPREFIX + EVENTREPLY, '%s:%s' % (moduleobj.name, pobj.export),
|
||||
# error-report !
|
||||
[err.name, repr(err), dict(t=currenttime())])
|
||||
self.broadcast_event(msg)
|
||||
@@ -125,7 +118,7 @@ class Dispatcher(object):
|
||||
if not ':' in eventname:
|
||||
# also remove 'more specific' subscriptions
|
||||
for k, v in self._subscriptions.items():
|
||||
if k.startswith(u'%s:' % eventname):
|
||||
if k.startswith('%s:' % eventname):
|
||||
v.discard(conn)
|
||||
if eventname in self._subscriptions:
|
||||
self._subscriptions[eventname].discard(conn)
|
||||
@@ -143,7 +136,7 @@ class Dispatcher(object):
|
||||
self._active_connections.discard(conn)
|
||||
|
||||
def register_module(self, moduleobj, modulename, export=True):
|
||||
self.log.debug(u'registering module %r as %s (export=%r)' %
|
||||
self.log.debug('registering module %r as %s (export=%r)' %
|
||||
(moduleobj, modulename, export))
|
||||
self._modules[modulename] = moduleobj
|
||||
if export:
|
||||
@@ -154,7 +147,7 @@ class Dispatcher(object):
|
||||
return self._modules[modulename]
|
||||
elif modulename in list(self._modules.values()):
|
||||
return modulename
|
||||
raise NoSuchModuleError(u'Module does not exist on this SEC-Node!')
|
||||
raise NoSuchModuleError('Module does not exist on this SEC-Node!')
|
||||
|
||||
def remove_module(self, modulename_or_obj):
|
||||
moduleobj = self.get_module(modulename_or_obj)
|
||||
@@ -163,7 +156,7 @@ class Dispatcher(object):
|
||||
self._export.remove(modulename)
|
||||
self._modules.pop(modulename)
|
||||
self._subscriptions.pop(modulename, None)
|
||||
for k in [k for k in self._subscriptions if k.startswith(u'%s:' % modulename)]:
|
||||
for k in [kk for kk in self._subscriptions if kk.startswith('%s:' % modulename)]:
|
||||
self._subscriptions.pop(k, None)
|
||||
|
||||
def list_module_names(self):
|
||||
@@ -171,52 +164,52 @@ class Dispatcher(object):
|
||||
return self._export[:]
|
||||
|
||||
def export_accessibles(self, modulename):
|
||||
self.log.debug(u'export_accessibles(%r)' % modulename)
|
||||
self.log.debug('export_accessibles(%r)' % modulename)
|
||||
if modulename in self._export:
|
||||
# omit export=False params!
|
||||
res = OrderedDict()
|
||||
for aobj in self.get_module(modulename).accessibles.values():
|
||||
if aobj.export:
|
||||
res[aobj.export] = aobj.for_export()
|
||||
self.log.debug(u'list accessibles for module %s -> %r' %
|
||||
self.log.debug('list accessibles for module %s -> %r' %
|
||||
(modulename, res))
|
||||
return res
|
||||
self.log.debug(u'-> module is not to be exported!')
|
||||
self.log.debug('-> module is not to be exported!')
|
||||
return OrderedDict()
|
||||
|
||||
def get_descriptive_data(self):
|
||||
"""returns a python object which upon serialisation results in the descriptive data"""
|
||||
# XXX: be lazy and cache this?
|
||||
result = {u'modules': OrderedDict()}
|
||||
result = {'modules': OrderedDict()}
|
||||
for modulename in self._export:
|
||||
module = self.get_module(modulename)
|
||||
if not module.properties.get('export', False):
|
||||
continue
|
||||
# some of these need rework !
|
||||
mod_desc = {u'accessibles': self.export_accessibles(modulename)}
|
||||
mod_desc = {'accessibles': self.export_accessibles(modulename)}
|
||||
mod_desc.update(module.exportProperties())
|
||||
mod_desc.pop('export', False)
|
||||
result[u'modules'][modulename] = mod_desc
|
||||
result[u'equipment_id'] = self.equipment_id
|
||||
result[u'firmware'] = u'FRAPPY - The Python Framework for SECoP'
|
||||
result[u'version'] = u'2019.08'
|
||||
result['modules'][modulename] = mod_desc
|
||||
result['equipment_id'] = self.equipment_id
|
||||
result['firmware'] = 'FRAPPY - The Python Framework for SECoP'
|
||||
result['version'] = '2019.08'
|
||||
result.update(self.nodeprops)
|
||||
return result
|
||||
|
||||
def _execute_command(self, modulename, exportedname, argument=None):
|
||||
moduleobj = self.get_module(modulename)
|
||||
if moduleobj is None:
|
||||
raise NoSuchModuleError(u'Module does not exist on this SEC-Node!')
|
||||
raise NoSuchModuleError('Module does not exist on this SEC-Node!')
|
||||
|
||||
cmdname = moduleobj.commands.exported.get(exportedname, None)
|
||||
if cmdname is None:
|
||||
raise NoSuchCommandError(u'Module has no command %r on this SEC-Node!' % exportedname)
|
||||
raise NoSuchCommandError('Module has no command %r on this SEC-Node!' % exportedname)
|
||||
cmdspec = moduleobj.commands[cmdname]
|
||||
if argument is None and cmdspec.datatype.argument is not None:
|
||||
raise BadValueError(u'Command needs an argument!')
|
||||
raise BadValueError('Command needs an argument!')
|
||||
|
||||
if argument is not None and cmdspec.datatype.argument is None:
|
||||
raise BadValueError(u'Command takes no argument!')
|
||||
raise BadValueError('Command takes no argument!')
|
||||
|
||||
if cmdspec.datatype.argument:
|
||||
# validate!
|
||||
@@ -224,7 +217,7 @@ class Dispatcher(object):
|
||||
|
||||
# now call func
|
||||
# note: exceptions are handled in handle_request, not here!
|
||||
func = getattr(moduleobj, u'do_' + cmdname)
|
||||
func = getattr(moduleobj, 'do_' + cmdname)
|
||||
res = func(argument) if argument else func()
|
||||
|
||||
# pipe through cmdspec.datatype.result
|
||||
@@ -236,20 +229,20 @@ class Dispatcher(object):
|
||||
def _setParameterValue(self, modulename, exportedname, value):
|
||||
moduleobj = self.get_module(modulename)
|
||||
if moduleobj is None:
|
||||
raise NoSuchModuleError(u'Module does not exist on this SEC-Node!')
|
||||
raise NoSuchModuleError('Module does not exist on this SEC-Node!')
|
||||
|
||||
pname = moduleobj.parameters.exported.get(exportedname, None)
|
||||
if pname is None:
|
||||
raise NoSuchParameterError(u'Module has no parameter %r on this SEC-Node!' % exportedname)
|
||||
raise NoSuchParameterError('Module has no parameter %r on this SEC-Node!' % exportedname)
|
||||
pobj = moduleobj.parameters[pname]
|
||||
if pobj.constant is not None:
|
||||
raise ReadOnlyError(u'This parameter is constant and can not be accessed remotely.')
|
||||
raise ReadOnlyError('This parameter is constant and can not be accessed remotely.')
|
||||
if pobj.readonly:
|
||||
raise ReadOnlyError(u'This parameter can not be changed remotely.')
|
||||
raise ReadOnlyError('This parameter can not be changed remotely.')
|
||||
|
||||
# validate!
|
||||
value = pobj.datatype(value)
|
||||
writefunc = getattr(moduleobj, u'write_%s' % pname, None)
|
||||
writefunc = getattr(moduleobj, 'write_%s' % pname, None)
|
||||
# note: exceptions are handled in handle_request, not here!
|
||||
if writefunc:
|
||||
# return value is ignored here, as it is automatically set on the pobj and broadcast
|
||||
@@ -261,18 +254,18 @@ class Dispatcher(object):
|
||||
def _getParameterValue(self, modulename, exportedname):
|
||||
moduleobj = self.get_module(modulename)
|
||||
if moduleobj is None:
|
||||
raise NoSuchModuleError(u'Module does not exist on this SEC-Node!')
|
||||
raise NoSuchModuleError('Module does not exist on this SEC-Node!')
|
||||
|
||||
pname = moduleobj.parameters.exported.get(exportedname, None)
|
||||
if pname is None:
|
||||
raise NoSuchParameterError(u'Module has no parameter %r on this SEC-Node!' % exportedname)
|
||||
raise NoSuchParameterError('Module has no parameter %r on this SEC-Node!' % exportedname)
|
||||
pobj = moduleobj.parameters[pname]
|
||||
if pobj.constant is not None:
|
||||
# really needed? we could just construct a readreply instead....
|
||||
#raise ReadOnlyError(u'This parameter is constant and can not be accessed remotely.')
|
||||
#raise ReadOnlyError('This parameter is constant and can not be accessed remotely.')
|
||||
return pobj.datatype.export_value(pobj.constant)
|
||||
|
||||
readfunc = getattr(moduleobj, u'read_%s' % pname, None)
|
||||
readfunc = getattr(moduleobj, 'read_%s' % pname, None)
|
||||
if readfunc:
|
||||
# should also update the pobj (via the setter from the metaclass)
|
||||
# note: exceptions are handled in handle_request, not here!
|
||||
@@ -288,7 +281,7 @@ class Dispatcher(object):
|
||||
|
||||
will call 'queue_async_reply(data)' on conn or return reply
|
||||
"""
|
||||
self.log.debug(u'Dispatcher: handling msg: %s' % repr(msg))
|
||||
self.log.debug('Dispatcher: handling msg: %s' % repr(msg))
|
||||
|
||||
# play thread safe !
|
||||
# XXX: ONLY ONE REQUEST (per dispatcher) AT A TIME
|
||||
@@ -298,8 +291,8 @@ class Dispatcher(object):
|
||||
if action == IDENTREQUEST:
|
||||
action, specifier, data = '_ident', None, None
|
||||
|
||||
self.log.debug(u'Looking for handle_%s' % action)
|
||||
handler = getattr(self, u'handle_%s' % action, None)
|
||||
self.log.debug('Looking for handle_%s' % action)
|
||||
handler = getattr(self, 'handle_%s' % action, None)
|
||||
|
||||
if handler:
|
||||
return handler(conn, specifier, data)
|
||||
@@ -319,28 +312,28 @@ class Dispatcher(object):
|
||||
def handle_read(self, conn, specifier, data):
|
||||
if data:
|
||||
raise ProtocolError('read requests don\'t take data!')
|
||||
modulename, pname = specifier, u'value'
|
||||
modulename, pname = specifier, 'value'
|
||||
if ':' in specifier:
|
||||
modulename, pname = specifier.split(':', 1)
|
||||
# XXX: trigger polling and force sending event ???
|
||||
return (READREPLY, specifier, list(self._getParameterValue(modulename, pname)))
|
||||
|
||||
def handle_change(self, conn, specifier, data):
|
||||
modulename, pname = specifier, u'value'
|
||||
modulename, pname = specifier, 'value'
|
||||
if ':' in specifier:
|
||||
modulename, pname = specifier.split(u':', 1)
|
||||
modulename, pname = specifier.split(':', 1)
|
||||
return (WRITEREPLY, specifier, list(self._setParameterValue(modulename, pname, data)))
|
||||
|
||||
def handle_do(self, conn, specifier, data):
|
||||
# XXX: should this be done asyncron? we could just return the reply in
|
||||
# that case
|
||||
modulename, cmd = specifier.split(u':', 1)
|
||||
modulename, cmd = specifier.split(':', 1)
|
||||
return (COMMANDREPLY, specifier, list(self._execute_command(modulename, cmd, data)))
|
||||
|
||||
def handle_ping(self, conn, specifier, data):
|
||||
if data:
|
||||
raise ProtocolError('ping requests don\'t take data!')
|
||||
return (HEARTBEATREPLY, specifier, [None, {u't':currenttime()}])
|
||||
return (HEARTBEATREPLY, specifier, [None, {'t':currenttime()}])
|
||||
|
||||
def handle_activate(self, conn, specifier, data):
|
||||
if data:
|
||||
@@ -348,7 +341,7 @@ class Dispatcher(object):
|
||||
if specifier:
|
||||
modulename, exportedname = specifier, None
|
||||
if ':' in specifier:
|
||||
modulename, exportedname = specifier.split(u':', 1)
|
||||
modulename, exportedname = specifier.split(':', 1)
|
||||
if modulename not in self._export:
|
||||
raise NoSuchModuleError('Module does not exist on this SEC-Node!')
|
||||
moduleobj = self.get_module(modulename)
|
||||
@@ -373,7 +366,7 @@ class Dispatcher(object):
|
||||
moduleobj = self._modules.get(modulename, None)
|
||||
if pname:
|
||||
pobj = moduleobj.accessibles[pname]
|
||||
updmsg = (EVENTREPLY, u'%s:%s' % (modulename, pobj.export),
|
||||
updmsg = (EVENTREPLY, '%s:%s' % (modulename, pobj.export),
|
||||
[pobj.export_value(), dict(t=pobj.timestamp)])
|
||||
conn.queue_async_reply(updmsg)
|
||||
continue
|
||||
@@ -383,7 +376,7 @@ class Dispatcher(object):
|
||||
if not pobj.export:
|
||||
continue
|
||||
# can not use announce_update here, as this will send to all clients
|
||||
updmsg = (EVENTREPLY, u'%s:%s' % (modulename, pobj.export),
|
||||
updmsg = (EVENTREPLY, '%s:%s' % (modulename, pobj.export),
|
||||
[pobj.export_value(), dict(t=pobj.timestamp)])
|
||||
conn.queue_async_reply(updmsg)
|
||||
return (ENABLEEVENTSREPLY, specifier, None) if specifier else (ENABLEEVENTSREPLY, None, None)
|
||||
|
||||
@@ -28,7 +28,7 @@ SPACE = b' '
|
||||
def encode_msg_frame(action, specifier=None, data=None):
|
||||
""" encode a msg_tripel into an msg_frame, ready to be sent
|
||||
|
||||
action (and optional specifier) are unicode strings,
|
||||
action (and optional specifier) are str strings,
|
||||
data may be an json-yfied python object"""
|
||||
action = action.encode('utf-8')
|
||||
if specifier is None:
|
||||
@@ -54,7 +54,7 @@ def get_msg(_bytes):
|
||||
|
||||
|
||||
def decode_msg(msg):
|
||||
"""decode the (binary) msg into a (unicode) msg_tripel"""
|
||||
"""decode the (binary) msg into a (str) msg_tripel"""
|
||||
# check for leading/trailing CR and remove it
|
||||
res = msg.split(b' ', 2)
|
||||
action = res[0].decode('utf-8')
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
#
|
||||
# *****************************************************************************
|
||||
"""provides tcp interface to the SECoP Server"""
|
||||
from __future__ import division, print_function
|
||||
|
||||
import collections
|
||||
import socket
|
||||
import sys
|
||||
import socket
|
||||
import collections
|
||||
import socketserver
|
||||
|
||||
from secop.datatypes import StringType, IntRange, BoolType
|
||||
from secop.errors import SECoPError
|
||||
@@ -34,17 +34,10 @@ from secop.protocol.interface import decode_msg, encode_msg_frame, get_msg
|
||||
from secop.protocol.messages import ERRORPREFIX, \
|
||||
HELPREPLY, HELPREQUEST, HelpMessage
|
||||
|
||||
try:
|
||||
import socketserver # py3
|
||||
except ImportError:
|
||||
import SocketServer as socketserver # py2
|
||||
|
||||
|
||||
|
||||
DEF_PORT = 10767
|
||||
MESSAGE_READ_SIZE = 1024
|
||||
|
||||
|
||||
CR = b'\r'
|
||||
SPACE = b' '
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
# *****************************************************************************
|
||||
"""provide a zmq server"""
|
||||
|
||||
from __future__ import division, print_function
|
||||
|
||||
# tbd.
|
||||
|
||||
|
||||
@@ -20,50 +20,49 @@
|
||||
#
|
||||
# *****************************************************************************
|
||||
"""Define SECoP Messages"""
|
||||
from __future__ import division, print_function
|
||||
|
||||
# allowed actions:
|
||||
|
||||
IDENTREQUEST = u'*IDN?' # literal
|
||||
IDENTREQUEST = '*IDN?' # literal
|
||||
# literal! first part is fixed!
|
||||
IDENTREPLY = u'SINE2020&ISSE,SECoP,V2019-08-20,v1.0 RC2'
|
||||
IDENTREPLY = 'SINE2020&ISSE,SECoP,V2019-08-20,v1.0 RC2'
|
||||
|
||||
DESCRIPTIONREQUEST = u'describe' # literal
|
||||
DESCRIPTIONREPLY = u'describing' # +<id> +json
|
||||
DESCRIPTIONREQUEST = 'describe' # literal
|
||||
DESCRIPTIONREPLY = 'describing' # +<id> +json
|
||||
|
||||
ENABLEEVENTSREQUEST = u'activate' # literal + optional spec
|
||||
ENABLEEVENTSREPLY = u'active' # literal + optional spec, is end-of-initial-data-transfer
|
||||
ENABLEEVENTSREQUEST = 'activate' # literal + optional spec
|
||||
ENABLEEVENTSREPLY = 'active' # literal + optional spec, is end-of-initial-data-transfer
|
||||
|
||||
DISABLEEVENTSREQUEST = u'deactivate' # literal + optional spec
|
||||
DISABLEEVENTSREPLY = u'inactive' # literal + optional spec
|
||||
DISABLEEVENTSREQUEST = 'deactivate' # literal + optional spec
|
||||
DISABLEEVENTSREPLY = 'inactive' # literal + optional spec
|
||||
|
||||
COMMANDREQUEST = u'do' # +module:command +json args (if needed)
|
||||
COMMANDREQUEST = 'do' # +module:command +json args (if needed)
|
||||
# +module:command +json args (if needed) # send after the command finished !
|
||||
COMMANDREPLY = u'done'
|
||||
COMMANDREPLY = 'done'
|
||||
|
||||
# +module[:parameter] +json_value
|
||||
WRITEREQUEST = u'change'
|
||||
WRITEREQUEST = 'change'
|
||||
# +module[:parameter] +json_value # send with the read back value
|
||||
WRITEREPLY = u'changed'
|
||||
WRITEREPLY = 'changed'
|
||||
|
||||
# +module[:parameter] +json_value
|
||||
BUFFERREQUEST = u'buffer'
|
||||
BUFFERREQUEST = 'buffer'
|
||||
# +module[:parameter] +json_value # send with the read back value
|
||||
BUFFERREPLY = u'buffered'
|
||||
BUFFERREPLY = 'buffered'
|
||||
|
||||
# +module[:parameter] -> NO direct reply, calls POLL internally!
|
||||
READREQUEST = u'read'
|
||||
READREPLY = u'reply' # See Issue 54
|
||||
READREQUEST = 'read'
|
||||
READREPLY = 'reply' # See Issue 54
|
||||
|
||||
EVENTREPLY = u'update' # +module[:parameter] +json_value (value, qualifiers_as_dict)
|
||||
EVENTREPLY = 'update' # +module[:parameter] +json_value (value, qualifiers_as_dict)
|
||||
|
||||
HEARTBEATREQUEST = u'ping' # +nonce_without_space
|
||||
HEARTBEATREPLY = u'pong' # +nonce_without_space
|
||||
HEARTBEATREQUEST = 'ping' # +nonce_without_space
|
||||
HEARTBEATREPLY = 'pong' # +nonce_without_space
|
||||
|
||||
ERRORPREFIX = u'error_' # + specifier + json_extended_info(error_report)
|
||||
ERRORPREFIX = 'error_' # + specifier + json_extended_info(error_report)
|
||||
|
||||
HELPREQUEST = u'help' # literal
|
||||
HELPREPLY = u'helping' # +line number +json_text
|
||||
HELPREQUEST = 'help' # literal
|
||||
HELPREPLY = 'helping' # +line number +json_text
|
||||
|
||||
# helper mapping to find the REPLY for a REQUEST
|
||||
REQUEST2REPLY = {
|
||||
|
||||
Reference in New Issue
Block a user