class TestChoiceArrayMeta(unittest.TestCase): def setUp(self): self.meta = ChoiceArrayMeta("test description", ["a", "b"]) def test_init(self): self.meta = ChoiceArrayMeta("test description", ["a", "b"]) assert "test description" == self.meta.description assert self.meta.label == "" assert self.meta.typeid == "malcolm:core/ChoiceArrayMeta:1.0" assert self.meta.choices == ["a", "b"] def test_validate_none(self): assert self.meta.validate(None) == [] def test_validate(self): response = self.meta.validate(["b", "a"]) assert ["b", "a"] == response def test_not_iterable_raises(self): value = "abb" with self.assertRaises(ValueError): self.meta.validate(value) def test_null_element_maps_default(self): array = ["b", None] assert self.meta.validate(array) == ["b", "a"] def test_invalid_choice_raises(self): with self.assertRaises(ValueError): self.meta.validate(["a", "x"])
def __init__( self, client: AClient, meta: AMeta, block_name: ABlockName, field_name: AFieldName, ) -> None: # Fill in the meta object with the correct headers columns = OrderedDict() self.field_data = OrderedDict() fields = client.get_table_fields(block_name, field_name) if not fields: # Didn't put any metadata in, make some up fields["VALUE"] = TableFieldData(31, 0, "The Value", None, True) for column_name, field_data in fields.items(): nbits = field_data.bits_hi - field_data.bits_lo + 1 if nbits < 1: raise ValueError("Bad bits in %s" % (field_data, )) if field_data.labels: column_meta = ChoiceArrayMeta(choices=field_data.labels) widget = Widget.COMBO elif nbits == 1: column_meta = BooleanArrayMeta() widget = Widget.CHECKBOX else: dtype = get_dtype(nbits, field_data.signed) column_meta = NumberArrayMeta(dtype) widget = Widget.TEXTINPUT column_name = snake_to_camel(column_name) column_meta.set_label(camel_to_title(column_name)) column_meta.set_tags([widget.tag()]) column_meta.set_description(field_data.description) column_meta.set_writeable(True) columns[column_name] = column_meta self.field_data[column_name] = field_data meta.set_elements(columns) # Work out how many ints per row # TODO: this should be in the block data max_bits_hi = max(f.bits_hi for f in self.field_data.values()) self.ints_per_row = int((max_bits_hi + 31) / 32) # Superclass will make the attribute for us super().__init__(client, meta, block_name, field_name)
def __init__(self, client, meta, block_name, field_name): # type: (AClient, AMeta, ABlockName, AFieldName) -> None # Fill in the meta object with the correct headers columns = OrderedDict() self.field_data = OrderedDict() fields = client.get_table_fields(block_name, field_name) if not fields: # Didn't put any metadata in, make some up fields["VALUE"] = TableFieldData(31, 0, "The Value", None) for column_name, field_data in fields.items(): nbits = field_data.bits_hi - field_data.bits_lo + 1 if nbits < 1: raise ValueError("Bad bits in %s" % (field_data, )) if field_data.labels: column_meta = ChoiceArrayMeta(choices=field_data.labels) widget = Widget.COMBO elif nbits == 1: column_meta = BooleanArrayMeta() widget = Widget.CHECKBOX else: if nbits <= 8: dtype = "uint8" elif nbits <= 16: dtype = "uint16" elif nbits <= 32: dtype = "uint32" elif nbits <= 64: dtype = "uint64" else: raise ValueError("Bad bits in %s" % (field_data, )) column_meta = NumberArrayMeta(dtype) widget = Widget.TEXTINPUT column_name = snake_to_camel(column_name) column_meta.set_label(camel_to_title(column_name)) column_meta.set_tags([widget.tag()]) column_meta.set_description(field_data.description) column_meta.set_writeable(True) columns[column_name] = column_meta self.field_data[column_name] = field_data meta.set_elements(columns) # Superclass will make the attribute for us super(PandABlocksTablePart, self).__init__(client, meta, block_name, field_name)
def __init__( self, mri: AMri, config_dir: AConfigDir, template_designs: ATemplateDesigns = "", initial_design: AInitialDesign = "", use_git: AUseGit = True, description: ADescription = "", ) -> None: super().__init__(mri=mri, description=description) assert os.path.isdir(config_dir), "%s is not a directory" % config_dir self.config_dir = config_dir self.initial_design = initial_design self.use_git = use_git self.template_designs = template_designs self.git_config: Tuple[str, ...] if use_git: if check_git_version("1.7.2"): self.git_email = os.environ["USER"] + "@" + socket.gethostname( ) self.git_name = "Malcolm" self.git_config = ( "-c", "user.name=%s" % self.git_name, "-c", 'user.email="%s"' % self.git_email, ) else: self.git_config = () # last saved layout and exports self.saved_visibility = None self.saved_exports = None # ((name, AttributeModel/MethodModel, setter, needs_context)) self._current_part_fields = () self._subscriptions: List[Subscribe] = [] self.port_info: Dict[APartName, List[PortInfo]] = {} self.part_exportable: Dict[Part, List[AAttributeName]] = {} # TODO: turn this into "exported attribute modified" self.context_modified: Dict[Part, Set[str]] = {} self.part_modified: Dict[Part, PartModifiedInfo] = {} # The attributes our part has published self.our_config_attributes: Dict[str, AttributeModel] = {} # The reportable infos we are listening for self.info_registry.add_reportable(PartModifiedInfo, self.update_modified) # Update queue of exportable fields self.info_registry.add_reportable(PartExportableInfo, self.update_exportable) # Create a port for ourself self.field_registry.add_attribute_model( "mri", StringMeta( "A port for giving our MRI to things that might use us", tags=[Port.BLOCK.source_port_tag(self.mri)], ).create_attribute_model(self.mri), ) # Create a layout table attribute for setting block positions self.layout = TableMeta.from_table( LayoutTable, "Layout of child blocks", Widget.FLOWGRAPH, writeable=["x", "y", "visible"], ).create_attribute_model() self.set_writeable_in(self.layout, ss.READY) self.field_registry.add_attribute_model("layout", self.layout, self.set_layout) # Create a design attribute for loading an existing layout self.design = ChoiceMeta("Design name to load", tags=[config_tag(), Widget.COMBO.tag() ]).create_attribute_model() self.field_registry.add_attribute_model("design", self.design, self.set_design) self.set_writeable_in(self.design, ss.READY) # Create an export table for mirroring exported fields self.exports = TableMeta.from_table( ExportTable, "Exported fields of child blocks", writeable=list(ExportTable.call_types), ).create_attribute_model() # Overwrite the sources meta to be a ChoiceArrayMeta self.exports.meta.elements["source"] = ChoiceArrayMeta( "Name of the block.field to export", writeable=True, tags=[Widget.COMBO.tag()], ) self.set_writeable_in(self.exports, ss.READY) self.field_registry.add_attribute_model("exports", self.exports, self.set_exports) # Create read-only indicator for when things are modified self.modified = BooleanMeta("Whether the design is modified", tags=[Widget.LED.tag() ]).create_attribute_model() self.field_registry.add_attribute_model("modified", self.modified) # Create the save method self.set_writeable_in(self.field_registry.add_method_model(self.save), ss.READY)
def test_init(self): self.meta = ChoiceArrayMeta("test description", ["a", "b"]) assert "test description" == self.meta.description assert self.meta.label == "" assert self.meta.typeid == "malcolm:core/ChoiceArrayMeta:1.0" assert self.meta.choices == ["a", "b"]
def setUp(self): self.meta = ChoiceArrayMeta("test description", ["a", "b"])