def create_attributes(self):
     tags = [widget("group")]
     meta = ChoiceMeta("All %s attributes" % self.attr_name,
                       choices=["expanded", "collapsed"], tags=tags,
                       label=self.attr_name.title())
     self.attr = meta.make_attribute("expanded")
     yield self.attr_name, self.attr, self.attr.set_value
Example #2
0
 def create_attributes(self):
     tags = ["widget:group"]
     meta = ChoiceMeta("All %s attributes" % self.attr_name,
                       choices=["expanded", "collapsed"],
                       tags=tags,
                       label=self.attr_name.title())
     self.attr = meta.make_attribute("expanded")
     yield self.attr_name, self.attr, self.attr.set_value
Example #3
0
 def __init__(self, process, attr_name):
     params = Part.MethodMeta.prepare_input_map(name=attr_name)
     super(PandABoxGroupPart, self).__init__(process, params)
     self.attr_name = attr_name
     tags = [widget("group"), config()]
     self.meta = ChoiceMeta("All %s attributes" % self.attr_name,
                            choices=["expanded", "collapsed"],
                            tags=tags,
                            label=self.attr_name.title())
Example #4
0
 def test_init(self):
     self.choice_meta = ChoiceMeta("test description", ["a", "b"])
     self.assertEqual("test description", self.choice_meta.description)
     self.assertEqual(self.choice_meta.typeid,
                      "malcolm:core/ChoiceMeta:1.0")
     self.assertEqual(self.choice_meta.label, "")
     self.assertEqual(self.choice_meta.choices, ("a", "b"))
Example #5
0
def make_meta(subtyp, description, tags, writeable=True, labels=None):
    if subtyp == "enum":
        if writeable:
            widget_type = "combo"
        else:
            widget_type = "textupdate"
        tags.append(widget(widget_type))
        meta = ChoiceMeta(description, labels, tags)
    elif subtyp == "bit":
        if writeable:
            widget_type = "checkbox"
        else:
            widget_type = "led"
        tags.append(widget(widget_type))
        meta = BooleanMeta(description, tags)
    else:
        if writeable:
            widget_type = "textinput"
        else:
            widget_type = "textupdate"
        tags.append(widget(widget_type))
        if subtyp == "uint":
            meta = NumberMeta("uint32", description, tags)
        elif subtyp == "int":
            meta = NumberMeta("int32", description, tags)
        elif subtyp == "scalar":
            meta = NumberMeta("float64", description, tags)
        elif subtyp == "lut":
            meta = StringMeta(description, tags)
        elif subtyp in ("pos", "relative_pos"):
            meta = NumberMeta("float64", description, tags)
        else:
            raise ValueError("Unknown subtype %r" % subtyp)
    return meta
 def test_from_dict(self):
     bm = ChoiceMeta.from_dict(self.serialized)
     self.assertEqual(type(bm), ChoiceMeta)
     self.assertEquals(bm.description, "desc")
     self.assertEquals(bm.choices, ["a", "b"])
     self.assertEqual(bm.tags, [])
     self.assertFalse(bm.writeable)
     self.assertEqual(bm.label, "name")
 def test_from_dict(self):
     bm = ChoiceMeta.from_dict(self.serialized)
     self.assertEqual(type(bm), ChoiceMeta)
     self.assertEquals(bm.description, "desc")
     self.assertEquals(bm.choices, ["a", "b"])
     self.assertEqual(bm.tags, [])
     self.assertFalse(bm.writeable)
     self.assertEqual(bm.label, "name")
class TestValidate(unittest.TestCase):

    def setUp(self):
        self.choice_meta = ChoiceMeta(
            "test description", ["a", "b"])

    def test_given_valid_value_then_return(self):
        response = self.choice_meta.validate("a")
        self.assertEqual("a", response)

    def test_int_validate(self):
        response = self.choice_meta.validate(1)
        self.assertEqual("b", response)

    def test_None_valid(self):
        response = self.choice_meta.validate(None)
        self.assertEqual(None, response)

    def test_given_invalid_value_then_raises(self):
        with self.assertRaises(ValueError):
            self.choice_meta.validate('badname')

    def test_set_choices(self):
        self.choice_meta.set_choices(["4"])

        self.assertEqual(["4"], self.choice_meta.choices)
