-
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
Change repeated capabilities #718
Changes from 5 commits
3dc54c9
ad95cba
10eade5
3860ec6
a89cd1f
bf49be6
ea96d19
8458488
b6c1330
0467916
339908b
8ba8760
fe0b7a1
a5ee751
5e51689
cb97f7f
186dd6c
e4152b9
c764db6
86c220a
5790fb3
2832f66
ae065a2
6588ecf
798ba75
e5c2322
d84fc00
558bded
94696e1
188832d
2916d4a
1b0d10d
5b2fd0f
d3a91b4
c8df30b
747368d
e61b621
18c489f
c572c70
3dda354
d9443dd
4f13ed8
80dfc2f
01aab4f
32cc605
3e5ab43
83e059d
049ccfc
6eab9b4
7337b8e
24b67f7
d08ea33
ff3dfb3
603e9ac
61c7d2f
0b43ad4
e9891b7
ff9213b
fe9e2c0
ed34c39
7fa18ce
2026eb0
d7ae7d6
951f5f9
d7f89d2
b2c8bbb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
# Changelog | ||
|
||
* [Unreleased](#unreleased) | ||
* [0.5.0](#060---2017-12-20) | ||
* [0.6.0](#060---2017-12-20) | ||
* [0.5.0](#050---2017-11-27) | ||
* [0.4.0](#040---2017-11-07) | ||
* [0.3.0](#030---2017-10-13) | ||
|
@@ -14,6 +14,25 @@ All notable changes to this project will be documented in this file. | |
* ### ALL | ||
* #### Added | ||
* #### Changed | ||
* Repeated capabilities are no longer accessed directly on the session object. Instead there is now a repeated capabilies object for each type of repeated capability that the driver supports. Some drivers do not use repeated capabilities so there is no change for them. | ||
* The repeated capabilities object can take integers or strings, a single item or a list. | ||
* The repeated capabilities object knows the proper prefix and will add it if needed. | ||
* The following are all legal | ||
```python | ||
import niscope | ||
session = niscope.Session('PXI1Slot2') | ||
|
||
# Channel repeated capabilities | ||
session.channel['0'].channel_enabled = True | ||
session.channel[0].channel_enabled = True | ||
session.channel[[0, 1, 3]].channel_enabled = True | ||
|
||
# P2P repeated capabilities | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2P is not supported, right? Maybe use NI-FGEN MarkerEvents for the example? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should add P2P attributes back. |
||
i = session.p2p_streams['0'].P2P_SAMPLES_AVAIL_IN_ENDPOINT | ||
i = session.p2p_streams[0].P2P_SAMPLES_AVAIL_IN_ENDPOINT | ||
i = session.p2p_streams[[0, 1, 3]].P2P_SAMPLES_AVAIL_IN_ENDPOINT | ||
i = session.p2p_streams['FIFOEndpoint0'].P2P_SAMPLES_AVAIL_IN_ENDPOINT | ||
``` | ||
* #### Removed | ||
* ### NI-DMM | ||
* #### Added | ||
|
@@ -29,14 +48,19 @@ All notable changes to this project will be documented in this file. | |
* #### Removed | ||
* ### NI-DCPower | ||
* #### Added | ||
* Channel repeated capability | ||
* #### Changed | ||
* #### Removed | ||
* ### NI-FGEN | ||
* #### Added | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Script Triggers, Marker Events are two NI-FGEN and NI-HSDIO repeated capabilities. Don't know of others. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added |
||
* Channel repeated capability | ||
* P2P repeated capability | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought we took all P2P stuff out of the Python bindings. |
||
* #### Changed | ||
* #### Removed | ||
* ### NI-SCOPE | ||
* #### Added | ||
* Channel repeated capability | ||
* P2P repeated capability | ||
* #### Changed | ||
* #### Removed | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,7 +48,23 @@ class ${session_context_manager}(object): | |
|
||
|
||
% endif | ||
class _SessionBase(object): | ||
% for rep_cap in config['repeated_capabilities']: | ||
class _${rep_cap['python_class_name']}(object): | ||
def __init__(self, ${config['session_handle_parameter_name']}): | ||
self._${config['session_handle_parameter_name']} = ${config['session_handle_parameter_name']} | ||
|
||
def __getitem__(self, repeated_capability): | ||
'''Set/get properties or call methods with a repeated capability (i.e. channels)''' | ||
if isinstance(repeated_capability, list): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems restrictive. Clients should be able to pass anything iterable even if not a list. For example, range() doesn't return a list. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed to use duck typing. Anything iterable will now work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider moving all this logic to a function in _converters.py where you can unit test it in isolation. I think it will help readability too. It would need to take the prefix as a parameter. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved and tested |
||
rep_cap_list = [str(r) if str(r).startswith('${rep_cap['prefix']}') else '${rep_cap['prefix']}' + str(r) for r in repeated_capability] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmmm... IVI repeated capability strings are case insensitive, but the prefix check here is case sensitive. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Made check case insensitive. |
||
else: | ||
rep_cap_list = [str(repeated_capability) if str(repeated_capability).startswith('${rep_cap['prefix']}') else '${rep_cap['prefix']}' + str(repeated_capability)] | ||
|
||
return _RepeatedCapbilities(self._${config['session_handle_parameter_name']}, ','.join(rep_cap_list)) | ||
|
||
|
||
% endfor | ||
class _RepeatedCapbilities(object): | ||
'''Base class for all ${config['driver_name']} sessions.''' | ||
|
||
# This is needed during __init__. Without it, __setattr__ raises an exception | ||
|
@@ -85,10 +101,12 @@ init_method_params = helper.get_params_snippet(init_function, helper.ParameterUs | |
init_call_params = helper.get_params_snippet(init_function, helper.ParameterUsageOptions.SESSION_METHOD_CALL) | ||
%>\ | ||
|
||
def __init__(self, repeated_capability): | ||
def __init__(self, ${config['session_handle_parameter_name']}, repeated_capability): | ||
self._library = library_singleton.get() | ||
self._repeated_capability = repeated_capability | ||
self._${config['session_handle_parameter_name']} = ${config['session_handle_parameter_name']} | ||
self._encoding = 'windows-1251' | ||
self._is_frozen = True | ||
|
||
def __setattr__(self, key, value): | ||
if self._is_frozen and key not in dir(self): | ||
|
@@ -125,34 +143,25 @@ init_call_params = helper.get_params_snippet(init_function, helper.ParameterUsag | |
% endfor | ||
% endfor | ||
|
||
class _RepeatedCapability(_SessionBase): | ||
'''Allows for setting/getting properties and calling methods for specific repeated capabilities (such as channels) on your session.''' | ||
|
||
def __init__(self, ${config['session_handle_parameter_name']}, repeated_capability): | ||
super(_RepeatedCapability, self).__init__(repeated_capability) | ||
self._${config['session_handle_parameter_name']} = ${config['session_handle_parameter_name']} | ||
self._is_frozen = True | ||
|
||
|
||
class Session(_SessionBase): | ||
class Session(_RepeatedCapbilities): | ||
'''${config['session_class_description']}''' | ||
|
||
def __init__(${init_method_params}): | ||
super(Session, self).__init__(repeated_capability='') | ||
self._library = library_singleton.get() | ||
self._encoding = 'windows-1251' | ||
self._${config['session_handle_parameter_name']} = 0 # This must be set before calling ${init_function['python_name']}(). | ||
self._${config['session_handle_parameter_name']} = self.${init_function['python_name']}(${init_call_params}) | ||
self._is_frozen = True | ||
% for rep_cap in config['repeated_capabilities']: | ||
self.${rep_cap['python_name']} = _${rep_cap['python_class_name']}(self._${config['session_handle_parameter_name']}) | ||
% endfor | ||
super(Session, self).__init__(self._${config['session_handle_parameter_name']}, repeated_capability='') | ||
|
||
def __enter__(self): | ||
return self | ||
|
||
def __exit__(self, exc_type, exc_value, traceback): | ||
self.close() | ||
|
||
def __getitem__(self, repeated_capability): | ||
'''Set/get properties or call methods with a repeated capability (i.e. channels)''' | ||
return _RepeatedCapability(self._${config['session_handle_parameter_name']}, repeated_capability) | ||
|
||
def initiate(self): | ||
return ${session_context_manager}(self) | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,21 @@ def __exit__(self, exc_type, exc_value, traceback): | |
self._session.abort() | ||
|
||
|
||
class _SessionBase(object): | ||
class _Channel(object): | ||
def __init__(self, vi): | ||
self._vi = vi | ||
|
||
def __getitem__(self, repeated_capability): | ||
'''Set/get properties or call methods with a repeated capability (i.e. channels)''' | ||
if isinstance(repeated_capability, list): | ||
rep_cap_list = [str(r) if str(r).startswith('') else '' + str(r) for r in repeated_capability] | ||
else: | ||
rep_cap_list = [str(repeated_capability) if str(repeated_capability).startswith('') else '' + str(repeated_capability)] | ||
|
||
return _RepeatedCapbilities(self._vi, ','.join(rep_cap_list)) | ||
|
||
|
||
class _RepeatedCapbilities(object): | ||
'''Base class for all NI-DCPower sessions.''' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems odd that a class named _RepeatedCapbilities is 'Base class for all NI-DCPower sessions.' There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What should it be called? It is the class that contains any attribute (all) or function that takes a repeated capabilities string. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't come up with a perfect name for it but _SessionBase is probably better than _RepeatedCapabilities. When I read _RepeatedCapabilities, I think of a collection of repeated capabilities such as "0" or "ScriptTrigger2". |
||
|
||
# This is needed during __init__. Without it, __setattr__ raises an exception | ||
|
@@ -1467,10 +1481,12 @@ class _SessionBase(object): | |
var = session['0,1'].voltage_pole_zero_ratio | ||
''' | ||
|
||
def __init__(self, repeated_capability): | ||
def __init__(self, vi, repeated_capability): | ||
self._library = library_singleton.get() | ||
self._repeated_capability = repeated_capability | ||
self._vi = vi | ||
self._encoding = 'windows-1251' | ||
self._is_frozen = True | ||
|
||
def __setattr__(self, key, value): | ||
if self._is_frozen and key not in dir(self): | ||
|
@@ -2566,34 +2582,23 @@ def _error_message(self, error_code): | |
return error_message_ctype.value.decode(self._encoding) | ||
|
||
|
||
class _RepeatedCapability(_SessionBase): | ||
'''Allows for setting/getting properties and calling methods for specific repeated capabilities (such as channels) on your session.''' | ||
|
||
def __init__(self, vi, repeated_capability): | ||
super(_RepeatedCapability, self).__init__(repeated_capability) | ||
self._vi = vi | ||
self._is_frozen = True | ||
|
||
|
||
class Session(_SessionBase): | ||
class Session(_RepeatedCapbilities): | ||
'''An NI-DCPower session to a National Instruments Programmable Power Supply or Source Measure Unit.''' | ||
|
||
def __init__(self, resource_name, channels='', reset=False, option_string=''): | ||
super(Session, self).__init__(repeated_capability='') | ||
self._library = library_singleton.get() | ||
self._encoding = 'windows-1251' | ||
self._vi = 0 # This must be set before calling _initialize_with_channels(). | ||
self._vi = self._initialize_with_channels(resource_name, channels, reset, option_string) | ||
self._is_frozen = True | ||
self.channel = _Channel(self._vi) | ||
super(Session, self).__init__(self._vi, repeated_capability='') | ||
|
||
def __enter__(self): | ||
return self | ||
|
||
def __exit__(self, exc_type, exc_value, traceback): | ||
self.close() | ||
|
||
def __getitem__(self, repeated_capability): | ||
'''Set/get properties or call methods with a repeated capability (i.e. channels)''' | ||
return _RepeatedCapability(self._vi, repeated_capability) | ||
|
||
def initiate(self): | ||
return _Acquisition(self) | ||
|
||
|
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.
since this is a container that you're indexing, shouldn't it be in plural form ("channels")?
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.
Changed to channels