From 48b207d452b450a26da7b01bada4809e20b994c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20L=C3=B3pez=20S=C3=A1nchez?= Date: Thu, 15 Jul 2021 11:09:45 +0000 Subject: [PATCH 1/2] fix: PoolTangoObject full_name discovery. The ways of retrieving the tango database host between PyTango and TangoNameValidators are inconsistent. For instance, inside a docker container PyTango returns .: while using a Taurus validator returns the host and port specified by the TANGO_HOST environment variable. Use Taurus validators instead of accessing PyTango database host and port API for discovery the full name of a PoolTangoObject. --- src/sardana/pool/poolexternal.py | 38 ++++++++++---------------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/src/sardana/pool/poolexternal.py b/src/sardana/pool/poolexternal.py index 38113f0003..72919d4919 100644 --- a/src/sardana/pool/poolexternal.py +++ b/src/sardana/pool/poolexternal.py @@ -53,35 +53,21 @@ def get_config(self): class PoolTangoObject(PoolBaseExternalObject): """TODO""" - def __init__(self, **kwargs): - scheme = kwargs.pop('scheme', 'tango') - attribute_name = kwargs.pop('_shortattrname') - host, port = kwargs.pop('host', None), kwargs.pop('port', None) - devalias = kwargs.pop('_devalias', None) - device_name = kwargs.pop('devname', None) - if host is None: - db = PyTango.Database() - host, port = db.get_db_host(), db.get_db_port() - else: - db = PyTango.Database(host, port) - full_name = "" - if device_name is None: - if devalias is not None: - try: - device_name = db.get_device_alias(devalias) - full_name = "tango://{0}:{1}/{2}/{3}".format( - host, port, device_name, attribute_name) - except: - full_name = "{0}/{1}".format(devalias, attribute_name) - else: - full_name = "tango://{0}:{1}/{2}/{3}".format( - host, port, device_name, attribute_name) - self._device_name = device_name - self._attribute_name = attribute_name + def __init__(self, pool, name): + validator = TangoAttributeNameValidator() + params = validator.getUriGroups(name) + full_name = "{}:{}{}".format(params['scheme'], params['authority'], params['path']) + name = "{}/{}".format(params['devname'], params['_shortattrname']) + self._device_name = params['devname'] + self._attribute_name = params['_shortattrname'] self._config = None self._device = None + # TODO evaluate to use alias instead of device_name - kwargs['name'] = '{0}/{1}'.format(device_name, attribute_name) + kwargs = {} + kwargs['scheme'] = params['scheme'] + kwargs['pool'] = pool + kwargs['name'] = name kwargs['full_name'] = full_name PoolBaseExternalObject.__init__(self, **kwargs) From 6bcefe0634003902b8fbaa16a8971101ef848403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20L=C3=B3pez=20S=C3=A1nchez?= Date: Thu, 15 Jul 2021 11:17:28 +0000 Subject: [PATCH 2/2] refactor: PoolExternalObject API. PoolExternalObject requires many kwargs describing the object identity, this forces the API users to discover those kwargs using Taurus validators. Since PoolTangoObject can do this discovery by itself, we decided to change the PoolExternalObject API and we adapted its usage in Sardana code base. --- src/sardana/pool/poolbasegroup.py | 5 +---- src/sardana/pool/poolexternal.py | 23 ++++++++++++++++++----- src/sardana/pool/poolmeasurementgroup.py | 5 +---- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/sardana/pool/poolbasegroup.py b/src/sardana/pool/poolbasegroup.py index 9beaf11b37..cdcb4c62df 100644 --- a/src/sardana/pool/poolbasegroup.py +++ b/src/sardana/pool/poolbasegroup.py @@ -171,10 +171,7 @@ def _build_elements(self): # a tango channel or non internal element (ex: ioregister or motor # in measurement group) if not internal: - validator = TangoAttributeNameValidator() - params = validator.getUriGroups(user_element_id) - params['pool'] = self._get_pool() - user_element = PoolExternalObject(**params) + user_element = PoolExternalObject(pool, user_element_id) self.add_user_element(user_element) self._pending = False diff --git a/src/sardana/pool/poolexternal.py b/src/sardana/pool/poolexternal.py index 72919d4919..0e3974628d 100644 --- a/src/sardana/pool/poolexternal.py +++ b/src/sardana/pool/poolexternal.py @@ -33,8 +33,9 @@ import PyTango from sardana import ElementType +import sardana from sardana.pool.poolbaseobject import PoolBaseObject - +from taurus.core.tango.tangovalidator import TangoAttributeNameValidator class PoolBaseExternalObject(PoolBaseObject): """TODO""" @@ -104,7 +105,19 @@ def get_config(self): None: PoolTangoObject} -def PoolExternalObject(**kwargs): - scheme = kwargs.get('scheme', 'tango') - klass = _SCHEME_CLASS[scheme] - return klass(**kwargs) +def PoolExternalObject(pool, name): + """ + Factory of Pool external objects. + + :param pool: The pool object. + :type pool: `sardana.pool.Pool` + :param name: The name of the external object (Any name accepted by Taurus + validators.). + :type name: `str` + :return: Pool external object. + :rtype: `sardana.pool.poolexternal.PoolBaseExternalObject` + """ + + scheme = name.split(":")[0] + klass = _SCHEME_CLASS.get(scheme, PoolTangoObject) + return klass(pool, name) diff --git a/src/sardana/pool/poolmeasurementgroup.py b/src/sardana/pool/poolmeasurementgroup.py index 86436a75f1..6f4e273fb8 100644 --- a/src/sardana/pool/poolmeasurementgroup.py +++ b/src/sardana/pool/poolmeasurementgroup.py @@ -794,11 +794,8 @@ def set_configuration_from_user(self, cfg): user_config_ctrl['channels'] = user_config_channel = {} for ch_name, ch_data in list(ctrl_data['channels'].items()): if external: - validator = TangoAttributeNameValidator() full_name = ch_data.get('full_name', ch_name) - params = validator.getUriGroups(full_name) - params['pool'] = pool - channel = PoolExternalObject(**params) + channel = PoolExternalObject(pool, full_name) else: channel = pool.get_element_by_full_name(ch_name) ch_data = self._fill_channel_data(channel, ch_data)