class TestValidate(unittest.TestCase):

    def setUp(self):
        self.choice_meta = ChoiceMeta(
            "test description", ["a", "b"])

    def test_given_valid_value_then_return(self):
        response = self.choice_meta.validate("a")
        self.assertEqual("a", response)

    def test_int_validate(self):
        response = self.choice_meta.validate(1)
        self.assertEqual("b", response)

    def test_None_valid(self):
        response = self.choice_meta.validate(None)
        self.assertEqual("a", response)

    def test_given_invalid_value_then_raises(self):
        with self.assertRaises(ValueError):
            self.choice_meta.validate('badname')

    def test_set_choices(self):
        self.choice_meta.set_choices(["4"])

        self.assertEqual(["4"], self.choice_meta.choices)
Example #10
0
 def create_attributes(self):
     for data in super(DetectorDriverPart, self).create_attributes():
         yield data
     meta = NumberMeta("float64", "Time taken to readout detector")
     self.readout_time = meta.make_attribute(self.params.readoutTime)
     yield "readoutTime", self.readout_time, self.readout_time.set_value
     meta = ChoiceMeta("Whether detector is software or hardware triggered",
                       ["Software", "Hardware"])
     self.trigger_mode = meta.make_attribute("Hardware")
     yield "triggerMode", self.trigger_mode, None
 def _create_default_attributes(self):
     # Add the state, status and busy attributes
     self.state = ChoiceMeta("State of Block",
                             self.stateMachine.possible_states,
                             label="State").make_attribute()
     yield "state", self.state, None
     self.status = StringMeta("Status of Block",
                              label="Status").make_attribute()
     yield "status", self.status, None
     self.busy = BooleanMeta("Whether Block busy or not",
                             label="Busy").make_attribute()
     yield "busy", self.busy, None
Example #12
0
 def create_attributes(self):
     for data in super(ManagerController, self).create_attributes():
         yield data
     # Make a table for the layout info we need
     columns = OrderedDict()
     columns["name"] = StringArrayMeta("Name of layout part")
     columns["mri"] = StringArrayMeta("Malcolm full name of child block")
     columns["x"] = NumberArrayMeta("float64", "X Coordinate of child block")
     columns["y"] = NumberArrayMeta("float64", "Y Coordinate of child block")
     columns["visible"] = BooleanArrayMeta("Whether child block is visible")
     layout_table_meta = TableMeta("Layout of child blocks", columns=columns)
     layout_table_meta.set_writeable_in(sm.EDITABLE)
     self.layout = layout_table_meta.make_attribute()
     yield "layout", self.layout, self.set_layout
     self.layout_name = ChoiceMeta(
         "Saved layout name to load", []).make_attribute()
     self.layout_name.meta.set_writeable_in(
         self.stateMachine.AFTER_RESETTING)
     yield "layoutName", self.layout_name, self.load_layout
     assert os.path.isdir(self.params.configDir), \
         "%s is not a directory" % self.params.configDir
Example #13
0
 def _make_time_parts(self, field_name, field_data, writeable):
     description = field_data.description
     if writeable:
         widget_tag = widget("textupdate")
         group_tag = self._make_group("parameters")
     else:
         widget_tag = widget("textinput")
         group_tag = self._make_group("readbacks")
     meta = NumberMeta("float64", description, [group_tag, widget_tag])
     self._make_field_part(field_name, meta, writeable)
     meta = ChoiceMeta(description + " time units", ["s", "ms", "us"],
                       tags=[group_tag, widget("combo")])
     self._make_field_part(field_name + ".UNITS", meta, writeable=True)
