def save(self, context): # type: (AContext) -> AStructure child = context.block_view(self.mri) part_structure = OrderedDict() for k in child: attr = getattr(child, k) if isinstance(attr, Attribute) and get_config_tag(attr.meta.tags): part_structure[k] = serialize_object(attr.value) self.saved_structure = part_structure return part_structure
def __init__(self, client, block_name, block_data, doc_url_base): self.client = client self.block_name = block_name self.block_data = block_data self.doc_url_base = doc_url_base self.parts = OrderedDict() # Make an icon self._make_icon_label() for field_name, field_data in block_data.fields.items(): self.make_parts_for(field_name, field_data)
def _get_flowgraph_ports(self, direction="out"): # {attr_name: port_tag} ports = OrderedDict() for attr_name in self.child.endpoints: attr = self.child[attr_name] if isinstance(attr, Attribute): for tag in attr.meta.tags: if tag.startswith("%sport" % direction): ports[attr] = tag return ports
def set_elements(self, elements): # type: (ATableElements) -> ATableElements """Set the elements dict from a serialized dict""" deserialized = OrderedDict() for k, v in elements.items(): if k != "typeid": deserialized[k] = deserialize_object(v, VArrayMeta) ret = self.set_endpoint_data("elements", deserialized) self.set_table_cls(self.table_cls) return ret
def test_init(self): expected = OrderedDict() expected["Resetting"] = {"Ready", "Fault", "Disabling"} expected["Ready"] = {"Saving", "Fault", "Disabling", "Loading"} expected["Saving"] = {"Fault", "Ready", "Disabling"} expected["Loading"] = {"Disabling", "Fault", "Ready"} expected["Fault"] = {"Resetting", "Disabling"} expected["Disabling"] = {"Disabled", "Fault"} expected["Disabled"] = {"Resetting"} assert self.o._allowed == expected
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 set_elements(self, elements): # type: (AElements) -> AElements deserialized = OrderedDict() for k, v in elements.items(): if k != "typeid": v = deserialize_object(v, VMeta) if not v.label: v.set_label(camel_to_title(k)) deserialized[k] = v return self.set_endpoint_data("elements", deserialized)
def _mark_clean(self, design): with self.changes_squashed: self.saved_visibility = self.layout.value.visible self.saved_exports = self.exports.value.to_dict() # Now we are clean, modified should clear self.part_modified = OrderedDict() self.update_modified() self._set_layout_names(design) self.design.set_value(design) self._update_block_endpoints()
def _make_blocks_parts(self): # {block_name_without_number: BlockData} self._blocks_data = OrderedDict() self._blocks_parts = OrderedDict() for block_rootname, block_data in self.client.get_blocks_data().items(): block_names = [] if block_data.number == 1: block_names.append(block_rootname) else: for i in range(block_data.number): block_names.append("%s%d" % (block_rootname, i + 1)) for block_name in block_names: self._blocks_data[block_name] = block_data self._make_parts(block_name, block_data) # Handle the initial set of changes to get an initial value self.handle_changes(self.client.get_changes()) # Then once more to let bit_outs toggle back self.handle_changes(()) assert not self.changes, "There are still changes %s" % self.changes
def on_save(self, context: AContext) -> AStructure: child = context.block_view(self.mri) part_structure = OrderedDict() for k in child: if self._unmanaged_attr(k): attr = getattr(child, k) if isinstance(attr, Attribute) and get_config_tag(attr.meta.tags): part_structure[k] = attr.value self.saved_structure = part_structure return part_structure
def test_init(self): expected = OrderedDict() expected['Resetting'] = {'Ready', 'Fault', 'Disabling'} expected['Ready'] = {'Saving', "Fault", "Disabling", "Loading"} expected['Saving'] = {'Fault', 'Ready', 'Disabling'} expected['Loading'] = {'Disabling', 'Fault', 'Ready'} expected['Fault'] = {"Resetting", "Disabling"} expected['Disabling'] = {"Disabled", "Fault"} expected['Disabled'] = {"Resetting"} assert self.o._allowed == expected
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 execute(self, args): self.log_debug("Execute %s method called on [%s] with: %s", self._method, self._block, args) self.log_debug("Structure: %s", args.getStructureDict()) # Acquire the lock with self._lock: try: # We now need to create the Post message and execute it endpoint = [self._block, self._method] request = Post(None, self._server.q, endpoint, self.parse_variants(args.toDict(True))) request.set_id(self._id) self._server.process.q.put(request) # Now wait for the Post reply self.log_debug("Waiting for reply") self.wait_for_reply(timeout=None) self.log_debug("Reply received %s %s", type(self._response), self._response) response_dict = OrderedDict() if isinstance(self._response, Return): response_dict = self._response["value"] self.log_debug("Response value : %s", response_dict) elif isinstance(self._response, Error): response_dict = self._response.to_dict() response_dict.pop("id") if not response_dict: pv_object = pvaccess.PvObject(OrderedDict(), 'malcolm:core/Map:1.0') else: #pv_object = self._server.dict_to_structure(response_dict) #self.log_debug("Pv Object structure created") #self.log_debug("%s", self._server.strip_type_id(response_dict)) #pv_object.set(self._server.strip_type_id(response_dict)) pv_object = self._server.dict_to_pv_object(response_dict) self.log_debug("Pv Object value set: %s", pv_object) # Add this RPC to the purge list #self._server.register_dead_rpc(self._id) return pv_object except Exception: self.log_exception("Request %s failed", self._request)
def test_blocks_update(self): msg = OrderedDict() msg['typeid'] = "malcolm:core/Subscribe:1.0" msg['id'] = 0 msg['path'] = (".", "blocks", "value") msg['delta'] = False IOLoopHelper.call(self.send_message, msg) resp = self.result.get(timeout=2) assert resp == dict(typeid="malcolm:core/Update:1.0", id=0, value=["hello", "server"])
def test_error_server_and_simple_client_no_path(self): msg = OrderedDict() msg['typeid'] = "malcolm:core/Post:1.0" msg['id'] = 0 IOLoopHelper.call(self.send_message, msg) resp = self.result.get(timeout=2) assert resp == dict( typeid="malcolm:core/Error:1.0", id=0, message= 'ValueError: Expected a path with at least 1 element, got []')
def test_error_server_and_simple_client_no_id(self): msg = OrderedDict() msg['typeid'] = "malcolm:core/Post:1.0" msg['path'] = ("hello", "greet") msg['parameters'] = dict(name="me") IOLoopHelper.call(self.send_message, msg) resp = self.result.get(timeout=2) assert resp == dict( typeid="malcolm:core/Error:1.0", id=-1, message="FieldError: id field not present in JSON message")
def test_server_and_simple_client(self): msg = OrderedDict() msg['typeid'] = "malcolm:core/Post:1.0" msg['id'] = 0 msg['path'] = ("hello", "greet") msg['parameters'] = dict(name="me") IOLoopHelper.call(self.send_message, msg) resp = self.result.get(timeout=2) assert resp == dict(typeid="malcolm:core/Return:1.0", id=0, value="Hello me")
def test_blocks_delta(self): msg = OrderedDict() msg['typeid'] = "malcolm:core/Subscribe:1.0" msg['id'] = 0 msg['path'] = (".", "blocks", "value") msg['delta'] = True IOLoopHelper.call(self.send_message, msg) resp = self.result.get(timeout=2) assert resp == dict(typeid="malcolm:core/Delta:1.0", id=0, changes=[[[], ["hello", "server"]]])
def set_parameters(self, parameters): """Parameters to Post to endpoint Args: parameters: Value to post to path """ if parameters is not None: parameters = OrderedDict( (deserialize_object(k, str_), serialize_object(v)) for k, v in parameters.items()) self.parameters = parameters
def convert_value_to_dict(v): # type: (Value) -> Dict d = OrderedDict() # Fill in typeid if set typeid = v.getID() if typeid != "structure": d["typeid"] = typeid # Fill in all the fields for name, spec in v.type().items(): d[name] = convert_from_type_spec(spec, v[name]) return d
def create_process_block(self): self.process_block = Block() # TODO: add a meta here children = OrderedDict() children["blocks"] = StringArrayMeta( description="Blocks hosted by this Process").make_attribute([]) children["remoteBlocks"] = StringArrayMeta( description="Blocks reachable via ClientComms").make_attribute([]) self.process_block.replace_endpoints(children) self.process_block.set_process_path(self, [self.name]) self.add_block(self.process_block, self)
def add_controller(controller: Controller) -> OrderedDict: children = OrderedDict() tree[controller.mri] = children for part in controller.parts.values(): part_mri = getattr(part, "mri", None) is_child.add(part_mri) if part_mri in tree: children[part_mri] = tree[part_mri] elif part_mri in self._controllers: children[part_mri] = add_controller(self._controllers[part_mri]) return tree[controller.mri]
def _setup_parts(self, parts, controller_name): parts_dict = OrderedDict() for part in parts: part.set_logger_name("%s.%s" % (controller_name, part.name)) # Check part hooks into one of our hooks for func_name, part_hook, _ in get_hook_decorated(part): assert part_hook in self.hook_names, \ "Part %s func %s not hooked into %s" % ( part.name, func_name, self) parts_dict[part.name] = part return parts_dict
def test_error_server_and_simple_client_bad_path_controller(self): msg = OrderedDict() msg['typeid'] = "malcolm:core/Post:1.0" msg['id'] = 0 msg['path'] = ("goodbye", "insult") msg['parameters'] = dict(name="me") IOLoopHelper.call(self.send_message, msg) resp = self.result.get(timeout=2) assert resp == dict( typeid="malcolm:core/Error:1.0", id=0, message="ValueError: No controller registered for mri 'goodbye'")
def test_error_server_and_simple_client_bad_type(self): msg = OrderedDict() msg['typeid'] = "NotATypeID" msg['id'] = 0 msg['path'] = ("hello", "greet") msg['parameters'] = dict(name="me") IOLoopHelper.call(self.send_message, msg) resp = self.result.get(timeout=2) assert resp == dict( typeid="malcolm:core/Error:1.0", id=0, message="FieldError: 'NotATypeID' not a valid typeid")
def pva_structure_from_value(value, empty_allowed=False): # Create pv structure if value is None: structure = pvaccess.PvObject({}) elif isinstance(value, str_): structure = pvaccess.STRING elif isinstance(value, bool): structure = pvaccess.BOOLEAN elif isinstance(value, (int, long_)): structure = pvaccess.LONG elif isinstance(value, float): structure = pvaccess.DOUBLE elif isinstance(value, np.number): structure = pva_dtypes[value.dtype.type] elif isinstance(value, np.ndarray): assert len(value.shape) == 1, \ "Expected 1d array, got {}".format(value.shape) structure = [pva_dtypes[value.dtype.type]] elif isinstance(value, StringArray): structure = [pvaccess.STRING] elif isinstance(value, list): # if not empty then determine its type structures = set() for v in value: v_structure = pva_structure_from_value(v) if isinstance(v_structure, pvaccess.PvObject): # variant union structures.add(()) else: structures.add(v_structure) structure = list(structures) if len(structure) == 0 or len(structure) > 1: # variant union structure = [()] elif isinstance(value, dict): # structure structure = OrderedDict() typeid = "" for k, v in value.items(): if k == "typeid": typeid = v else: subtyp = pva_structure_from_value(v) if subtyp is not None: structure[k] = subtyp if structure or empty_allowed: structure = pvaccess.PvObject(structure, typeid) else: structure = None else: raise ValueError("Cannot get pva type from %s %r" % (type(value), value)) return structure
def do_save(self, design=""): if not design: design = self.design.value assert design, "Please specify save design name when saving from new" assert not design.startswith( "template_"), "Cannot save over a template" structure = OrderedDict() attributes = structure.setdefault("attributes", OrderedDict()) # Add the layout table layout = attributes.setdefault("layout", OrderedDict()) for name, mri, x, y, visible in self.layout.value.rows(): layout_structure = OrderedDict() layout_structure["x"] = x layout_structure["y"] = y layout_structure["visible"] = visible layout[name] = layout_structure # Add the exports table exports = attributes.setdefault("exports", OrderedDict()) for source, export in self.exports.value.rows(): exports[source] = export # Add other attributes for name, attribute in self.our_config_attributes.items(): attributes[name] = attribute.value # Add any structure that a child part wants to save structure["children"] = self.run_hooks( SaveHook(p, c) for p, c in self.create_part_contexts(only_visible=False).items()) text = json_encode(structure, indent=2) filename = self._validated_config_filename(design) if filename.startswith("/tmp"): self.log.warning("Saving to tmp directory %s" % filename) with open(filename, "w") as f: f.write(text) # Run a sync command to make sure we flush this file to disk subprocess.call("sync") # Try and commit the file to git, don't care if it fails self._run_git_cmd("add", filename) msg = "Saved %s %s" % (self.mri, design) self._run_git_cmd("commit", "--allow-empty", "-m", msg, filename) self._mark_clean(design)
def do_save(self, design=""): if not design: design = self.design.value assert design, "Please specify save design name when saving from new" structure = OrderedDict() # Add the layout table part_layouts = {} 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 part_layouts[name] = layout_structure structure["layout"] = OrderedDict() for part_name in self.parts: if part_name in part_layouts: structure["layout"][part_name] = part_layouts[part_name] # Add the exports table structure["exports"] = OrderedDict() for name, export_name in sorted( zip(self.exports.value.name, self.exports.value.exportName)): structure["exports"][name] = export_name # Add any structure that a child part wants to save part_structures = self.run_hook( self.Save, self.create_part_contexts(only_visible=False)) for part_name, part_structure in sorted(part_structures.items()): structure[part_name] = part_structure text = json_encode(structure, indent=2) filename = self._validated_config_filename(design) with open(filename, "w") as f: f.write(text) if os.path.isdir(os.path.join(self.params.configDir, ".git")): # Try and commit the file to git, don't care if it fails self._run_git_cmd("add", filename) msg = "Saved %s %s" % (self.mri, design) self._run_git_cmd("commit", "--allow-empty", "-m", msg, filename) self._mark_clean(design)
def test_error_server_and_simple_client_superfluous_params(self): msg = OrderedDict() msg['typeid'] = "malcolm:core/Get:1.0" msg['id'] = 0 msg['path'] = ("hello", "meta") msg['parameters'] = dict(name="me") IOLoopHelper.call(self.send_message, msg) resp = self.result.get(timeout=2) assert resp == dict( typeid="malcolm:core/Error:1.0", id=0, message="TypeError: malcolm:core/Get:1.0 raised error: " + "__init__() got an unexpected keyword argument 'parameters'")
def convert_value_to_dict(v: Value) -> Dict: d = OrderedDict() # Fill in typeid if set typeid = v.getID() if typeid != "structure": d["typeid"] = typeid # Fill in all the fields for name, spec in v.type().items(): if typeid == NTTable.typeid and name == "labels": # NTTable might give us labels, ignore them continue d[name] = convert_from_type_spec(spec, v[name]) return d