Skip to content
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

Merged
merged 66 commits into from
Feb 8, 2018
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
3dc54c9
Add repeated_capabilities key in config for all drivers
texasaggie97-zz Jan 4, 2018
ad95cba
Update tests for new method of accessing repeated capabilities
texasaggie97-zz Jan 4, 2018
10eade5
Change how repeated capabilities are handled
texasaggie97-zz Jan 4, 2018
3860ec6
Update generated files
texasaggie97-zz Jan 4, 2018
a89cd1f
Update changelog
texasaggie97-zz Jan 4, 2018
bf49be6
Add function example in changelog
texasaggie97-zz Jan 4, 2018
ea96d19
Case insensitive check
texasaggie97-zz Jan 4, 2018
8458488
Missed a channel reference
texasaggie97-zz Jan 4, 2018
b6c1330
Update generated files
texasaggie97-zz Jan 4, 2018
0467916
Fix parent/child instance variables
texasaggie97-zz Jan 4, 2018
339908b
Update generated files
texasaggie97-zz Jan 4, 2018
8ba8760
Fix up channel based tip admonition for new syntax
texasaggie97-zz Jan 5, 2018
fe0b7a1
Update generated files
texasaggie97-zz Jan 5, 2018
a5ee751
Change channel rep cap class to plural - channels
texasaggie97-zz Jan 8, 2018
5e51689
Add Marker and Script Trigger repeated capabilities to FGen
texasaggie97-zz Jan 8, 2018
cb97f7f
Fix typo in names
texasaggie97-zz Jan 8, 2018
186dd6c
Update tests for plural channels
texasaggie97-zz Jan 8, 2018
e4152b9
Use duck typing insted of checking for list
texasaggie97-zz Jan 8, 2018
c764db6
Fix tests
texasaggie97-zz Jan 8, 2018
86c220a
Update generated files
texasaggie97-zz Jan 8, 2018
5790fb3
Fix tests to use range() instead of driver channel list format
texasaggie97-zz Jan 8, 2018
2832f66
Add example to show using range() as a rep cap list
texasaggie97-zz Jan 8, 2018
ae065a2
Fix range usage
texasaggie97-zz Jan 8, 2018
6588ecf
Fix range usage
texasaggie97-zz Jan 9, 2018
798ba75
Merge branch 'master' into api/rep_caps
texasaggie97-zz Jan 10, 2018
e5c2322
Merge branch 'master' into api/rep_caps
texasaggie97-zz Jan 10, 2018
d84fc00
Missed channel string
texasaggie97-zz Jan 10, 2018
558bded
Merge branch 'master' into api/rep_caps
texasaggie97-zz Jan 15, 2018
94696e1
Merge branch 'master' into api/rep_caps
texasaggie97-zz Jan 16, 2018
188832d
Merge branch 'master' into api/rep_caps
texasaggie97-zz Jan 17, 2018
2916d4a
Have to use timedelta for all timeouts
texasaggie97-zz Jan 17, 2018
1b0d10d
Rename _RepeatedCapabilites to _SessionBase
texasaggie97-zz Jan 18, 2018
5b2fd0f
Add support for slices
texasaggie97-zz Jan 18, 2018
d3a91b4
Update generated files
texasaggie97-zz Jan 18, 2018
c8df30b
Merge branch 'master' into api/rep_caps
texasaggie97-zz Jan 23, 2018
747368d
Merge master
texasaggie97-zz Jan 23, 2018
e61b621
Merge branch 'master' into api/rep_caps
texasaggie97-zz Jan 25, 2018
18c489f
Make formatting consisten with other branches
texasaggie97-zz Jan 25, 2018
c572c70
Merge branch 'master' into api/rep_caps
texasaggie97-zz Jan 31, 2018
3dda354
Merge branch 'master' into api/rep_caps
texasaggie97-zz Feb 2, 2018
d9443dd
Change logic for finding lists
texasaggie97-zz Feb 2, 2018
4f13ed8
Add test cases for all supported formats for repeated capabilities
texasaggie97-zz Feb 2, 2018
80dfc2f
Update generated files
texasaggie97-zz Feb 2, 2018
01aab4f
Move more complete information into readme
texasaggie97-zz Feb 5, 2018
32cc605
Use python names
texasaggie97-zz Feb 5, 2018
3e5ab43
Mention issue in readme
texasaggie97-zz Feb 5, 2018
83e059d
Move repeated caps login into _converters and test
texasaggie97-zz Feb 5, 2018
049ccfc
Update generated files
texasaggie97-zz Feb 5, 2018
6eab9b4
Test int and string
texasaggie97-zz Feb 5, 2018
7337b8e
Remove now redundant tests
texasaggie97-zz Feb 5, 2018
24b67f7
Update generated files
texasaggie97-zz Feb 5, 2018
d08ea33
Only define one class and instantiate multiple times
texasaggie97-zz Feb 5, 2018
ff3dfb3
Spaces matter
texasaggie97-zz Feb 5, 2018
603e9ac
Update generated files
texasaggie97-zz Feb 5, 2018
61c7d2f
Add comments in __init__
texasaggie97-zz Feb 5, 2018
0b43ad4
Initialize _RepeatedCapabilities with Session instead of individual i…
texasaggie97-zz Feb 5, 2018
e9891b7
Update generated files
texasaggie97-zz Feb 5, 2018
ff9213b
Remove p2p mentions.
texasaggie97-zz Feb 7, 2018
fe9e2c0
Use auto numbering for the enum
texasaggie97-zz Feb 8, 2018
ed34c39
Fix readme
texasaggie97-zz Feb 8, 2018
7fa18ce
Once we have a list, we just call ourselves with it
texasaggie97-zz Feb 8, 2018
2026eb0
No default parameters on _SessionBase __init__, pass None in explicitly
texasaggie97-zz Feb 8, 2018
d7ae7d6
Update generated files
texasaggie97-zz Feb 8, 2018
951f5f9
Change logic for getting repeated capability string
texasaggie97-zz Feb 8, 2018
d7f89d2
Don't show using prefix
texasaggie97-zz Feb 8, 2018
b2c8bbb
Update generated files
texasaggie97-zz Feb 8, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion CHANGELOG.md
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)
Expand All @@ -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
Copy link
Member

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")?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to channels