Example #14
0
class PandABoxGroupPart(Part):
    """This will normally be instantiated by the PandABox assembly, not created
    in yaml"""
    def __init__(self, process, attr_name):
        params = Part.MethodMeta.prepare_input_map(name=attr_name)
        super(PandABoxGroupPart, self).__init__(process, params)
        self.attr_name = attr_name
        tags = [widget("group"), config()]
        self.meta = ChoiceMeta("All %s attributes" % self.attr_name,
                               choices=["expanded", "collapsed"],
                               tags=tags,
                               label=self.attr_name.title())

    def create_attributes(self):
        attr = self.meta.make_attribute("expanded")
        yield self.attr_name, attr, attr.set_value
Example #15
0
    def create_attributes(self):
        """Method that should provide Attribute instances for Block

        Yields:
            tuple: (string name, Attribute, callable put_function).
        """
        # Add the state, status and busy attributes
        self.state = ChoiceMeta("State of Block",
                                self.stateMachine.possible_states,
                                label="State").make_attribute()
        yield "state", self.state, None
        self.status = StringMeta("Status of Block",
                                 label="Status").make_attribute()
        yield "status", self.status, None
        self.busy = BooleanMeta("Whether Block busy or not",
                                label="Busy").make_attribute()
        yield "busy", self.busy, None
Example #16
0
 def _make_mux(self, field_name, field_data, typ):
     group_tag = self._make_group("inputs")
     if typ == "bit":
         inport_type = "bool"
     else:
         inport_type = "int32"
     meta = ChoiceMeta(
         field_data.description,
         field_data.labels,
         tags=[group_tag,
               inport(inport_type, "ZERO"),
               widget("combo")])
     self._make_field_part(field_name, meta, writeable=True)
     meta = make_meta(typ,
                      "%s current value" % field_name,
                      tags=[group_tag],
                      writeable=False)
     self._make_field_part(field_name + ".VAL", meta, writeable=False)
Example #17
0
 def _make_out_capture(self, field_name, field_data):
     group_tag = self._make_group("outputs")
     meta = ChoiceMeta("Capture %s in PCAP?" % field_name,
                       field_data.labels,
                       tags=[group_tag, widget("combo")])
     self._make_field_part(field_name + ".CAPTURE", meta, writeable=True)
     if self.area_detector:
         from malcolm.parts.ADCore.hdfwriterpart import \
             attribute_dataset_types
         # Make a string part to hold the name of the dataset
         part_name = field_name + ".DATASET_NAME"
         label, attr_name = make_label_attr_name(part_name)
         params = StringPart.MethodMeta.prepare_input_map(
             name=attr_name,
             widget="textinput",
             description="Name of the captured dataset in HDF file",
             writeable=True,
             config=True)
         part = StringPart(self.process, params)
         self._add_part(part_name, part)
         # Make a choice part to hold the type of the dataset
         part_name = field_name + ".DATASET_TYPE"
         label, attr_name = make_label_attr_name(part_name)
         if "INENC" in self.block_name:
             initial = "position"
         else:
             initial = "monitor"
         params = ChoicePart.MethodMeta.prepare_input_map(
             name=attr_name,
             widget="textinput",
             description="Type of the captured dataset in HDF file",
             writeable=True,
             choices=attribute_dataset_types,
             initialValue=initial)
         part = StringPart(self.process, params)
         self._add_part(part_name, part)
Example #18
0
 def setUp(self):
     self.choice_meta = ChoiceMeta(
         "test description", ["a", "b"])
 def test_to_dict(self):
     bm = ChoiceMeta("desc", ["a", "b"], label="name")
     self.assertEqual(bm.to_dict(), self.serialized)
 def setUp(self):
     self.choice_meta = ChoiceMeta(
         "test description", ["a", "b"])
