Skip to content

Commit

Permalink
Added scalar channel access parts
Browse files Browse the repository at this point in the history
  • Loading branch information
gilesknap committed Jul 21, 2016
1 parent 39f2b59 commit ac6cc26
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 26 deletions.
4 changes: 2 additions & 2 deletions malcolm/core/part.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ def _call_setup(self, params):
# have a Method attached to it. Calling the Method will fill in defaults
if not hasattr(self.setup, "Method"):
raise NotImplementedError()
# unfortunately thi has to be done now rather than at @takes decorate
# unfortunately this has to be done now rather than at @takes decorate
# time so it gets the bound method rather than the unbound function
self.setup.Method.set_function(self.setup)
self.setup.Method.call_function(params)

def setup(selfself, params):
def setup(self, params):
raise NotImplementedError()
32 changes: 32 additions & 0 deletions malcolm/parts/ca/cachoicepart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from cothread import catools

from malcolm.parts.ca.capart import CAPart
from malcolm.metas.choicemeta import ChoiceMeta
from malcolm.metas.stringmeta import StringMeta
from malcolm.core.method import takes, REQUIRED


class CAChoicePart(CAPart):
"""Defines a part which connects to a pv via channel access DBR_ENUM"""

@takes(
StringMeta("name", "name of created attribute"), REQUIRED,
StringMeta("description", "desc of created attribute"), REQUIRED,
StringMeta("pv", "full pv of demand and default for rbv"), REQUIRED,
StringMeta("rbv", "override for rbv"), None,
StringMeta("rbv_suff", "set rbv ro pv + rbv_suff"), None,
)
def setup(self, params):
""" setup is called by the base class Part.__init__ via self.Method.
self.Method is defined by the @takes decorator above.
It defines an attribute to publish the pv
Args:
params(Map): parameters described in @takes
"""
meta = ChoiceMeta("meta", params.description, [])
self.create_attribute(meta, params.pv, rbv=params.rbv,
rbv_suff=params.rbv_suff)

def get_datatype(self):
return catools.DBR_ENUM
13 changes: 9 additions & 4 deletions malcolm/parts/ca/cadoublepart.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import numpy as np
from cothread import catools

from malcolm.parts.ca.capart import CAPart
from malcolm.metas.numbermeta import NumberMeta
Expand All @@ -7,7 +8,7 @@


class CADoublePart(CAPart):
""" Defines a part which connects via channel access to a DBR_DOUBLE pv"""
""" Defines a part which connects to a pv via channel access DBR_DOUBLE"""

@takes(
StringMeta("name", "name of created attribute"), REQUIRED,
Expand All @@ -18,12 +19,16 @@ class CADoublePart(CAPart):
)
def setup(self, params):
""" setup is called by the base class Part.__init__ via self.Method.
self. Method is defined by the @takes decorator above.
It defines an attribute to publish the pv via Malcolm
self.Method is defined by the @takes decorator above.
It defines an attribute to publish the pv
Args:
params(OrderedDict): parameters described in @takes
params(Map): parameters described in @takes
"""
meta = NumberMeta("meta", params.description, np.float64)
self.create_attribute(meta, params.pv, rbv=params.rbv,
rbv_suff=params.rbv_suff)


def get_datatype(self):
return catools.DBR_DOUBLE
33 changes: 33 additions & 0 deletions malcolm/parts/ca/calongpart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import numpy as np
from cothread import catools

from malcolm.parts.ca.capart import CAPart
from malcolm.metas.numbermeta import NumberMeta
from malcolm.metas.stringmeta import StringMeta
from malcolm.core.method import takes, returns, REQUIRED


class CALongPart(CAPart):
""" Defines a part which connects to a pv via channel access DBR_LONG"""

