Title: Tango-Independent
TEP: 3
State: ACCEPTED
Date: 2016-03-16
Drivers: Carlos Falcon-Torres cfalcon@cells.es, Carlos Pascual-Izarra cpascual@cells.es
URL: https://sourceforge.net/p/tauruslib/wiki/TEP3
License: http://www.jclark.com/xml/copying.txt
Abstract:
The goal of this TEP is to refactor the Taurus core to make the Tango dependency optional instead of mandatory. The idea is to have a generic core that accepts any scheme without forcing PyTango.
This TEP describes an enhancement proposal for a refactoring of Taurus to make the Tango dependency optional instead of mandatory.
PS: see also [TEP14], which extends and complements this proposal.
The TEP3 was created from [sardana:wiki:SEP3] after the split of Taurus from sardana according to [sardana:wiki:SEP10].
Taurus evolved from Tau which was conceived as a library for creating GUIs & CLIs on top of a Tango control system. As such, Taurus models incorporate concepts such as “Device”, “Attribute”, etc that are heavily influenced by Tango.
Lately, however, Taurus models have been extended to allow the interaction with other control systems and/or hardware via the “schemes” extensions (current schemes are: “tango”, “simulation”, “eval”, “epics”, “spec”).
The tango scheme was the one initially developed, and is not completely isolated from the rest of Taurus. Taurus uses objects from the PyTango module, and assumes naming conventions in many parts of the code, making it impossible to even import taurus if Tango is not installed.
The objective of this proposal is to define a pure Taurus interface so that at least the Taurus core treats Tango just as another (optional) scheme.
It should be possible to use all the features of taurus.core without having PyTango installed. PyTango should not be imported and PyTango objects should not be assumed outside taurus.core.tango
A clear API should be offered to facilitate the creation of new schemes
A minimum set of functionality should be defined in an abstract Taurus API so that code using taurus.core can work transparently regardless of the type of scheme that provides the model object
The refactored taurus.core should be backwards-compatible in general, and in particular it must be backwards-compatible with the tango and evaluation schemes. In case of object name or other API changes, the old names/API should still be usable too (although deprecation warnings may be issued)
taurus.core must provide the following Base/Abstract classes to be inherited or used in each scheme:
TaurusFactory
TaurusAuthority (corresponding to which was previously known as TaurusDatabase)
TaurusDevice
TaurusAttribute
TaurusConfiguration
TaurusAuthorityNameValidator
TaurusDeviceNameValidator
TaurusAttributeNameValidator
TaurusConfigurationNameValidator
A scheme to be used in Taurus must provide the following classes (xxx is the name of the scheme, and the corresponding base class to use is given in parenthesis):
xxxFactory(TaurusFactory)
xxxAuthority(TaurusAuthority)
xxxDevice(TaurusDevice)
xxxAttribute(TaurusAttribute)
xxxConfiguration(TaurusConfiguration)
xxxAuthorityNameValidator(TaurusAuthorityNameValidator)
xxxDeviceNameValidator(TaurusDeviceNameValidator)
xxxAttributeNameValidator(TaurusAttributeNameValidator)
xxxConfigurationNameValidator(TaurusConfigurationNameValidator)
Keep in mind the following notes:
The value object returned when reading an attribute model object must be an instance of TaurusAttributeValue (or of a subclass of it).
The value object returned when reading a configuration model object must be an instance of TaurusConfigValue (or of a subclass of it).
Note: the validator classes should ideally be implemented using name parsing only (e.g. avoiding to instantiate TaurusModel ojects), and, if possible, avoid requiring the import of optional modules. The base classes provided for validators allow defining a new validator by providing just a few partial regexps for each URI component.
Users of Taurus are encouraged to write “scheme-agnostic” code whenever it is possible (e.g., code using the taurus.core should try to avoid assuming that a given attribute is of a certain scheme type).
Checks should be done (whenever it is possible) against the Base/Abstract classes instead of scheme-specific.
Also, taurus.core must provide the following scheme-agnostic factory functions:
Factory(modelname). Returns a xxxFactory instance.
Authority(modelname). Returns a xxxAuthority instance.
Device(modelname). Returns a xxxDevice instance.
Attribute(modelname). Returns a xxxAttribute instance.
Configuration(modelname). Returns a xxxConfiguration instance.
taurus.core should also provide utility functions for the following tasks:
find out cheaply whether a certain model name corresponds to a given Taurus Element Type (Attribute, Device, Database or Configuration). It can be achieved with taurus.isValidName()
find the scheme associated to a given model name. It can be achieved with taurus.getSchemeFromName()
find the supported schemes that are available.It can be achieved with taurus.Manager().getPlugins()
Tango models are case-insensitive, but this is not generally the case for other schemes. Case insensitivity is assumed in many parts of the code (e.g. through the use of CaselessList and CaselessDict containers to store models). The Factory classes should declare whether the scheme naming is case sensitive or not via a xxxFactory.caseSensitive class attribute (or property).
The refactoring of the validator classes brings the opportunity of making the model names proper URIs (i.e., to comply with RFC3986.
Parsing any Taurus model name must yield at least a dictionary with the
following keys: 'scheme', 'authority', 'path', 'query', 'fragment',
corresponding to the basic URI components. Additionally, the dictionary
resulting from parsing the URI of a Taurus device should contain the device name
under the key 'devname'. Similarly for the attribute name in the case of a
Taurus Attribute (under 'attrname') and for the configuration key in the case of
Configuration objects (under 'cfgkey').
Apart from the keys mentioned above, the dictionary resulting from parsing a
given URI can contain also other keys for convenience (e.g. for scheme-specific
definitions) but it is recommended that those keys are prefixed with an
underscore ("_") to differentiate them from the generic ones.
The validator classes must provide an attribute called
'namePattern' containing a regexp which validates the model names and which may
define named groups to help in constructing the dictionary with the above
mentioned keys.
In the proposed implementation, the validator base classes are created assuming
the following RFC3986-compliant structure of the names for the Authority, Device,
Attribute and Configuration element types respectively (note we use Auth instead
of Database to be scheme-agnostic):
Auth: <scheme>:<authority>[/<path>][?<query>][#<fragment>] Dev: <scheme>:[<authority>/]<path>[?<query>][#<fragment>] Attr: <scheme>:[<authority>/]<path>[?<query>][#<fragment>] Conf: <scheme>:[<authority>/]<path>[?<query>]#<fragment>
Note about syntax: square brackets indicate "optionality" and segment names
are represented between angle brackets. The rest of the characters are literal)
The proposed base validator classes can then use the mentioned structure to simplify the creation of the 'namePattern'. A base implementation of 'namePattern' exists as a property that returns the name pattern by constructing it from the following attributes:
- scheme - authority - path - query - fragment
Each of these attributes should contain the regexp for the same-named segment of the URI
For example, the validator for a Tango database name is:
class TangoAuthorityNameValidator(TaurusAuthorityNameValidator): '''Validator for Tango authority names. Apart from the standard named groups (scheme, authority, path, query and fragment), the following named groups are created: - host: tango host name, without port. - port: port number ''' scheme = 'tango' authority = '//(?P<host>([\w\-_]+\.)*[\w\-_]+):(?P<port>\d{1,5})' path = '(?!)' query = '(?!)' fragment = '(?!)'
and the resulting 'namePattern' is:
^(?P<scheme>tango):(?P<authority>//(?P<host>([\w\-_]+\.)*[\w\-_]+):(?P<port>\d{1,5}))((?=/)(?P<path>(?!)))?(\?(?P<query>(?!)))?(#(?P<fragment>(?!)))?$
A mechanism should be implemented to provide compatibility with previous syntax.
For example, in pre-TEP3 implementations, '//' was used as part of a separator between the scheme and the rest of the model name instead of as a prefix of authority (which is what RFC3986 dictates).
Usage of old-style model names should be accepted to the maximum possible extent (although deprecation warnings may be issued)
The proposed API for this is that those validator classes that need to provide backwards compatibility should expose an attribute called 'nonStrictNamePattern' containing a regexp that matches the "old-style" names. Then, the validator's isValid() methods accept a 'strict' flag which, in case of being False, would allow to fall back to the nonStrictNamePattern if the regular validation failed.
In order to be RFC3986-compliant, the evaluation scheme model names
need a radical transformation.
In the proposed implementation, the following changes have been made:
So, for example, the old-style model name
'evaluation://dev=foo;x+y?x=1;y=2'
would now be written as:
'eval:@foo/x=1;y=2;x+y'
The proposed implementation changes the model name syntax for the configuration objects of both the tango and eval schemes. Where before the suffix "?configuration" was used, now "#" is used. Similarly, when a configuration key was defined with the suffix "?configuration=<cfg_key>", now it is defined as "#<cfg_key>".
This new syntax has the following advantages:
Previous to TEP3, five schemes were included in Taurus. The following list summarizes how they are adapted to the TEP3 changes:
tango: the proposed implementation completely ports the tango scheme, including providing backwards compatibility.
eval: the proposed implementation completely ports the eval scheme, including providing backwards compatibility.
simulation: the proposed implementation removes the simulation scheme (which was used only by the taurusdesigner to provide an offline mock for tango and which was already broken). The necessary changes have been done in taurusdesigner.
epics: the epics scheme is left in an unfinished (unusable) state after the proposed implementation of TEP3. This scheme was just a proof-of-concept and not used in production, so it can be adapted on a later moment (e.g. after TEP14) without blocking the TEP3 acceptance.
spec: the spec scheme is left in an unfinished (unusable) state after the proposed implementation of TEP3. This scheme was just a proof-of-concept and not used in production, so it can be adapted on a later moment (e.g. after TEP14) without blocking the TEP3 acceptance.
res: the res scheme (which provides a model indirection mechanism) is left in an unfinished (unusable) state after the proposed implementation of TEP3. This scheme is not used in production, so it can be adapted on a later moment (e.g. after TEP14) without blocking the TEP3 acceptance.
A description of a refactoring of other taurus.core features such as TaurusAttributeValue and TaurusConfigValue was included into the draft of TEP3, but it has now been moved to [TEP14].
The initial discussions about the SEP3 itself are in the sardana-devel mailing list.
Further (post [sardana:wiki:SEP10] split) discussions about TEP3 are held on the tauruslib-devel mailing list.
This TEP effectively makes the Taurus core tango-independent at the import level (i.e., it makes it possible to import taurus without importing PyTango). But there many implementations details remain that are inherited from the Tango-dependency history. The [TEP14] proposes a further taurus.core refactoring that eliminates some of the most evident of these "tangoisms", thus simplifying even more the creation of new schemes.
Once the taurus.core is independent of Tango (and maybe also after [TEP14]), other proposals should be made to a) make as many widgets from taurus.qt both scheme-agnostic and Tango-independent; and b) to identify and document those that are for some reason bound to one or another scheme.
The TEP3 was created from [sardana:wiki:SEP3] after the split of Taurus from sardana according to [sardana:wiki:SEP10]. The SEP3 still remains to cover the changes necessary in sardana to adapt to the TEP3 changes.
Implementation is currently in the tep3 branch of git://git.code.sf.net/p/tauruslib/taurus
The following compilation of tasks was started on 12/08/2014 (by then, many of the requirements from this TEP were already implemented) and was used as a checklist of pending issues before submitting the implementation of TEP3 for approval. The list is kept in this appendix of the TEP3 to provide a historical reference:
The following tasks were previously part of the above requirements list, but have been moved to the [TEP14]:
The following tasks were previously part of the above requirements list, but have been left out of TEP3 for not being critical. They can be handled as feature requests after approval of TEP3:
The following copyright statement and license apply to TEP3 (this
document).
Copyright (c) 2013 CELLS / ALBA Synchrotron, Bellaterra, Spain
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2013-06-26
cmft First draft based on previous documents and discussions with tiagocoutinho and cpascual
2013-11-04
cpascual Partial rewrite of section on implementation. Also some spellchecking.
2013-11-04
cpascual Partial rewrite of section on implementation. Also some spellchecking.
2013-11-06
cmft Including "getting things done" section
2014-04-28
cmft Changed API description for validators
2014-08-13
cpascual General update of the document based on code review and discussions with cmft. Also added the "Changes" section.
2014-08-14
cpascual Added some more tasks to implementation plan and reference to [sardana:wiki:Taurus_URIRefactoring] document
2014-10-03
cpascual Updated pending tasks and completed some info about validators
2015-04-28
cpascual Adapted latest version of [sardana:wiki:SEP3] to update TEP3 and move some parts to [TEP14]
2015-04-30
cpascual Added 'Refactoring of Model name syntax' section using info from [sardana:wiki:Taurus_URIRefactoring]. Also several other minor changes and improvements.
2015-04-30
cpascual passing to CANDIDATE
2015-05-06
cpascual Introduced some minor changes according to comments from zreszela
2015-05-06
cpascual Added the adapting existing schemes to TEP3, and updated the Implementation plan
2015-05-08
cpascual Updated the Implementation plan (cross last task) and added section about change in configuration name syntax.
2016-03-16
cpascual Passing to ACCEPTED
2016-06-13
cpascual Minor formatting fix
Sardana: Wiki: SEP10
Sardana: Wiki: SEP3
Sardana: Wiki: Taurus_URIRefactoring
OLD Tickets: #112
OLD Tickets: #328
Wiki: TEP14