Example #21
0
class ManagerController(DefaultController):
    """RunnableDevice implementer that also exposes GUI for child parts"""
    # The stateMachine that this controller implements
    stateMachine = sm()

    ReportOutports = Hook()
    """Called before Layout to get outport info from children

    Args:
        task (Task): The task used to perform operations on child blocks

    Returns:
        [`OutportInfo`] - the type and value of each outport of the child
    """

    Layout = Hook()
    """Called when layout table set and at init to update child layout

    Args:
        task (Task): The task used to perform operations on child blocks
        part_info (dict): {part_name: [Info]} returned from Layout hook
        layout_table (Table): A possibly partial set of changes to the layout
            table that should be acted on

    Returns:
        [`LayoutInfo`] - the child layout resulting from this change
    """

    Load = Hook()
    """Called at load() or revert() to load child settings from a structure

    Args:
        task (Task): The task used to perform operations on child blocks
        structure (dict): {part_name: part_structure} where part_structure is
            the return from Save hook
    """

    Save = Hook()
    """Called at save() to serialize child settings into a dict structure

    Args:
        task (Task): The task used to perform operations on child blocks

    Returns:
        dict: serialized version of the child that could be loaded from
    """

    # attributes
    layout = None
    layout_name = None

    # {part_name: part_structure} of currently loaded settings
    load_structure = None

    def create_attributes(self):
        for data in super(ManagerController, self).create_attributes():
            yield data
        # Make a table for the layout info we need
        columns = OrderedDict()
        columns["name"] = StringArrayMeta("Name of layout part")
        columns["mri"] = StringArrayMeta("Malcolm full name of child block")
        columns["x"] = NumberArrayMeta("float64", "X Coordinate of child block")
        columns["y"] = NumberArrayMeta("float64", "Y Coordinate of child block")
        columns["visible"] = BooleanArrayMeta("Whether child block is visible")
        layout_table_meta = TableMeta("Layout of child blocks", columns=columns)
        layout_table_meta.set_writeable_in(sm.EDITABLE)
        self.layout = layout_table_meta.make_attribute()
        yield "layout", self.layout, self.set_layout
        self.layout_name = ChoiceMeta(
            "Saved layout name to load", []).make_attribute()
        self.layout_name.meta.set_writeable_in(
            self.stateMachine.AFTER_RESETTING)
        yield "layoutName", self.layout_name, self.load_layout
        assert os.path.isdir(self.params.configDir), \
            "%s is not a directory" % self.params.configDir

    def set_layout(self, value):
        # If it isn't a table, make it one
        if not isinstance(value, Table):
            value = Table(self.layout.meta, value)
        part_info = self.run_hook(self.ReportOutports, self.create_part_tasks())
        part_info = self.run_hook(
            self.Layout, self.create_part_tasks(), part_info, value)
        layout_table = Table(self.layout.meta)
        for name, layout_infos in LayoutInfo.filter_parts(part_info).items():
            assert len(layout_infos) == 1, \
                "%s returned more than 1 layout infos" % name
            layout_info = layout_infos[0]
            row = [name, layout_info.mri, layout_info.x, layout_info.y,
                   layout_info.visible]
            layout_table.append(row)
        self.layout.set_value(layout_table)

    def do_reset(self):
        super(ManagerController, self).do_reset()
        # This will trigger all parts to report their layout, making sure the
        # layout table has a valid value
        self.set_layout(Table(self.layout.meta))
        # List the configDir and add to choices
        self._set_layout_names()
        # If we have no load_structure (initial reset) define one
        if self.load_structure is None:
            if self.params.defaultConfig:
                self.load_layout(self.params.defaultConfig)
            else:
                self.load_structure = self._save_to_structure()

    @method_writeable_in(sm.READY)
    def edit(self):
        self.transition(sm.EDITABLE, "Layout editable")

    def go_to_error_state(self, exception):
        if self.state.value == sm.EDITABLE:
            # If we got a save or revert exception, don't go to fault
            self.log_exception("Fault occurred while trying to save/revert")
        else:
            super(ManagerController, self).go_to_error_state(exception)

    @method_writeable_in(sm.EDITABLE)
    @method_takes(
        "layoutName", StringMeta(
            "Name of layout to save to, if different from current layoutName"),
        None)
    def save(self, params):
        self.try_stateful_function(
            sm.SAVING, self.stateMachine.AFTER_RESETTING, self.do_save,
            params.layoutName)

    def do_save(self, layout_name=None):
        if not layout_name:
            layout_name = self.layout_name.value
        structure = self._save_to_structure()
        text = json_encode(structure, indent=2)
        filename = self._validated_config_filename(layout_name)
        open(filename, "w").write(text)
        self._set_layout_names(layout_name)
        self.layout_name.set_value(layout_name)
        self.load_structure = structure

    def _set_layout_names(self, extra_name=None):
        names = []
        if extra_name:
            names.append(extra_name)
        dir_name = self._make_config_dir()
        for f in os.listdir(dir_name):
            if os.path.isfile(
                    os.path.join(dir_name, f)) and f.endswith(".json"):
                names.append(f.split(".json")[0])
        self.layout_name.meta.set_choices(names)

    @method_writeable_in(sm.EDITABLE)
    def revert(self):
        self.try_stateful_function(
            sm.REVERTING, self.stateMachine.AFTER_RESETTING, self.do_revert)

    def do_revert(self):
        self._load_from_structure(self.load_structure)

    def _validated_config_filename(self, name):
        """Make config dir and return full file path and extension

        Args:
            name (str): Filename without dir or extension

        Returns:
            str: Full path including extensio
        """
        dir_name = self._make_config_dir()
        filename = os.path.join(dir_name, name.split(".json")[0] + ".json")
        return filename

    def _make_config_dir(self):
        dir_name = os.path.join(self.params.configDir, self.mri)
        try:
            os.mkdir(dir_name)
        except OSError:
            # OK if already exists, if not then it will fail on write anyway
            pass
        return dir_name

    def load_layout(self, value):
        # TODO: race condition if we get 2 loads at once...
        # Do we need a Loading state?
        filename = self._validated_config_filename(value)
        text = open(filename, "r").read()
        structure = json_decode(text)
        self._load_from_structure(structure)
        self.layout_name.set_value(value)

    def _save_to_structure(self):
        structure = OrderedDict()
        structure["layout"] = OrderedDict()
        for name, x, y, visible in sorted(
                zip(self.layout.value.name, self.layout.value.x,
                    self.layout.value.y, self.layout.value.visible)):
            layout_structure = OrderedDict()
            layout_structure["x"] = x
            layout_structure["y"] = y
            layout_structure["visible"] = visible
            structure["layout"][name] = layout_structure
        for part_name, part_structure in sorted(self.run_hook(
                self.Save, self.create_part_tasks()).items()):
            structure[part_name] = part_structure
        return structure

    def _load_from_structure(self, structure):
        table = Table(self.layout.meta)
        for part_name, part_structure in structure["layout"].items():
            table.append([part_name, "", part_structure["x"],
                          part_structure["y"], part_structure["visible"]])
        self.set_layout(table)
        self.run_hook(self.Load, self.create_part_tasks(), structure)