@takes(
StringMeta("name", "name of created attribute"), REQUIRED,
StringMeta("description", "desc of created attribute"), REQUIRED,
StringMeta("pv", "full pv of demand and default for rbv"), REQUIRED,
StringMeta("rbv", "override for rbv"), None,
StringMeta("rbv_suff", "set rbv ro pv + rbv_suff"), None,
)
def setup(self, params):
""" setup is called by the base class Part.__init__ via self.Method.
self.Method is defined by the @takes decorator above.
It defines an attribute to publish the pv
Args:
params(Map): parameters described in @takes
"""
meta = NumberMeta("meta", params.description, np.int32)
self.create_attribute(meta, params.pv, rbv=params.rbv,
rbv_suff=params.rbv_suff)

def get_datatype(self):
return catools.DBR_LONG
7 changes: 1 addition & 6 deletions malcolm/parts/ca/capart.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,7 @@ def create_attribute(self, meta, pv, rbv=None, rbv_suff=None,
self.monitor = None

def get_datatype(self):
# TODO: use meta to infer datatype
if self.long_string:
datatype = catools.DBR_CHAR_STR
else:
datatype = None
return datatype
raise NotImplementedError

@Controller.Resetting
def connect_pvs(self):
Expand Down
32 changes: 32 additions & 0 deletions malcolm/parts/ca/castringpart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import cothread
from cothread import catools

from malcolm.parts.ca.capart import CAPart
from malcolm.metas.stringmeta import StringMeta
from malcolm.core.method import takes, REQUIRED


class CAStringPart(CAPart):
"""Defines a part which connects to a pv via channel access DBR_STRING"""

@takes(
StringMeta("name", "name of created attribute"), REQUIRED,
StringMeta("description", "desc of created attribute"), REQUIRED,
StringMeta("pv", "full pv of demand and default for rbv"), REQUIRED,
StringMeta("rbv", "override for rbv"), None,
StringMeta("rbv_suff", "set rbv ro pv + rbv_suff"), None,
)
def setup(self, params):
""" setup is called by the base class Part.__init__ via self.Method.
self.Method is defined by the @takes decorator above.
It defines an attribute to publish the pv
Args:
params(Map): parameters described in @takes
"""
meta = StringMeta("meta", params.description)
self.create_attribute(meta, params.pv, rbv=params.rbv,
rbv_suff=params.rbv_suff)

def get_datatype(self):
return catools.DBR_CHAR_STR
8 changes: 7 additions & 1 deletion tests/test_core/test_part.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import setup_malcolm_paths

import unittest
from mock import Mock
from mock import Mock, patch

from malcolm.core.part import Part

Expand All @@ -17,5 +17,11 @@ def test_init(self):
self.assertRaises(NotImplementedError, Part, "part", process, block,
None)

def test_setup(self):
with patch('malcolm.core.part.Part.__init__') as init_mock:
init_mock.return_value = None
p = Part(None, None, None, None)
self.assertRaises(NotImplementedError, p.setup, None)

if __name__ == "__main__":
unittest.main(verbosity=2)
26 changes: 14 additions & 12 deletions tests/test_parts/test_ca/test_cadoublepart.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
import os
import sys

sys.path.append(os.path.join(os.path.dirname(__file__), "..", ".."))
import setup_malcolm_paths

from cothread import catools
from malcolm.parts.ca.cadoublepart import CADoublePart

import unittest
from mock import Mock, patch, ANY


class TestCADoublePart(unittest.TestCase):

def test_init(self):
CADoublePart.create_attribute = Mock()
# reading yaml will result in a dictionary such as:-
exposure_pv={"name": "exposure",
"description": "shutter time",
"pv": "BL00I-EA-DET-01:AcquireTime",
"rbv_suff": "_RBV"}
p = CADoublePart("exp", Mock(), Mock(), exposure_pv)

# TODO: add above exposure_pv params
p.create_attribute.assert_called_once_with(ANY,
"BL00I-EA-DET-01:AcquireTime", rbv=None, rbv_suff='_RBV')
CADoublePart.create_attribute = Mock()
# reading yaml will result in a dictionary such as:-
d = {"name": "pv",
"description": "a test pv",
"pv": "Prefix:Suffix",
"rbv_suff": "_RBV"}
p = CADoublePart("part", Mock(), Mock(), d)

p.create_attribute.assert_called_once_with(ANY,
"Prefix:Suffix", rbv=None,
rbv_suff='_RBV')
if __name__ == "__main__":
unittest.main(verbosity=2)
31 changes: 31 additions & 0 deletions tests/test_parts/test_ca/test_calongpart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os
import sys

sys.path.append(os.path.join(os.path.dirname(__file__), "..", ".."))
import setup_malcolm_paths

from cothread import catools
from malcolm.parts.ca.calongpart import CALongPart

import unittest
from mock import Mock, patch, ANY


class TestCALongPart(unittest.TestCase):
def test_init(self):
CALongPart.create_attribute = Mock()
# reading yaml will result in a dictionary such as:-
d = {"name": "pv",
"description": "a test pv",
"pv": "Prefix:Suffix",
"rbv_suff": "_RBV"}
p = CALongPart("part", Mock(), Mock(), d)

p.create_attribute.assert_called_once_with(ANY,
"Prefix:Suffix", rbv=None,
rbv_suff='_RBV')

self.assertEqual(p.get_datatype(), catools.DBR_LONG)

if __name__ == "__main__":
unittest.main(verbosity=2)
3 changes: 2 additions & 1 deletion tests/test_parts/test_ca/test_capart.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def test_init_no_rbv(self):

def test_reset(self):
p = self.create_part()
p.get_datatype = MagicMock(return_value=None)
catools.connect.return_value = MagicMock(ok=True)
p.connect_pvs()
catools.connect.assert_called_with(["pv", "pv2"], cainfo=True)
Expand Down Expand Up @@ -83,7 +84,7 @@ def test_close_monitor(self):
def test_get_datatype(self):
p = self.create_part()
p.long_string = True
self.assertEqual(p.get_datatype(), catools.DBR_CHAR_STR)
self.assertRaises(NotImplementedError, p.get_datatype)

def test_update_value_good(self):
p = self.create_part()
Expand Down
31 changes: 31 additions & 0 deletions tests/test_parts/test_ca/test_caschoicepart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), "..", ".."))
import setup_malcolm_paths

