Source code for taurus.core.taurusdatabase

#!/usr/bin/env python

#############################################################################
##
## This file is part of Taurus
## 
## http://taurus-scada.org
##
## Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
## 
## Taurus is free software: you can redistribute it and/or modify
## it under the terms of the GNU Lesser General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
## 
## Taurus is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU Lesser General Public License for more details.
## 
## You should have received a copy of the GNU Lesser General Public License
## along with Taurus.  If not, see <http://www.gnu.org/licenses/>.
##
#############################################################################

"""This module contains the base class for a taurus database"""

__all__ = ["TaurusInfo", "TaurusDevInfo", "TaurusServInfo", "TaurusDevClassInfo",
           "TaurusAttrInfo", "TaurusDevTree", "TaurusServerTree",
           "TaurusDatabaseCache", "TaurusDatabase"]

__docformat__ = "restructuredtext"

import weakref
import operator

from .taurusbasetypes import TaurusEventType, TaurusSWDevHealth, TaurusElementType
from .taurusmodel import TaurusModel
from .util.containers import CaselessDict

DFT_DATABASE_DESCRIPTION = "A database"


[docs]class TaurusInfo(object): def __init__(self, container, name=None, full_name=None): self._container = weakref.ref(container) self._name = name self._full_name = full_name
[docs] def container(self): return self._container()
[docs] def name(self): return self._name
[docs] def fullName(self): return self._full_name
def __str__(self): return "%s(%s)" % (self.__class__.__name__, self.name()) __repr__ = __str__
[docs]class TaurusDevInfo(TaurusInfo): def __init__(self, container, name=None, full_name=None, alias=None, server=None, klass=None, exported=False, host=None): super(TaurusDevInfo, self).__init__(container, name=name, full_name=full_name) self._alias = alias self._server = weakref.ref(server) self._klass = weakref.ref(klass) self._exported = bool(int(exported)) self._alive = None self._health = None self._host = host self._domain, self._family, self._member = map(str.upper, name.split("/", 2)) self._attributes = None
[docs] def domain(self): return self._domain
[docs] def family(self): return self._family
[docs] def member(self): return self._member
[docs] def alias(self): return self._alias
[docs] def server(self): return self._server()
[docs] def klass(self): return self._klass()
[docs] def exported(self): return self._exported
[docs] def alive(self): return self._alive
[docs] def health(self): if self._health is None: if self.exported(): alive = self.alive() if alive == True: self._health = TaurusSWDevHealth.ExportedAlive elif alive == False: self._health = TaurusSWDevHealth.ExportedNotAlive else: self._health = TaurusSWDevHealth.Exported else: self._health = TaurusSWDevHealth.NotExported return self._health
[docs] def host(self): return self._host
[docs] def attributes(self): return self._attributes
[docs] def getAttribute(self, attrname): attrname= attrname.lower() for a in self.attributes(): if a.name() == attrname: return a return None
[docs] def setAttributes(self, attributes): self._attributes = attributes
[docs]class TaurusServInfo(TaurusInfo): def __init__(self, container, name=None, full_name=None): super(TaurusServInfo, self).__init__(container, name=name, full_name=full_name) self._devices = CaselessDict() self._exported = False self._alive = None self._host = "" self._server_name, self._server_instance = name.split("/", 1)
[docs] def devices(self): return self._devices
[docs] def getDeviceNames(self): if not hasattr(self, "_device_name_list"): self._device_name_list = sorted(map(TaurusDevInfo.name, self._devices.values())) return self._device_name_list
[docs] def getClassNames(self): if not hasattr(self, "_klass_name_list"): klasses = set(map(TaurusDevInfo.klass, self._devices.values())) self._klass_name_list = sorted(map(TaurusDevClassInfo.name, klasses)) return self._klass_name_list
[docs] def exported(self): return self._exported
[docs] def alive(self): return self._alive
[docs] def health(self): exported = self.exported() if exported: alive = self.alive() if alive == True: return TaurusSWDevHealth.ExportedAlive elif alive == False: return TaurusSWDevHealth.ExportedNotAlive else: return TaurusSWDevHealth.Exported return TaurusSWDevHealth.NotExported
[docs] def host(self): return self._host
[docs] def serverName(self): return self._server_name
[docs] def serverInstance(self): return self._server_instance
[docs] def addDevice(self, dev): self._exported |= dev.exported() self._host = dev.host() self._devices[dev.name()] = dev
[docs]class TaurusDevClassInfo(TaurusInfo): def __init__(self, container, name=None, full_name=None): super(TaurusDevClassInfo, self).__init__(container, name=name, full_name=full_name) self._devices = CaselessDict()
[docs] def devices(self): return self._devices
[docs] def getDeviceNames(self): if not hasattr(self, "_device_name_list"): self._device_name_list = sorted(map(TaurusDevInfo.name, self._devices.values())) return self._device_name_list
[docs] def addDevice(self, dev): self._devices[dev.name()] = dev
[docs]class TaurusAttrInfo(TaurusInfo): def __init__(self, container, name=None, full_name=None, device=None, info=None): super(TaurusAttrInfo, self).__init__(container, name=name, full_name=full_name) self._info = info self._device = weakref.ref(device)
[docs] def device(self): return self._device()
[docs] def info(self): return self._info
def __getattr__(self, name): return getattr(self._info, name)
[docs]class TaurusDevTree(CaselessDict): def __init__(self, other=None): super(TaurusDevTree, self).__init__() self._devices = CaselessDict() if other is not None: self._update(other) def _update(self, other): try: if operator.isMappingType(other): other = other.values() for dev in other: try: self.addDevice(dev) except Exception, e: print e except Exception, e: raise Exception("Must give dict<obj, TaurusDevInfo> or sequence<TaurusDevInfo>")
[docs] def addDevice(self, dev_info): domain, family, member = dev_info.domain(), dev_info.family(), dev_info.member() families = self[domain] = self.get(domain, CaselessDict()) devs = self._devices[domain] = self._devices.get(domain, CaselessDict()) devs[dev_info.name()] = dev_info families[family] = members = families.get(family, CaselessDict()) members[member] = dev_info
[docs] def getDomainDevices(self, domain): """Returns all devices under the given domain. Returns empty list if the domain doesn't exist or doesn't contain any devices""" return self._devices.get(domain, {}).values()
[docs] def getFamilyDevices(self, domain, family): """Returns all devices under the given domain/family. Returns empty list if the domain/family doesn't exist or doesn't contain any devices""" families = self.get(domain) if families is None: return return families.get(family, {}).values()
[docs]class TaurusServerTree(dict): def __init__(self, other=None): super(TaurusServerTree, self).__init__() if other is not None: self._update(other) def _update(self, other): try: if operator.isMappingType(other): other = other.values() for serv in other: try: self.addServer(serv) except Exception, e: print e except Exception, e: raise Exception("Must give dict<obj, TaurusServInfo> or sequence<TaurusServInfo>")
[docs] def addServer(self, serv_info): serverName, serverInstance = serv_info.serverName(), serv_info.serverInstance() serverInstances = self[serverName] = self.get(serverName, {}) serverInstances[serverInstance] = serv_info
[docs] def getServerNameInstances(self, serverName): """Returns all servers under the given serverName. Returns empty list if the server name doesn't exist or doesn't contain any instances""" return self.get(serverName, {}).values()
[docs]class TaurusDatabaseCache(object): def __init__(self, db): self._db = weakref.ref(db) self._device_tree = None self._server_tree = None self._servers = None self._server_name_list = None self._devices = None self._device_name_list = None self._klasses = None self._klass_name_list = None self._aliases = None self._alias_name_list = None self.refresh() @property def db(self): return self._db()
[docs] def refresh(self): raise RuntimeError("Must be implemented in subclass")
[docs] def refreshAttributes(self, device): raise RuntimeError("Must be implemented in subclass")
[docs] def getDevice(self, name): """Returns a :class:`taurus.core.taurusdatabase.TaurusDevInfo` object with information about the given device name :param name: (str) the device name :return: (TaurusDevInfo) information about the device""" return self._devices.get(name)
[docs] def getDeviceNames(self): """Returns a list of registered device names :return: (sequence<str>) a sequence with all registered device names""" if self._device_name_list is None: self._device_name_list = sorted(map(TaurusDevInfo.name, self.devices().values())) return self._device_name_list
[docs] def getAliasNames(self): if self._alias_name_list is None: self._alias_name_list = sorted(map(TaurusDevInfo.alias, self.aliases().values())) return self._alias_name_list
[docs] def getServerNames(self): """Returns a list of registered server names :return: (sequence<str>) a sequence with all registered server names""" if self._server_name_list is None: self._server_name_list = sorted(map(TaurusServInfo.name, self.servers().values())) return self._server_name_list
[docs] def getClassNames(self): """Returns a list of registered device classes :return: (sequence<str>) a sequence with all registered device classes""" if self._klass_name_list is None: self._klass_name_list = sorted(map(TaurusDevClassInfo.name, self.klasses().values())) return self._klass_name_list
[docs] def deviceTree(self): """Returns a tree container with all devices in three levels: domain, family and member :return: (TaurusDevTree) a tree containning all devices""" return self._device_tree
[docs] def serverTree(self): """Returns a tree container with all servers in two levels: server name and server instance :return: (TaurusServerTree) a tree containning all servers""" return self._server_tree
[docs] def servers(self): return self._servers
[docs] def devices(self): return self._devices
[docs] def klasses(self): return self._klasses
[docs] def getDeviceDomainNames(self): return self._device_tree.keys()
[docs] def getDeviceFamilyNames(self, domain): families = self._device_tree.get(domain) if families is None: return [] return families.keys()
[docs] def getDeviceMemberNames(self, domain, family): families = self._device_tree.get(domain) if families is None: return [] members = families.get(family) if members is None: return [] return members.keys()
[docs] def getDomainDevices(self, domain): return self.deviceTree().getDomainDevices(domain)
[docs] def getFamilyDevices(self, domain, family): return self.deviceTree().getFamilyDevices(domain, family)
[docs] def getServerNameInstances(self, serverName): return self.serverTree().getServerNameInstances(serverName)
[docs]class TaurusDatabase(TaurusModel): def __init__(self, complete_name, parent=None): self._descr = None self.call__init__(TaurusModel, complete_name, parent) #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- # TaurusModel implementation #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
[docs] def cleanUp(self): self.trace("[TaurusDatabase] cleanUp") TaurusModel.cleanUp(self)
@classmethod
[docs] def getTaurusElementType(cls): return TaurusElementType.Database
@classmethod
[docs] def buildModelName(cls, parent_model, relative_name): """build an 'absolute' model name from the parent name and the 'relative' name. parent_model is ignored since there is nothing above the Database object""" return relative_name
@classmethod
[docs] def getNameValidator(cls): from .taurusvalidator import DatabaseNameValidator return DatabaseNameValidator()
[docs] def getDescription(self,cache=True): if self._descr is None or not cache: try: self._descr = self.info() except: self._descr = self._getDefaultDescription() return self._descr
[docs] def getDisplayValue(self,cache=True): return self.getDisplayDescription(cache)
[docs] def getDisplayDescription(self,cache=True): return self.getFullName()
[docs] def getDisplayDescrObj(self,cache=True): obj = [] obj.append(('name', self.getDisplayName(cache=cache))) descr = self.getDescription(cache=cache) obj.append(('description', descr)) return obj
[docs] def addListener(self, listener): ret = TaurusModel.addListener(self, listener) if not ret: return ret self.fireEvent(TaurusEventType.Change, self.getDisplayValue(), listener) return ret
[docs] def getChildObj(self,child_name): if not child_name: return None return self.getDevice(child_name)
#-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- # Device access methods #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- def getDevice(self, devname): """Returns the device object given its name""" import taurusdevice return self.factory().getObject(taurusdevice.TaurusDevice, devname) #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- # Query capabilities built on top of a cache #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
[docs] def refreshCache(self): self.cache().refresh()
[docs] def getDevice(self, name): """Returns a :class:`taurus.core.tango.TangoDevInfo` object with information about the given device name :param name: (str) the device name :return: (TangoDevInfo) information about the tango device""" return self.cache().getDevice(name)
[docs] def getDeviceNames(self): """Returns a list of registered tango device names :return: (sequence<str>) a sequence with all registered tango device names""" return self.cache().getDeviceNames()
[docs] def getAliasNames(self): """Returns a list of registered tango device alias :return: (sequence<str>) a sequence with all registered tango device alias""" return self.cache().getAliasNames()
[docs] def getServerNames(self): """Returns a list of registered tango device servers in format<name>/<instance> :return: (sequence<str>) a sequence with all registered tango device servers""" return self.cache().getServerNames()
[docs] def getClassNames(self): """Returns a list of registered tango device classes :return: (sequence<str>) a sequence with all registered tango device classes""" return self.cache().getClassNames()
[docs] def getDeviceDomainNames(self): return self.cache().getDeviceDomainNames()
[docs] def getDeviceFamilyNames(self, domain): return self.cache().getDeviceFamilyNames(domain)
[docs] def getDeviceMemberNames(self, domain, family): return self.cache().getDeviceMemberNames(domain, family)
[docs] def getDomainDevices(self, domain): return self.cache().getDomainDevices(domain)
[docs] def getFamilyDevices(self, domain, family): return self.cache().getFamilyDevices(domain, family)
[docs] def getServerNameInstances(self, serverName): return self.cache().getServerNameInstances(serverName)
[docs] def deviceTree(self): """Returns a tree container with all devices in three levels : domain, family and member :return: (TangoDevTree) a tree containning all devices""" return self.cache().deviceTree()
#-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- # Mandatory methods to overwrite #-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
[docs] def cache(self): raise RuntimeError("TaurusDatabase.cache cannot be called")
[docs] def getElementAlias(self, full_name): raise RuntimeError("TaurusDatabase.getElementAlias cannot be called")
[docs] def getElementFullName(self, alias): raise RuntimeError("TaurusDatabase.getElementFullName cannot be called")
def _getDefaultDescription(self): return DFT_DATABASE_DESCRIPTION