class PoolBaseController(PoolBaseElement): """Base class for all controllers""" def __init__(self, **kwargs): self._ctrl = None self._ctrl_error = None self._element_ids = {} self._pending_element_ids = {} self._element_axis = {} self._pending_element_axis = {} self._element_names = CaselessDict() self._pending_element_names = CaselessDict() self._operator = None kwargs['elem_type'] = ElementType.Controller super(PoolBaseController, self).__init__(**kwargs) def get_ctrl_types(self): raise NotImplementedError def get_ctrl_type_names(self): return list(map(ElementType.whatis, self.get_ctrl_types())) def is_online(self): return True def get_ctrl_error(self): return self._ctrl_error def get_ctrl_error_str(self): """""" err = self._ctrl_error if err is None: return "" sio = io.StringIO() traceback.print_exception(err[0], err[1], err[2], None, sio) s = sio.getvalue() sio.close() if s[-1:] == "\n": s = s[:-1] return s def add_element(self, elem, propagate=1): name, axis, eid = elem.get_name(), elem.get_axis(), elem.get_id() if self.is_online(): try: self._ctrl.AddDevice(axis) except: self.error("Unable to add %s(%s)", name, axis, exc_info=1) self._pending_element_ids[eid] = elem self._pending_element_axis[axis] = elem self._pending_element_names[name] = elem self._element_ids[eid] = elem self._element_axis[axis] = elem self._element_names[name] = elem else: # TODO: raise exception self._pending_element_ids[eid] = elem self._pending_element_axis[axis] = elem self._pending_element_names[name] = elem if propagate: elements = self.get_elements() elements = [elements[_id].name for _id in sorted(elements)] self.fire_event(EventType("elementlist", priority=propagate), elements) def remove_element(self, elem, propagate=1): name, axis, eid = elem.get_name(), elem.get_axis(), elem.get_id() f = eid in self._element_ids if not f: f = eid in self._pending_element_ids if not f: raise Exception("element '%s' is not in controller") del self._pending_element_ids[eid] del self._pending_element_axis[axis] del self._pending_element_names[name] else: del self._element_ids[eid] del self._element_axis[axis] del self._element_names[name] try: self._ctrl.DeleteDevice(axis) except: self.error("Unable to delete %s(%s)", name, axis, exc_info=1) if propagate: elements = self.get_elements() elements = [elements[_id].name for _id in sorted(elements)] self.fire_event(EventType("elementlist", priority=propagate), elements) def rename_element(self, old_name, new_name, propagate=1): """Rename element in the controller. :param old_name: old name of the element :type old_name: :obj:`str` :param new_name: new name of the element :type new_name: :obj:`str` :param propagate: 0 for not propagating, 1 to propagate, 2 propagate with priority :type propagate: :obj:`int` """ element = self._element_names.pop(old_name, None) if element is None: raise KeyError('There is no element with name %s' % old_name) self._element_names[new_name] = element if propagate: elements = self.get_elements() elements = [elements[_id].name for _id in sorted(elements)] self.fire_event(EventType("elementlist", priority=propagate), elements) def remove_axis(self, axis, propagate=1): f = axis in self._element_axis if not f: f = axis in self._pending_element_axis if not f: raise Exception("element '%s' is not in controller") elem = self._pending_element_axis[axis] else: elem = self._element_axis[axis] self.remove_element(elem, propagate=propagate) def get_elements(self): return self._element_ids def get_element_ids(self): return self._element_ids def get_element_axis(self): return self._element_axis def get_element(self, **kwargs): k = kwargs.get('axis') if k is None: k = kwargs.get('name') if k is None: k = kwargs.get('id') if k is None: raise Exception("Must give either name, id or axis") d, pd = self._element_ids, self._pending_element_ids else: d, pd = self._element_names, self._pending_element_names else: d, pd = self._element_axis, self._pending_element_axis elem = d.get(k) if elem is None: elem = pd.get(k) return elem def read_axis_states(self, axes=None): """Reads the state for the given axes. If axes is None, reads the state of all active axes. :param axes: the list of axis to get the state. Default is None meaning all active axis in this controller :type axes: seq<int> or None :return: a map containing the controller state information for each axis :rtype: dict<PoolElement, state info> """ raise NotImplementedError def read_axis_values(self, axes=None): """Reads the value for the given axes. If axes is None, reads the value of all active axes. :param axes: the list of axis to get the value. Default is None meaning all active axis in this controller :type axes: seq<int> or None :return: a map containing the controller value information for each axis :rtype: dict<PoolElement, value> """ raise NotImplementedError def get_status(self, cache=True, propagate=1): """Returns the status for this object. If cache is True (default) it returns the current status stored in cache (it will force an update if cache is empty). If propagate > 0 and if the status changed since last read, it will propagate the status event to all listeners. :param cache: tells if return value from local cache or update from HW read [default: True] :type cache: bool :param propagate: if > 0 propagates the event in case it changed since last HW read. Values bigger that mean the event if sent should be a priority event [default: 1] :type propagate: int :return: the current object status :rtype: str""" if not cache or self._status is None: state_info = None self._set_state_info(state_info, propagate=propagate) return self._status _STD_STATUS = '{name} is {state}' def calculate_state_info(self, status_info=None): """Transforms the given state information. This specific base implementation transforms the given state,status tuple into a state, new_status tuple where new_status is "*self.name* is *state*. :param status_info: given status information [default: None, meaning use current state status. :type status_info: tuple<State, str> :return: a transformed state information :rtype: tuple<State, str>""" if status_info is None: status_info = self._state, self._status state, _ = status_info state_str = State[state] new_status = self._STD_STATUS.format(name=self.name, state=state_str) return status_info[0], new_status
class SardanaContainer(object): """A container class for sardana elements""" def __init__(self): # map of all elements # key - element ID # value - pointer to the element object self._element_ids = {} # map of all elements by name # key - element name # value - pointer to the element object self._element_names = CaselessDict() # map of all elements by name # key - element full name # value - pointer to the element object self._element_full_names = CaselessDict() # map of all elements by type # key - element type # value - map where: # key - element ID # value - pointer to the element object self._element_types = {} def add_element(self, e): """Adds a new :class:`pool.PoolObject` to this container :param e: the pool element to be added :type e: :class:`pool.PoolObject` """ name, full_name, id = e.get_name(), e.get_full_name(), e.get_id() elem_type = e.get_type() self._element_ids[id] = e self._element_names[name] = e self._element_full_names[full_name] = e type_elems = self._element_types.get(elem_type) if type_elems is None: self._element_types[elem_type] = type_elems = {} type_elems[id] = e return e def remove_element(self, e): """Removes the :class:`pool.PoolObject` from this container :param e: the pool object to be removed :type e: :class:`pool.PoolObject` :throw: KeyError """ name, full_name, id = e.get_name(), e.get_full_name(), e.get_id() elem_type = e.get_type() del self._element_ids[id] del self._element_names[name] del self._element_full_names[full_name] type_elems = self._element_types.get(elem_type) del type_elems[id] def get_element_id_map(self): """Returns a reference to the internal pool object ID map :return: the internal pool object ID map :rtype: dict<id, pool.PoolObject> """ return self._element_ids def get_element_name_map(self): """Returns a reference to the internal pool object name map :return: the internal pool object name map :rtype: dict<str, pool.PoolObject> """ return self._element_names def get_element_type_map(self): """Returns a reference to the internal pool object type map :return: the internal pool object type map :rtype: dict<pool.ElementType, dict<id, pool.PoolObject>> """ return self._element_types def get_element(self, **kwargs): """Returns a reference to the requested pool object :param kwargs: if key 'id' given: search by ID else if key 'full_name' given: search by full name else if key 'name' given: search by name :return: the pool object :rtype: pool.PoolObject :throw: KeyError """ if kwargs.has_key("id"): id = kwargs.pop("id") return self.get_element_by_id(id, **kwargs) if kwargs.has_key("full_name"): full_name = kwargs.pop("full_name") return self.get_element_by_full_name(full_name, **kwargs) name = kwargs.pop("name") return self.get_element_by_name(name, **kwargs) def get_element_by_name(self, name, **kwargs): """Returns a reference to the requested pool object :param name: pool object name :type name: str :return: the pool object :rtype: pool.PoolObject :throw: KeyError """ ret = self._element_names.get(name) if ret is None: raise KeyError("There is no element with name '%s'" % name) return ret def get_element_by_full_name(self, full_name, **kwargs): """Returns a reference to the requested pool object :param name: pool object full name :type name: str :return: the pool object :rtype: pool.PoolObject :throw: KeyError """ ret = self._element_full_names.get(full_name) if ret is None: raise KeyError("There is no element with full name '%s'" % full_name) return ret def get_element_by_id(self, id, **kwargs): """Returns a reference to the requested pool object :param id: pool object ID :type id: int :return: the pool object :rtype: pool.PoolObject :throw: KeyError """ ret = self._element_ids.get(id) if ret is None: raise KeyError("There is no element with ID '%d'" % id) return ret def get_elements_by_type(self, t): """Returns a list of all pool objects of the given type :param t: element type :type t: pool.ElementType :return: list of pool objects :rtype: seq<pool.PoolObject> """ elem_types_dict = self._element_types.get(t) if elem_types_dict is None: return [] return elem_types_dict.values() def get_element_names_by_type(self, t): """Returns a list of all pool object names of the given type :param t: element type :type t: pool.ElementType :return: list of pool object names :rtype: seq<str> """ return [elem.get_name() for elem in self.get_elements_by_type(t)] def rename_element(self, old_name, new_name): """Rename an object :param old_name: old object name :type old_name: str :param new_name: new object name :type new_name: str """ element = self._element_names.pop(old_name, None) if element is None: raise KeyError('There is no element with name %s' % old_name) element.name = new_name self._element_names[new_name] = element def check_element(self, name, full_name): raise_element_name = True try: elem = self.get_element(name=name) except: raise_element_name = False if raise_element_name: elem_type = ElementType[elem.get_type()] raise Exception("A %s with name '%s' already exists" % (elem_type, name)) raise_element_full_name = True try: elem = self.get_element(full_name=full_name) except: raise_element_full_name = False if raise_element_full_name: elem_type = ElementType[elem.get_type()] raise Exception("A %s with full name '%s' already exists" % (elem_type, full_name))
class SardanaContainer(object): """A container class for sardana elements""" def __init__(self): # map of all elements # key - element ID # value - pointer to the element object self._element_ids = {} # map of all elements by name # key - element name # value - pointer to the element object self._element_names = CaselessDict() # map of all elements by name # key - element full name # value - pointer to the element object self._element_full_names = CaselessDict() # map of all elements by type # key - element type # value - map where: # key - element ID # value - pointer to the element object self._element_types = {} def add_element(self, e): """Adds a new :class:`pool.PoolObject` to this container :param e: the pool element to be added :type e: :class:`pool.PoolObject` """ name, full_name, id = e.get_name(), e.get_full_name(), e.get_id() elem_type = e.get_type() self._element_ids[id] = e self._element_names[name] = e self._element_full_names[full_name] = e type_elems = self._element_types.get(elem_type) if type_elems is None: self._element_types[elem_type] = type_elems = {} type_elems[id] = e return e def remove_element(self, e): """Removes the :class:`pool.PoolObject` from this container :param e: the pool object to be removed :type e: :class:`pool.PoolObject` :throw: KeyError """ name, full_name, id = e.get_name(), e.get_full_name(), e.get_id() elem_type = e.get_type() del self._element_ids[id] del self._element_names[name] del self._element_full_names[full_name] type_elems = self._element_types.get(elem_type) del type_elems[id] def get_element_id_map(self): """Returns a reference to the internal pool object ID map :return: the internal pool object ID map :rtype: dict<id, pool.PoolObject> """ return self._element_ids def get_element_name_map(self): """Returns a reference to the internal pool object name map :return: the internal pool object name map :rtype: dict<str, pool.PoolObject> """ return self._element_names def get_element_type_map(self): """Returns a reference to the internal pool object type map :return: the internal pool object type map :rtype: dict<pool.ElementType, dict<id, pool.PoolObject>> """ return self._element_types def get_element(self, **kwargs): """Returns a reference to the requested pool object :param kwargs: if key 'id' given: search by ID else if key 'full_name' given: search by full name else if key 'name' given: search by name :return: the pool object :rtype: pool.PoolObject :throw: KeyError """ if kwargs.has_key("id"): id = kwargs.pop("id") return self.get_element_by_id(id, **kwargs) if kwargs.has_key("full_name"): full_name = kwargs.pop("full_name") return self.get_element_by_full_name(full_name, **kwargs) name = kwargs.pop("name") return self.get_element_by_name(name, **kwargs) def get_element_by_name(self, name, **kwargs): """Returns a reference to the requested pool object :param name: pool object name :type name: :obj:`str` :return: the pool object :rtype: pool.PoolObject :throw: KeyError """ ret = self._element_names.get(name) if ret is None: raise KeyError("There is no element with name '%s'" % name) return ret def get_element_by_full_name(self, full_name, **kwargs): """Returns a reference to the requested pool object :param name: pool object full name :type name: :obj:`str` :return: the pool object :rtype: pool.PoolObject :throw: KeyError """ ret = self._element_full_names.get(full_name) if ret is None: raise KeyError( "There is no element with full name '%s'" % full_name) return ret def get_element_by_id(self, id, **kwargs): """Returns a reference to the requested pool object :param id: pool object ID :type id: int :return: the pool object :rtype: pool.PoolObject :throw: KeyError """ ret = self._element_ids.get(id) if ret is None: raise KeyError("There is no element with ID '%d'" % id) return ret def get_elements_by_type(self, t): """Returns a list of all pool objects of the given type :param t: element type :type t: pool.ElementType :return: list of pool objects :rtype: seq<pool.PoolObject> """ elem_types_dict = self._element_types.get(t) if elem_types_dict is None: return [] return elem_types_dict.values() def get_element_names_by_type(self, t): """Returns a list of all pool object names of the given type :param t: element type :type t: pool.ElementType :return: list of pool object names :rtype: seq<str> """ return [elem.get_name() for elem in self.get_elements_by_type(t)] def rename_element(self, old_name, new_name): """Rename an object :param old_name: old object name :type old_name: :obj:`str` :param new_name: new object name :type new_name: :obj:`str` """ element = self._element_names.pop(old_name, None) if element is None: raise KeyError('There is no element with name %s' % old_name) element.name = new_name self._element_names[new_name] = element def check_element(self, name, full_name): raise_element_name = True try: elem = self.get_element(name=name) except: raise_element_name = False if raise_element_name: elem_type = ElementType[elem.get_type()] raise Exception("A %s with name '%s' already exists" % (elem_type, name)) raise_element_full_name = True try: elem = self.get_element(full_name=full_name) except: raise_element_full_name = False if raise_element_full_name: elem_type = ElementType[elem.get_type()] raise Exception("A %s with full name '%s' already exists" % (elem_type, full_name))