from cothread import catools
from malcolm.parts.ca.cachoicepart import CAChoicePart

import unittest
from mock import Mock, patch, ANY


class TestCAChoicePart(unittest.TestCase):

def test_init(self):
CAChoicePart.create_attribute = Mock()
# reading yaml will result in a dictionary such as:-
d = {"name": "pv",
"description": "a test pv",
"pv": "Prefix:Suffix",
"rbv_suff": "_RBV"}
p = CAChoicePart("part", Mock(), Mock(), d)

p.create_attribute.assert_called_once_with(ANY,
"Prefix:Suffix", rbv=None,
rbv_suff='_RBV')

self.assertEqual(p.get_datatype(), catools.DBR_ENUM)

if __name__ == "__main__":
unittest.main(verbosity=2)
31 changes: 31 additions & 0 deletions tests/test_parts/test_ca/test_castringpart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os
import sys

sys.path.append(os.path.join(os.path.dirname(__file__), "..", ".."))
import setup_malcolm_paths

from cothread import catools
from malcolm.parts.ca.castringpart import CAStringPart
from malcolm.metas.stringmeta import StringMeta

import unittest
from mock import Mock, patch, ANY


class TestCAStringPart(unittest.TestCase):
def test_init(self):
CAStringPart.create_attribute = Mock()
# reading yaml will result in a dictionary such as:-
d = {"name": "pv",
"description": "a test pv",
"pv": "Prefix:Suffix",
"rbv_suff": "_RBV"}
p = CAStringPart("part", Mock(), Mock(), d)

p.create_attribute.assert_called_once_with(ANY,
"Prefix:Suffix", rbv=None,
rbv_suff='_RBV')
self.assertEqual(p.get_datatype(), catools.DBR_CHAR_STR)

if __name__ == "__main__":
unittest.main(verbosity=2)

0 comments on commit ac6cc26

Please sign in to comment.