-
Notifications
You must be signed in to change notification settings - Fork 99
Custom object expansion for repeated capabilities #2100
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
base: master
Are you sure you want to change the base?
Custom object expansion for repeated capabilities #2100
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2100 +/- ##
==========================================
- Coverage 91.34% 91.33% -0.01%
==========================================
Files 66 66
Lines 16292 16301 +9
==========================================
+ Hits 14882 14889 +7
- Misses 1410 1412 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 1 file with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
generated/nirfsg/nirfsg/session.py
Outdated
complete_rep_cap_list = [ | ||
current_rep_cap + self._separator + rep_cap | ||
for current_rep_cap in self._current_repeated_capability_list | ||
for rep_cap in rep_caps_list | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This list comprehension exists to support the chaining of repeated capabilities, i.e. session.sites[0, 1].pins['PinA', 'PinB'].ppmu_source()
.
See #1291
This new implementation won't work with chaining.
You can't call .pins in a class where we don't define properties/attributes for each of the other rep cap classes.
generated/nirfsg/nirfsg/session.py
Outdated
object.__setattr__(self, '_current_repeated_capability_list', complete_rep_cap_list) | ||
self._current_repeated_capability_list = complete_rep_cap_list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this being set twice?
build/helper/metadata_filters.py
Outdated
def filter_rep_cap_supported_attributes(attributes, rep_cap_name): | ||
'''Returns attribute metadata only for those attributes that support the specified repeated capability. | ||
Args: | ||
attributes: Dictionary of attribute metadata. | ||
rep_cap_name: The name of the repeated capability to filter by. | ||
Returns: | ||
Dictionary of attributes that support the specified repeated capability. | ||
''' | ||
return {k: v for k, v in attributes.items() if rep_cap_name in v.get('supported_rep_caps', [])} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good, but what about filter_rep_cap_supported_functions?
generated/nirfsg/nirfsg/session.py
Outdated
|
||
Example: :py:attr:`my_session.waveform[ ... ].waveform_runtime_scaling` | ||
|
||
To set/get on all waveform, you can call the property directly on the :py:class:`nirfsg.Session`. | ||
|
||
Example: :py:attr:`my_session.waveform_runtime_scaling` | ||
''' | ||
waveform_signal_bandwidth = _attributes.AttributeViReal64(1150264) | ||
'''Type: float | ||
|
||
Specifies the bandwidth of the arbitrary signal. This value must be less than or equal to (0.8× iq_rate). | ||
|
||
**Units**: hertz (Hz) | ||
|
||
**Supported Devices:** PXIe-5820/5830/5831/5832/5840/5841/5842/5860 | ||
|
||
Tip: | ||
This property can be set/get on specific waveform within your :py:class:`nirfsg.Session` instance. | ||
Use Python index notation on the repeated capabilities container waveform to specify a subset. | ||
|
||
Example: :py:attr:`my_session.waveform[ ... ].waveform_signal_bandwidth` | ||
|
||
To set/get on all waveform, you can call the property directly on the :py:class:`nirfsg.Session`. | ||
|
||
Example: :py:attr:`my_session.waveform_signal_bandwidth` | ||
''' | ||
waveform_waveform_size = _attributes.AttributeViInt32(1150297) | ||
'''Type: int | ||
|
||
Specifies the size of the waveform specified by an active channel. | ||
|
||
**Supported Devices:** PXIe-5820/5830/5831/5832/5840/5841/5841 with PXIe-5655/5842/5860 | ||
|
||
Tip: | ||
This property can be set/get on specific waveform within your :py:class:`nirfsg.Session` instance. | ||
Use Python index notation on the repeated capabilities container waveform to specify a subset. | ||
|
||
Example: :py:attr:`my_session.waveform[ ... ].waveform_waveform_size` | ||
|
||
To set/get on all waveform, you can call the property directly on the :py:class:`nirfsg.Session`. | ||
|
||
Example: :py:attr:`my_session.waveform_waveform_size` | ||
''' | ||
def __init__(self, session, repeated_capability_list): | ||
object.__setattr__(self, '_session', session) | ||
object.__setattr__(self, '_repeated_capability_list', repeated_capability_list) | ||
object.__setattr__(self, '_prefix', 'waveform::') | ||
object.__setattr__(self, '_current_repeated_capability_list', repeated_capability_list if len(repeated_capability_list) > 0 else ['']) | ||
object.__setattr__(self, '_separator', '') | ||
|
||
def __setattr__(self, key, value): | ||
if key not in dir(self): | ||
raise AttributeError("'{0}' object has no attribute '{1}'".format(type(self).__name__, key)) | ||
object.__setattr__(self, key, value) | ||
|
||
def __getitem__(self, repeated_capability): | ||
'''Set/get properties or call methods with a repeated capability (i.e. channels)''' | ||
rep_caps_list = _converters.convert_repeated_capabilities(repeated_capability, self._prefix) | ||
complete_rep_cap_list = [current_rep_cap + self._separator + rep_cap for current_rep_cap in self._current_repeated_capability_list for rep_cap in rep_caps_list] | ||
complete_rep_cap_list = [ | ||
current_rep_cap + self._separator + rep_cap | ||
for current_rep_cap in self._current_repeated_capability_list | ||
for rep_cap in rep_caps_list | ||
] | ||
object.__setattr__(self, '_current_repeated_capability_list', complete_rep_cap_list) | ||
self._current_repeated_capability_list = complete_rep_cap_list | ||
|
||
return _SessionBase( | ||
repeated_capability_list=complete_rep_cap_list, | ||
all_channels_in_session=self._session._all_channels_in_session, | ||
interpreter=self._session._interpreter, | ||
freeze_it=True | ||
) | ||
return self | ||
|
||
def _get_attribute_vi_real64(self, attribute): | ||
repeated_capability = ','.join(self._current_repeated_capability_list) | ||
value = self._session._interpreter.get_attribute_vi_real64(repeated_capability, attribute) | ||
return value | ||
|
||
# This is a very simple context manager we can use when we need to set/get attributes | ||
# or call functions from _SessionBase that require no channels. It is tied to the specific | ||
# implementation of _SessionBase and how repeated capabilities are handled. | ||
class _NoChannel(object): | ||
def __init__(self, session): | ||
self._session = session | ||
def _set_attribute_vi_real64(self, attribute, value): | ||
repeated_capability = ','.join(self._current_repeated_capability_list) | ||
self._session._interpreter.set_attribute_vi_real64(repeated_capability, attribute, value) | ||
|
||
def __enter__(self): | ||
self._repeated_capability_cache = self._session._repeated_capability | ||
self._session._repeated_capability = '' | ||
def _get_attribute_vi_int32(self, attribute): | ||
repeated_capability = ','.join(self._current_repeated_capability_list) | ||
value = self._session._interpreter.get_attribute_vi_int32(repeated_capability, attribute) | ||
return value | ||
|
||
def __exit__(self, exc_type, exc_value, traceback): | ||
self._session._repeated_capability = self._repeated_capability_cache |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class is for calling a function or attribute that does not support repeated capabilities, while in the middle of a fancy function that may have had repeated capabilties passed in.
Even if nirfsg doesn't happen to need it at the moment, I'm not sure it's okay to just blindly omit it. We need to reason through how such a use case would work without it. If nothing else, fancy function code would need to change to not use this, but I'm not sure it would work.
The description for this PR is not sufficient. |
generated/nirfsg/nirfsg/session.py
Outdated
def _get_attribute_vi_real64(self, attribute): | ||
repeated_capability = ','.join(self._current_repeated_capability_list) | ||
value = self._session._interpreter.get_attribute_vi_real64(repeated_capability, attribute) | ||
return value | ||
|
||
def _set_attribute_vi_real64(self, attribute, value): | ||
repeated_capability = ','.join(self._current_repeated_capability_list) | ||
self._session._interpreter.set_attribute_vi_real64(repeated_capability, attribute, value) | ||
|
||
def _get_attribute_vi_int32(self, attribute): | ||
repeated_capability = ','.join(self._current_repeated_capability_list) | ||
value = self._session._interpreter.get_attribute_vi_int32(repeated_capability, attribute) | ||
return value | ||
|
||
def _set_attribute_vi_int32(self, attribute, value): | ||
repeated_capability = ','.join(self._current_repeated_capability_list) | ||
self._session._interpreter.set_attribute_vi_int32(repeated_capability, attribute, value) | ||
|
||
def _get_attribute_vi_string(self, attribute): | ||
repeated_capability = ','.join(self._current_repeated_capability_list) | ||
value = self._session._interpreter.get_attribute_vi_string(repeated_capability, attribute) | ||
return value | ||
|
||
def _set_attribute_vi_string(self, attribute, value): | ||
repeated_capability = ','.join(self._current_repeated_capability_list) | ||
self._session._interpreter.set_attribute_vi_string(repeated_capability, attribute, value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're going to put these in every rep cap class, why not have a base class to inherit them from?
…vagupta/custom_obj_rep_cap_expansion
This contribution adheres to CONTRIBUTING.md.
I've updated CHANGELOG.md if applicable.
I've added tests applicable for this pull request
What does this Pull Request accomplish?
Currently to set an attribute with repeated capability, we create a new _SessionBase instance with repeated_capability information passed at the time of initalization.
The information of repeated capability stored in this new _SessionBase instance is used when dispatching call to the interpreter session to set the value in the driver.
Repeated Capabilities can be handled in a way that avoids going down this route.
Changes are made to the helper scripts and session mako template to support custom object expansion of the applicable only attributes.
List issues fixed by this Pull Request below, if any.
What testing has been done?