-
Notifications
You must be signed in to change notification settings - Fork 93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose NI-DCPower Advanced Sequences in Python API #504
Comments
I believe that if we cannot fix this on time for the 0.9 release, the feature is fairly unusable and we may be better off turning off code-gen for all the Advanced Sequence related functions. |
We decided to make all the advanced sequence functions private until we can come up with a suitable, Pythonic, solution. |
Proposed "Pythonic" advanced sequence API. with nidcpower.Session(resource_name="Dev1", channels=[0,1,2]) as session:
session.source_delay = datetime.timedelta(seconds=0.1)
session.voltage_level_autorange = True
session.current_level_autorange = True
# This is how you create an advanced sequence.
session.source_mode = nidcpower.SourceMode.SEQUENCE
my_advanced_sequence = [
{"output_function"=nidcpower.OutputFunction.DC_VOLTAGE, "voltage_level"=1.0},
{"output_function"=nidcpower.OutputFunction.DC_CURRENT, "current_level"=0.1}
]
session.create_advanced_sequence(sequence_name='my_sequence', my_advanced_sequence)
# Neat, right? |
Looks very neat! Pros
Caveats
session.create_advanced_sequence(sequence_name='my_sequence', my_advanced_sequence)
session.create_advanced_sequence_step()
session.output_function = nidcpower.OutputFunction.DC_VOLTAGE
session.source_delay = datetime.timedelta(seconds=0.5)
# If the user was expecting to change source_delay for only this new step,
# it will not have the intended effect, nor will it error. This is a problem
# even for the LV API, but at least we have the flexibility to protect
# against it by hiding create_advanced_sequence_step
session.create_advanced_sequence(sequence_name='my_sequence', my_advanced_sequence)
session.active_advanced_sequence_step = 0
session.output_function = nidcpower.OutputFunction.DC_CURRENT
session.source_delay = datetime.timedelta(seconds=0.5)
# Changes source delay for all steps, not just the currently active one!
# However, I don't think we can get away with hiding the
# active_advanced_sequence_step attribute. Other Thoughts
|
Definitely. There would be no public nidcpower.Session.create_advanced_sequence_step().
Agreed. I propose not allowing it from the Python API. Is this is too restrictive, we can look into exposing it somehow.
Yeah, we could do this. We'd use the Python names for the attributes as well. This would be closer to the C and LabVIEW APIs. Let's refer to this as Option 2. |
I don't think I could've done it any better myself. Looks very natural! |
After you get the prototype working, I'd try to make sure it plays nice with other iterable types that satisfy all the requirements (like a generator perhaps?). |
What's "it" in this context? |
Additionally, how does this effect attributes like |
The second argument given to |
I don't think it impacts
It's an interesting idea worth considering. We have 3 now, so I'll try to capture in the original issue description. |
So far, I like options 1 and 2 in that order. Option 0 is nasty and option 3 seems pretty complicated |
Could someone clarify what is wrong with Option 0. Generally the goal is to not have stringly typed APIs. They are easy to mess up and hard to know what is accepted. EDIT: I guess I'm focusing more on the "enum" part of Option 0 and not how the API is sequenced / the data structure |
I dislike that the client refers to a property (e.g. Output Function) in two ways throughout the program. In the normal case: @epage would you say you favor Option 1, but want the keys (properties) to be in the from instead of referring to properties in the form |
I'm still trying to come to understand the API and the usability issues associated with any proposal. So from talking with Sydney, it sounds like
From, this, I'm concerned about an API that offers a "one-shot" approach for creating a sequence. The user will expect the sequence to be created and it will be surprising that the session is left at the last step of the last sequence for any further operations they do. This violates the principle of least surprise.
Why is It seems like it'd be useful for checking how coercion happened, reconfiguring the sequence, etc. |
Crazy ideasequence = session.create_sequence(name, attrs)
sequence.create_step()
session.output_enabled = True
sequence.create_step()
session.output_enabled = False
sequence.create_step()
session.output_enabled = True
sequence.step = 2
output_enableds = [false, true., false]
for output_enabled, step in zip(session.create_sequence(name, attrs), outpout_enableds):
session.output_enabled = output_enabled
# Why not have attribute get/sets on `sequence`?
# No indication of interplay with session, particularly that gets/sets on session are related to the step |
Another idea that has the same problem as Option 1
It records your actions and then the call replays it
|
@epage To add a few more details that I left out in our call. This comment is based on the current API:
There's a couple different states (regarding the advanced sequence and the properties) the user could enter after calling create_advanced_sequence in the current API:
There could also be dependencies between properties that were specified in the |
This reminds me of something else. It is unfortunate that imo We should try to paper over this in the API. For example, see my Crazy Idea. If we had a way to edit a sequence without changing the active one, we could revert back to editing "" and all would be dandy. This would be my ideal API. |
Do you mean that the I do agree, though, that it might be confusing to the user that |
The key phrase in my statement "If we had a way to edit a sequence without changing the active one," |
Did we ever make a decision on how to implement this? So far, the PR is using string based names and is not supporting editing/modifying of the sequence after the fact. |
"Option 1" doesn't support multi-channel sequences. NI-DCPower doesn't support multi-channel sequences today, but the API (C, LabVIEW) can be trivially expanded to do so, and there is good reason to assume NI-DCPower will add multi-channel sequences in the future. How can "Option 1" be expanded to support multi-channel sequences? |
Met with @texasaggie97, Tom the NI guy that knows NI-DCPower the best, @thejcannon to discuss this. From Zen of Python
We decided to expose this functionality in a way that maps directly to the C and LabVIEW APIs, except we will use a list of strings with the Python names of the properties in |
The way the C API works, the client is supposed to pass an array of attribute IDs that he/she wants included in the advanced sequence. In our Python API, right now, this is just an int :(
This is not viable to expose as-is in Python because in the Python API clients never deal with attribute IDs.
So how to expose? Below some options, all viable but with no implementation details described.
Option 0: Enum for all attributes
We create an enum that contains all the attributes. The corresponding values are the attribute IDs.
Pros
Cons
Option 1: List of dicts for the whole sequence
Whole sequence is specified as a list of dicts. Each dict represents a step. Each key in a dict is a string that must match the Python attribute name.
Pros
Cons
Option 2: Use list of names to specify attributes in an active sequence
Pros
Cons
Option 3: Sequence object
A new type
AdvancedSequence
is introduced into the API. The user can create one of these and it acts as a list (iterable, etc). The user adds / modifies steps at will then passes it tonidcpower.Session.create_advanced_sequence(name, sequence)
. Presumably, at this point we create it, but allow further modifications.Pros
Cons
The text was updated successfully, but these errors were encountered: