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 <pedersen+jenkins@frm2.tum.de>
Reviewed-by: Markus Zolliker <markus.zolliker@psi.ch>
This commit is contained in:
l_samenv 2021-03-03 14:35:21 +01:00 committed by Markus Zolliker
parent 9b71d3621d
commit 4922f0d664
2 changed files with 19 additions and 16 deletions

View File

@ -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_<param>* and *write_<param>* methods will become shorter:
.. code:: python
...

View File

@ -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))