Example #22
0
from malcolm.parts.ca.castringpart import CAStringPart
from malcolm.controllers.defaultcontroller import DefaultController
from malcolm.core import method_takes, REQUIRED
from malcolm.core.vmetas import StringMeta, ChoiceMeta
from malcolm.tags import port_types, outport, widget


@method_takes("name", StringMeta("Name of the created attribute"), REQUIRED,
              "description", StringMeta("Desc of created attribute"),
              REQUIRED, "rbv",
              StringMeta("Full pv of demand and default for rbv"), REQUIRED,
              "outport", ChoiceMeta("Outport type", port_types), REQUIRED)
class AsynOutportPart(CAStringPart):
    def __init__(self, process, params):
        self.outport_type = params.outport
        params = CAStringPart.MethodMeta.prepare_input_map(
            name=params.name, description=params.description, rbv=params.rbv)
        super(AsynOutportPart, self).__init__(process, params)

    def create_tags(self):
        tags = super(AsynOutportPart, self).create_tags()
        tags.append(widget("textupdate"))
        return tags

    @DefaultController.Reset
    def reset(self, task=None):
        super(AsynOutportPart, self).reset(task)
        # Add the outport tags
        tags = [t for t in self.attr.meta.tags if not t.startswith("outport:")]
        tags.append(outport(self.outport_type, self.attr.value))
