Open cpascual opened 5 years ago
Hi,
The option 2, using fragments is the one that I see more feasible. Although flexibility is considered an advantage in option 1, it is more risky.
In fact, commands may have so many particular cases that I would avoid over-specifying the API as much as possible.
My only concern would be if using fragments for commands collides with other possible usages of them; for example to access device properties (we also need a URI for it).
The alternative could be using queries for properties or authority fragments for properties, but then we must have a way to distinguish class properties from device properties or free object properties.
Sergi
My only concern would be if using fragments for commands collides with other possible usages of them; for example to access device properties (we also need a URI for it).
The point is that the "fragment" has already a well defined meaning: "a/b/c/d#foo"
refers to getattr(taurus.Attribute("a/b/c/d"), "foo")
regardless of what is "foo".
That is, we are not assigning any special meaning to the syntax in relation to commands or properties or whatever and we are not creating any special "command" object. Instead we get whatever TaurusBaseComponent.getModelFragmentObj("foo")
returns to us. The only "command" concept would be a convention that widgets supporting commands use this mechanism to access the comand
The alternative could be using queries for properties or authority fragments for properties, but then we must have a way to distinguish class properties from device properties or free object properties.
I think this is altogether a different discussion that does not really affect the decision. If the model object provides a way of accessing properties as its member, then they can also be accessed as fragments without collisions. If not, you need to come up with a convention or to make properties a model object.
I personally, would tend to simply implement this by exposing the tango properties as TangoAttribute
objects... or, at most I would define a new schem (e.g. "tgprop") that maps properties as its TgpropAttribute
. But as I say, this is IMHO out-of-scope for this discussion.
Properties may be relative to any object in Tango (device, attribute, class or database), so they should not be exposed only from TangoAttribute but from any other object (or the database).
That said, if a mechanism is provided we should have a way to get commands or properties independently. I understood that fragment just gets any member of the object, so it will work with commands.
If instead of fragment we use queries for properties, how it would look like for a TangoDevice?
Properties (...)
Again, I think that, while interesting, the properties discussion is off-topic. In fact, issue #449 is already dedicated to it. Please let's move the properties discussion there.
intro
Hi, I am opening this issue to open a discussion on a topic that has been asked to me on several occasions and which we could try to implement (I will convert this issue into a TEP if there is interest):
Should we support "commands" in Taurus?
Note that as of now we have 3 types of models:
Authority
,Device
andAttribute
. The "command" concept is not a Taurus concept at all.In the Tango world , the commands are associated to devices, and therefore the widgets that interact with commands (e.g.
TaurusCommandButton
) tend to be implemented for accepting aTangoDevice
as its model and then use their own ways to configure the command name and/or the parameters for the command (e.g.TaurusCommandButton.setCommand()
andTaurusCommandButton.setParameters()
).The main limitations of this approach are:
I think that it would be a great improvement if we define the concept of "command" in Taurus and we allow commands to be described in URIs. This would allow e.g. to support the creation of forms that include command execution widgets mixed with the attribute and device widgets... and these forms could be created by just setting the appropriate model names.
So first, what would a "taurus command" be?
I personally, think that a generic definition to start with could be: "an object that can be executed (with optional arbitrary arguments) and that (optionally) returns a value as the result of the execution"
This definition matches well an implementation based on a python function/method.
I am intentionally leaving aside for simplicity the "detail" of whether the execution should be synchronous or asynchronous and how should the returned value be passed. I am also not going into how/whether to define the "accepted return value types".
Then we need to consider how we could integrate this new concept within taurus model-view architecture. Here are two alternatives that I've considered:
Alternative 1: commands as a model class on their own
This would imply adding a 4th model class
TaurusCommand
(alongsideTaurusAuthority
, etc.). The correspondingxxxFactory
would be in charge of providing them. TheTaurusCommand
model class would need to provide an API to trigger an execution and for returning the result value of the acquisition.PROs:
CONs:
xxxCommandNameValidator
, thexxxFactory.getCommand
, extensions toTaurusManager
andtaurushelper
, ...Alternative 2: commands as fragments of the existing models
This alternative would make use of the existing fragment support, and consider the command object as a fragment of a model.
For example, a
TaurusCommandButton
for executing theinit
command of thea/b/c
device could accept an URI liketango:a/b/c#init
and then simply useself.getModelFragmentObj()
to obtain the method to be executed.Also it is important to note that a fragment "lives" in the view side of the model-view architecture: e.g. in the
TaurusCommandButton
example used before, the model object would still be the device and the specific fragment name ("init") would only be available from the button widget, that stores it (seeTaurusBaseComponent.modelFragmentName
).Regarding how to codify the command arguments in the fragment part of the URI, this can be handled differently by different widgets, but IMHO it would be reasonable to agree in codifying them as "evaluable function call strings". For example, the following code
would be equivalent to what we now do with:
Note: we could provide a utility in taurus to parse these "evaluable function call strings", e.g.
parse_command("foo('a', 1, x=2)") --> ("foo", ("a", 1), {"x":2})
Finally, note that in the generic case I am not limiting the "command" to be a fragment of a
xxxDevice
. In some schemes it may make sense to get commands from anxxxAuthority
or anxxxAttribute
.PROs:
CONs:
xxxAuthority
,xxxDevice
orxxxAttribute
. (although in practice I do not think that this is a problem since either a dummy device or authority could always be used as a "command executor")