From adc9a6da71155fd55f3e9600da189970a52442dc Mon Sep 17 00:00:00 2001 From: l_samenv Date: Wed, 3 Mar 2021 14:35:21 +0100 Subject: [PATCH] fixed bugs from syntax migration - a new wrapper for a read function is not only to be created when the a new read method is in the class dict, but also when it is inherited, but not yet wrapped - a handler must not be ignored, when a write method is inherited - a proxy class must not call checkProperties + remove trailing spaces in tutorial_helevel.rst Change-Id: I16024c14232ea200db91a1bc07ec23326219ab68 Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/25093 Tested-by: Jenkins Automated Tests Reviewed-by: Markus Zolliker --- doc/source/tutorial_helevel.rst | 18 +++++++++--------- secop/modules.py | 17 ++++++++++------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/doc/source/tutorial_helevel.rst b/doc/source/tutorial_helevel.rst index f073cf8..77aadea 100644 --- a/doc/source/tutorial_helevel.rst +++ b/doc/source/tutorial_helevel.rst @@ -23,7 +23,7 @@ CCU4 luckily has a very simple and logical protocol: # the most common Frappy classes can be imported from secop.core from secop.core import Readable, Parameter, FloatRange, BoolType, StringIO, HasIodev - + class CCU4IO(StringIO): """communication with CCU4""" @@ -39,7 +39,7 @@ CCU4 luckily has a very simple and logical protocol: # Readable as a base class defines the value and status parameters class HeLevel(HasIodev, Readable): """He Level channel of CCU4""" - + # define the communication class to create the IO module iodevClass = CCU4IO @@ -99,11 +99,11 @@ the status codes from the hardware to the standard SECoP status codes. full_length = Parameter('warm length when full', FloatRange(0, 2000, unit='mm'), readonly=False) sample_rate = Parameter('sample rate', EnumType(slow=0, fast=1), readonly=False) - + ... - + Status = Readable.Status - + # conversion of the code from the CCU4 parameter 'hsf' STATUS_MAP = { 0: (Status.IDLE, 'sensor ok'), @@ -113,17 +113,17 @@ the status codes from the hardware to the standard SECoP status codes. 4: (Status.ERROR, 'not yet read'), 5: (Status.DISABLED, 'disabled'), } - + def read_status(self): name, txtvalue = self._iodev.communicate('hsf').split('=') assert name == 'hsf' return self.STATUS_MAP(int(txtvalue)) - + def read_empty_length(self): name, txtvalue = self._iodev.communicate('hem').split('=') assert name == 'hem' return txtvalue - + def write_empty_length(self, value): name, txtvalue = self._iodev.communicate('hem=%g' % value).split('=') assert name == 'hem' @@ -135,7 +135,7 @@ the status codes from the hardware to the standard SECoP status codes. Here we start to realize, that we will repeat similar code for other parameters, which means it might be worth to create a *query* method, and then the *read_* and *write_* methods will become shorter: - + .. code:: python ... diff --git a/secop/modules.py b/secop/modules.py index 8df582e..32f798e 100644 --- a/secop/modules.py +++ b/secop/modules.py @@ -91,15 +91,16 @@ class HasAccessibles(HasProperties): continue rfunc = getattr(cls, 'read_' + pname, None) rfunc_handler = pobj.handler.get_read_func(cls, pname) if pobj.handler else None - not_wrapped = getattr(rfunc, '__wrapped__', False) is False + wrapped = hasattr(rfunc, '__wrapped__') if rfunc_handler: - if rfunc and not_wrapped: + if rfunc and not wrapped: raise ProgrammingError("parameter '%s' can not have a handler " "and read_%s" % (pname, pname)) rfunc = rfunc_handler + wrapped = False # create wrapper except when read function is already wrapped - if rfunc is None or not_wrapped: + if not wrapped: def wrapped_rfunc(self, pname=pname, rfunc=rfunc): if rfunc: @@ -127,12 +128,14 @@ class HasAccessibles(HasProperties): if not pobj.readonly: wfunc = getattr(cls, 'write_' + pname, None) - not_wrapped = getattr(wfunc, '__wrapped__', False) is False - if wfunc is None or not_wrapped: # ignore the handler, if a write function is present - wfunc = pobj.handler.get_write_func(pname) if pobj.handler else None + wrapped = hasattr(wfunc, '__wrapped__') + if (wfunc is None or wrapped) and pobj.handler: + # ignore the handler, if a write function is present + wfunc = pobj.handler.get_write_func(pname) + wrapped = False # create wrapper except when write function is already wrapped - if wfunc is None or not_wrapped: + if not wrapped: def wrapped_wfunc(self, value, pname=pname, wfunc=wfunc): self.log.debug("check validity of %s = %r" % (pname, value))