logging as of 2022-02-01

Change-Id: I63c681bea9553cd822b214075b163ca6c42fe0cc
This commit is contained in:
2022-02-02 09:54:54 +01:00
parent 05d0cfb193
commit 9109170752
3 changed files with 193 additions and 13 deletions

View File

@ -31,13 +31,21 @@ from secop.datatypes import ArrayOf, BoolType, EnumType, FloatRange, \
IntRange, StatusType, StringType, TextType, TupleOf
from secop.errors import BadValueError, ConfigError, \
ProgrammingError, SECoPError, SilentError, secop_error
from secop.lib import formatException, mkthread
from secop.lib import formatException, mkthread, UniqueObject
from secop.lib.enum import Enum
from secop.params import Accessible, Command, Parameter
from secop.poller import BasicPoller, Poller
from secop.properties import HasProperties, Property
from secop.logging import RemoteLogHandler, add_comlog_handler
Done = object() #: a special return value for a read/write function indicating that the setter is triggered already
class DoneClass:
@classmethod
def __repr__(cls):
return 'Done'
Done = UniqueObject('Done')
class HasAccessibles(HasProperties):
@ -124,20 +132,20 @@ class HasAccessibles(HasProperties):
def wrapped_rfunc(self, pname=pname, rfunc=rfunc):
if rfunc:
self.log.debug("calling %r" % rfunc)
self.log.debug("call read_%s" % pname)
try:
value = rfunc(self)
self.log.debug("rfunc(%s) returned %r" % (pname, value))
self.log.debug("read_%s returned %r" % (pname, value))
if value is Done: # the setter is already triggered
return getattr(self, pname)
except Exception as e:
self.log.debug("rfunc(%s) failed %r" % (pname, e))
self.log.debug("read_%s failed %r" % (pname, e))
self.announceUpdate(pname, None, e)
raise
else:
# return cached value
self.log.debug("rfunc(%s): return cached value" % pname)
value = self.accessibles[pname].value
self.log.debug("return cached %s = %r" % (pname, value))
setattr(self, pname, value) # important! trigger the setter
return value
@ -158,16 +166,19 @@ class HasAccessibles(HasProperties):
if not wrapped:
def wrapped_wfunc(self, value, pname=pname, wfunc=wfunc):
self.log.debug("check validity of %s = %r" % (pname, value))
pobj = self.accessibles[pname]
value = pobj.datatype(value)
if wfunc:
self.log.debug('calling %s %r(%r)' % (wfunc.__name__, wfunc, value))
self.log.debug("check and call write_%s(%r)" % (pname, value))
value = pobj.datatype(value)
returned_value = wfunc(self, value)
self.log.debug('write_%s returned %r' % (pname, returned_value))
if returned_value is Done: # the setter is already triggered
return getattr(self, pname)
if returned_value is not None: # goodie: accept missing return value
value = returned_value
else:
self.log.debug("check %s = %r" % (pname, value))
value = pobj.datatype(value)
setattr(self, pname, value)
return value
@ -176,11 +187,17 @@ class HasAccessibles(HasProperties):
setattr(cls, 'write_' + pname, wrapped_wfunc)
wrapped_wfunc.__wrapped__ = True
# check information about Command's
# check for programming errors
for attrname in cls.__dict__:
if attrname.startswith('do_'):
prefix, _, pname = attrname.partition('_')
if not pname:
continue
if prefix == 'do':
raise ProgrammingError('%r: old style command %r not supported anymore'
% (cls.__name__, attrname))
elif prefix in ('read', 'write') and not isinstance(accessibles.get(pname), Parameter):
raise ProgrammingError('%s.%s defined, but %r is no parameter'
% (cls.__name__, attrname, pname))
res = {}
# collect info about properties
@ -434,6 +451,10 @@ class Module(HasAccessibles):
errors.append('%s: %s' % (aname, e))
if errors:
raise ConfigError(errors)
self.remoteLogHandler = None
self._earlyInitDone = False
self._initModuleDone = False
self._startModuleDone = False
# helper cfg-editor
def __iter__(self):
@ -579,6 +600,11 @@ class Module(HasAccessibles):
started_callback()
self.startModuleDone = True
def setRemoteLogging(self, conn, level):
if self.remoteLogHandler is None:
self.remoteLogHandler = RemoteLogHandler(self)
self.remoteLogHandler.set_conn_level(conn, level)
class Readable(Module):
"""basic readable module"""
@ -697,6 +723,10 @@ class Drivable(Writable):
class Communicator(Module):
"""basic abstract communication module"""
def initModule(self):
super().initModule()
add_comlog_handler(self)
@Command(StringType(), result=StringType())
def communicate(self, command):
"""communicate command
@ -708,7 +738,7 @@ class Communicator(Module):
class Attached(Property):
"""a special property, defining an attached modle
"""a special property, defining an attached module
assign a module name to this property in the cfg file,
and the server will create an attribute with this module