Example #23
0
from malcolm.core import Part, method_takes, REQUIRED
from malcolm.core.vmetas import StringMeta, BooleanMeta, ChoiceMeta
from malcolm.tags import widget_types, widget, config


@method_takes(
    "name", StringMeta("Name of the created attribute"), REQUIRED,
    "description", StringMeta("Desc of created attribute"), REQUIRED,
    "widget", ChoiceMeta("Widget type", [""] + widget_types), "",
    "writeable", BooleanMeta("Is the attribute writeable?"), False,
    "config", BooleanMeta("Should this field be loaded/saved?"), False)
class AttributePart(Part):
    # Attribute instance
    attr = None

    def create_attributes(self):
        # Find the tags
        tags = self.create_tags()
        # Make a meta object for our attribute
        meta = self.create_meta(self.params.description, tags)
        # The attribute we will be publishing
        initial_value = self.get_initial_value()
        self.attr = meta.make_attribute(initial_value)
        writeable_func = self.get_writeable_func()
        yield self.params.name, self.attr, writeable_func

    def create_meta(self, description, tags):
        raise NotImplementedError()

    def get_writeable_func(self):
        if self.params.writeable:
Example #24
0
from malcolm.core import method_takes, REQUIRED
from malcolm.parts.builtin.attributepart import AttributePart
from malcolm.core.vmetas import StringMeta, ChoiceMeta, BooleanMeta
from malcolm.controllers.defaultcontroller import DefaultController
from malcolm.parts.ca.cothreadimporter import CothreadImporter
from malcolm.tags import widget_types, inport, port_types


@method_takes(
    "name", StringMeta("Name of the created attribute"), REQUIRED,
    "description", StringMeta("Desc of created attribute"), REQUIRED,
    "pv", StringMeta("Full pv of demand and default for rbv"), "",
    "rbv", StringMeta("Override for rbv"), "",
    "rbvSuff", StringMeta("Set rbv ro pv + rbv_suff"), "",
    "widget", ChoiceMeta("Widget type", [""] + widget_types), "",
    "inport", ChoiceMeta("Inport type", [""] + port_types), "",
    "config", BooleanMeta("Should this field be loaded/saved?"), False)
class CAPart(AttributePart):
    # Camonitor subscription
    monitor = None

    def __init__(self, process, params):
        self.cothread, self.catools = CothreadImporter.get_cothread(process)
        # Format for all caputs
        self.ca_format = self.catools.FORMAT_TIME
        super(CAPart, self).__init__(process, params)

    def store_params(self, params):
        if not params.rbv and not params.pv:
            raise ValueError('Must pass pv or rbv')
        if not params.rbv:
Example #25
0
 def test_to_dict(self):
     bm = ChoiceMeta("desc", ["a", "b"], label="name")
     self.assertEqual(bm.to_dict(), self.serialized)
Example #26
0
 def create_meta(self, description, tags):
     return ChoiceMeta(choices=self.params.choices,
                       description=description,
                       tags=tags)
 def create_meta(self, description):
     return ChoiceMeta(description)
Example #28
0
 def create_meta(self, description, tags):
     return ChoiceMeta(description=description, tags=tags)