session.channel[0].channel_enabled = True
session.channel[[0, 1, 3]].channel_enabled = True

# P2P repeated capabilities
Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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
Expand All @@ -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
Copy link
Member

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

* Channel repeated capability
* P2P repeated capability
Copy link
Member

Choose a reason for hiding this comment

The 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

Expand Down
45 changes: 27 additions & 18 deletions build/templates/session.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Copy link
Member

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to use duck typing. Anything iterable will now work.

Copy link
Member

Choose a reason for hiding this comment

The 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.
It returns the repeated capability as a str.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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]
Copy link

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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)

Expand Down
4 changes: 2 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,15 @@

# General information about the project.
project = 'NI Modular Instruments Python API'
copyright = '2017-2017, National Instruments'
copyright = '2017-2018, National Instruments'
author = 'National Instruments'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The full version, including alpha/beta/rc tags.
release = '0.6.1.dev0'
release = '0.6.0'
# The short X.Y version.
version = release[:3]

Expand Down
41 changes: 23 additions & 18 deletions generated/nidcpower/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.'''
Copy link
Member

Choose a reason for hiding this comment

The 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.'

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

Copy link
Member

Choose a reason for hiding this comment

The 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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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)

Expand Down
26 changes: 8 additions & 18 deletions generated/nidmm/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __exit__(self, exc_type, exc_value, traceback):
self._session.abort()


class _SessionBase(object):
class _RepeatedCapbilities(object):
'''Base class for all NI-DMM sessions.'''

# This is needed during __init__. Without it, __setattr__ raises an exception
Expand Down Expand Up @@ -411,10 +411,12 @@ class _SessionBase(object):
For the NI 4070/4071/4072 only, specifies the rate of the waveform acquisition in Samples per second (S/s). The valid Range is 10.0-1,800,000 S/s. Values are coerced to the closest integer divisor of 1,800,000. The default value is 1,800,000.
'''

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):
Expand Down Expand Up @@ -840,34 +842,22 @@ 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-DMM session to a National Instruments Digital Multimeter'''

def __init__(self, resource_name, id_query=False, reset_device=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 _init_with_options().
self._vi = self._init_with_options(resource_name, id_query, reset_device, option_string)
self._is_frozen = True
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)

Expand Down
41 changes: 23 additions & 18 deletions generated/nifake/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,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-FAKE sessions.'''

# This is needed during __init__. Without it, __setattr__ raises an exception
Expand Down Expand Up @@ -58,10 +72,12 @@ class _SessionBase(object):
An attribute of type string with read/write access.
'''

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):
Expand Down Expand Up @@ -420,34 +436,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-FAKE session to a fake MI driver whose sole purpose is to test nimi-python code generation'''

def __init__(self, resource_name, id_query=False, reset_device=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 _init_with_options().
self._vi = self._init_with_options(resource_name, id_query, reset_device, 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)

Expand Down
Loading