Exemple #1
0
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
Exemple #2
0
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))