diff --git a/CHANGELOG.md b/CHANGELOG.md index 2263882f7..643f5e6e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,12 @@ All notable changes to this project will be documented in this file. ## Unreleased * ### ALL * #### Added + * Support for chained repeated capabilities. This allows things like + ``` python + session.sites[0, 1].pins['PinA', 'PinB'].ppmu_voltage_level = 4 + ``` + + The repeated capabilities will be expanded to `'site0/PinA,site0/PinB,site1/PinA,site1/PinB'` * #### Changed * #### Removed * ### NI-DCPower diff --git a/build/templates/session.py.mako b/build/templates/session.py.mako index 5a829b843..2e492f072 100644 --- a/build/templates/session.py.mako +++ b/build/templates/session.py.mako @@ -123,15 +123,20 @@ class _Lock(object): % endif % if len(config['repeated_capabilities']) > 0: class _RepeatedCapabilities(object): - def __init__(self, session, prefix): + def __init__(self, session, prefix, current_repeated_capability_list): self._session = session self._prefix = prefix + # We need at least one element. If we get an empty list, make the one element an empty string + self._current_repeated_capability_list = current_repeated_capability_list if len(current_repeated_capability_list) > 0 else [''] + # Now we know there is at lease one entry, so we look if it is an empty string or not + self._separator = '/' if len(self._current_repeated_capability_list[0]) > 0 else '' 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] - return _SessionBase(${config['session_handle_parameter_name']}=self._session._${config['session_handle_parameter_name']}, repeated_capability_list=rep_caps_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) + return _SessionBase(${config['session_handle_parameter_name']}=self._session._${config['session_handle_parameter_name']}, repeated_capability_list=complete_rep_cap_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) # This is a very simple context manager we can use when we need to set/get attributes @@ -196,6 +201,13 @@ constructor_params = helper.filter_parameters(init_function, helper.ParameterUsa param_list.append("encoding=" + pp.pformat(encoding)) self._param_list = ', '.join(param_list) +% if len(config['repeated_capabilities']) > 0: + # Instantiate any repeated capability objects +% for rep_cap in config['repeated_capabilities']: + self.${rep_cap['python_name']} = _RepeatedCapabilities(self, '${rep_cap["prefix"]}', repeated_capability_list) +% endfor + +% endif self._is_frozen = freeze_it def __repr__(self): @@ -260,11 +272,6 @@ class Session(_SessionBase): 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}) - # Instantiate any repeated capability objects -% for rep_cap in config['repeated_capabilities']: - self.${rep_cap['python_name']} = _RepeatedCapabilities(self, '${rep_cap["prefix"]}') -% endfor - % if config['supports_nitclk']: self.tclk = nitclk.SessionReference(self._${config['session_handle_parameter_name']}) diff --git a/docs/_static/nidigital_usage.inc b/docs/_static/nidigital_usage.inc index 58dc22c67..b4c599db5 100644 --- a/docs/_static/nidigital_usage.inc +++ b/docs/_static/nidigital_usage.inc @@ -3,13 +3,25 @@ Usage The following is a basic example of using the **nidigital** module to open a session to a .... +.. code-block:: python + + import nidigital + with nidigital.Session(resource_name='PXI1Slot2', channels='0') as session: + pass + + +Some repeated capabilities can be chained. This is useful for some methods that can be used with the `pins` +repeated capability. They can be chained with the `sites` repeated capability. + .. code-block:: python import nidigital # Configure the session. with nidigital.Session(resource_name='PXI1Slot2', channels='0') as session: - pass + session.sites[0, 1].pins['PinA', 'PinB'].ppmu_source() + +This will apply the method/property to `'site0/PinA`, `site0/PinB`, `site1/PinA`, `site1/PinB'` Additional examples for NI-Digital Pattern Driver are located in src/nidigital/examples/ directory. diff --git a/generated/nidcpower/nidcpower/session.py b/generated/nidcpower/nidcpower/session.py index c4de5215b..83bfd62d3 100644 --- a/generated/nidcpower/nidcpower/session.py +++ b/generated/nidcpower/nidcpower/session.py @@ -87,15 +87,20 @@ def __exit__(self, exc_type, exc_value, traceback): class _RepeatedCapabilities(object): - def __init__(self, session, prefix): + def __init__(self, session, prefix, current_repeated_capability_list): self._session = session self._prefix = prefix + # We need at least one element. If we get an empty list, make the one element an empty string + self._current_repeated_capability_list = current_repeated_capability_list if len(current_repeated_capability_list) > 0 else [''] + # Now we know there is at lease one entry, so we look if it is an empty string or not + self._separator = '/' if len(self._current_repeated_capability_list[0]) > 0 else '' 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] - return _SessionBase(vi=self._session._vi, repeated_capability_list=rep_caps_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) + return _SessionBase(vi=self._session._vi, repeated_capability_list=complete_rep_cap_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) # This is a very simple context manager we can use when we need to set/get attributes @@ -2345,6 +2350,9 @@ def __init__(self, repeated_capability_list, vi, library, encoding, freeze_it=Fa param_list.append("encoding=" + pp.pformat(encoding)) self._param_list = ', '.join(param_list) + # Instantiate any repeated capability objects + self.channels = _RepeatedCapabilities(self, '', repeated_capability_list) + self._is_frozen = freeze_it def __repr__(self): @@ -3772,9 +3780,6 @@ def __init__(self, resource_name, channels=None, reset=False, options={}): self._vi = 0 # This must be set before calling _initialize_with_channels(). self._vi = self._initialize_with_channels(resource_name, channels, reset, options) - # Instantiate any repeated capability objects - self.channels = _RepeatedCapabilities(self, '') - # Store the parameter list for later printing in __repr__ param_list = [] param_list.append("resource_name=" + pp.pformat(resource_name)) diff --git a/generated/nidigital/README.rst b/generated/nidigital/README.rst index c3bf41933..387643512 100644 --- a/generated/nidigital/README.rst +++ b/generated/nidigital/README.rst @@ -130,13 +130,25 @@ Usage The following is a basic example of using the **nidigital** module to open a session to a .... +.. code-block:: python + + import nidigital + with nidigital.Session(resource_name='PXI1Slot2', channels='0') as session: + pass + + +Some repeated capabilities can be chained. This is useful for some methods that can be used with the `pins` +repeated capability. They can be chained with the `sites` repeated capability. + .. code-block:: python import nidigital # Configure the session. with nidigital.Session(resource_name='PXI1Slot2', channels='0') as session: - pass + session.sites[0, 1].pins['PinA', 'PinB'].ppmu_source() + +This will apply the method/property to `'site0/PinA`, `site0/PinB`, `site1/PinA`, `site1/PinB'` Additional examples for NI-Digital Pattern Driver are located in src/nidigital/examples/ directory. diff --git a/generated/nidigital/nidigital/session.py b/generated/nidigital/nidigital/session.py index 51952a88e..04fb992a9 100644 --- a/generated/nidigital/nidigital/session.py +++ b/generated/nidigital/nidigital/session.py @@ -90,15 +90,20 @@ def __exit__(self, exc_type, exc_value, traceback): class _RepeatedCapabilities(object): - def __init__(self, session, prefix): + def __init__(self, session, prefix, current_repeated_capability_list): self._session = session self._prefix = prefix + # We need at least one element. If we get an empty list, make the one element an empty string + self._current_repeated_capability_list = current_repeated_capability_list if len(current_repeated_capability_list) > 0 else [''] + # Now we know there is at lease one entry, so we look if it is an empty string or not + self._separator = '/' if len(self._current_repeated_capability_list[0]) > 0 else '' 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] - return _SessionBase(vi=self._session._vi, repeated_capability_list=rep_caps_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) + return _SessionBase(vi=self._session._vi, repeated_capability_list=complete_rep_cap_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) # This is a very simple context manager we can use when we need to set/get attributes @@ -521,6 +526,14 @@ def __init__(self, repeated_capability_list, vi, library, encoding, freeze_it=Fa param_list.append("encoding=" + pp.pformat(encoding)) self._param_list = ', '.join(param_list) + # Instantiate any repeated capability objects + self.channels = _RepeatedCapabilities(self, '', repeated_capability_list) + self.pins = _RepeatedCapabilities(self, '', repeated_capability_list) + self.instruments = _RepeatedCapabilities(self, '', repeated_capability_list) + self.pattern_opcode_events = _RepeatedCapabilities(self, 'patternOpcodeEvent', repeated_capability_list) + self.conditional_jump_triggers = _RepeatedCapabilities(self, 'conditionalJumpTrigger', repeated_capability_list) + self.sites = _RepeatedCapabilities(self, 'site', repeated_capability_list) + self._is_frozen = freeze_it def __repr__(self): @@ -2452,14 +2465,6 @@ def __init__(self, resource_name, id_query=False, reset_device=False, options={} self._vi = 0 # This must be set before calling _init_with_options(). self._vi = self._init_with_options(resource_name, id_query, reset_device, options) - # Instantiate any repeated capability objects - self.channels = _RepeatedCapabilities(self, '') - self.pins = _RepeatedCapabilities(self, '') - self.instruments = _RepeatedCapabilities(self, '') - self.pattern_opcode_events = _RepeatedCapabilities(self, 'patternOpcodeEvent') - self.conditional_jump_triggers = _RepeatedCapabilities(self, 'conditionalJumpTrigger') - self.sites = _RepeatedCapabilities(self, 'site') - self.tclk = nitclk.SessionReference(self._vi) # Store the parameter list for later printing in __repr__ diff --git a/generated/nidmm/nidmm/session.py b/generated/nidmm/nidmm/session.py index b1f3d1b02..09e800905 100644 --- a/generated/nidmm/nidmm/session.py +++ b/generated/nidmm/nidmm/session.py @@ -1153,8 +1153,6 @@ def __init__(self, resource_name, id_query=False, reset_device=False, options={} self._vi = 0 # This must be set before calling _init_with_options(). self._vi = self._init_with_options(resource_name, id_query, reset_device, options) - # Instantiate any repeated capability objects - # Store the parameter list for later printing in __repr__ param_list = [] param_list.append("resource_name=" + pp.pformat(resource_name)) diff --git a/generated/nifake/nifake/session.py b/generated/nifake/nifake/session.py index 05409e8d1..4d3578be4 100644 --- a/generated/nifake/nifake/session.py +++ b/generated/nifake/nifake/session.py @@ -90,15 +90,20 @@ def __exit__(self, exc_type, exc_value, traceback): class _RepeatedCapabilities(object): - def __init__(self, session, prefix): + def __init__(self, session, prefix, current_repeated_capability_list): self._session = session self._prefix = prefix + # We need at least one element. If we get an empty list, make the one element an empty string + self._current_repeated_capability_list = current_repeated_capability_list if len(current_repeated_capability_list) > 0 else [''] + # Now we know there is at lease one entry, so we look if it is an empty string or not + self._separator = '/' if len(self._current_repeated_capability_list[0]) > 0 else '' 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] - return _SessionBase(vi=self._session._vi, repeated_capability_list=rep_caps_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) + return _SessionBase(vi=self._session._vi, repeated_capability_list=complete_rep_cap_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) # This is a very simple context manager we can use when we need to set/get attributes @@ -192,6 +197,10 @@ def __init__(self, repeated_capability_list, vi, library, encoding, freeze_it=Fa param_list.append("encoding=" + pp.pformat(encoding)) self._param_list = ', '.join(param_list) + # Instantiate any repeated capability objects + self.channels = _RepeatedCapabilities(self, '', repeated_capability_list) + self.sites = _RepeatedCapabilities(self, 'site', repeated_capability_list) + self._is_frozen = freeze_it def __repr__(self): @@ -701,9 +710,6 @@ def __init__(self, resource_name, options={}, id_query=False, reset_device=False self._vi = 0 # This must be set before calling _init_with_options(). self._vi = self._init_with_options(resource_name, options, id_query, reset_device) - # Instantiate any repeated capability objects - self.channels = _RepeatedCapabilities(self, '') - self.tclk = nitclk.SessionReference(self._vi) # Store the parameter list for later printing in __repr__ diff --git a/generated/nifake/nifake/unit_tests/test_session.py b/generated/nifake/nifake/unit_tests/test_session.py index 309012f0e..252907969 100644 --- a/generated/nifake/nifake/unit_tests/test_session.py +++ b/generated/nifake/nifake/unit_tests/test_session.py @@ -857,6 +857,21 @@ def test_repeated_capabilities_list(self): with nifake.Session('dev1') as session: assert session.channels['r0']._repeated_capability_list == ['r0'] + def test_chained_repeated_capabilities_list(self): + with nifake.Session('dev1') as session: + assert session.sites[0, 1].channels[2, 3]._repeated_capability_list == ['site0/2', 'site0/3', 'site1/2', 'site1/3'] + + def test_chained_repeated_capability_method_on_specific_channel(self): + test_maximum_time_ms = 10 # milliseconds + test_maximum_time = datetime.timedelta(milliseconds=test_maximum_time_ms) + test_reading = 5 + self.patched_library.niFake_ReadFromChannel.side_effect = self.side_effects_helper.niFake_ReadFromChannel + self.side_effects_helper['ReadFromChannel']['reading'] = test_reading + with nifake.Session('dev1') as session: + value = session.sites[0, 1].channels[2, 3].read_from_channel(test_maximum_time) + self.patched_library.niFake_ReadFromChannel.assert_called_once_with(_matchers.ViSessionMatcher(SESSION_NUM_FOR_TEST), _matchers.ViStringMatcher('site0/2,site0/3,site1/2,site1/3'), _matchers.ViInt32Matcher(test_maximum_time_ms), _matchers.ViReal64PointerMatcher()) + assert value == test_reading + # Attributes def test_get_attribute_int32(self): diff --git a/generated/nifgen/nifgen/session.py b/generated/nifgen/nifgen/session.py index e56ed5e03..07b6c0687 100644 --- a/generated/nifgen/nifgen/session.py +++ b/generated/nifgen/nifgen/session.py @@ -88,15 +88,20 @@ def __exit__(self, exc_type, exc_value, traceback): class _RepeatedCapabilities(object): - def __init__(self, session, prefix): + def __init__(self, session, prefix, current_repeated_capability_list): self._session = session self._prefix = prefix + # We need at least one element. If we get an empty list, make the one element an empty string + self._current_repeated_capability_list = current_repeated_capability_list if len(current_repeated_capability_list) > 0 else [''] + # Now we know there is at lease one entry, so we look if it is an empty string or not + self._separator = '/' if len(self._current_repeated_capability_list[0]) > 0 else '' 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] - return _SessionBase(vi=self._session._vi, repeated_capability_list=rep_caps_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) + return _SessionBase(vi=self._session._vi, repeated_capability_list=complete_rep_cap_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) # This is a very simple context manager we can use when we need to set/get attributes @@ -921,6 +926,11 @@ def __init__(self, repeated_capability_list, vi, library, encoding, freeze_it=Fa param_list.append("encoding=" + pp.pformat(encoding)) self._param_list = ', '.join(param_list) + # Instantiate any repeated capability objects + self.channels = _RepeatedCapabilities(self, '', repeated_capability_list) + self.script_triggers = _RepeatedCapabilities(self, 'ScriptTrigger', repeated_capability_list) + self.markers = _RepeatedCapabilities(self, 'Marker', repeated_capability_list) + self._is_frozen = freeze_it def __repr__(self): @@ -3056,11 +3066,6 @@ def __init__(self, resource_name, channel_name=None, reset_device=False, options self._vi = 0 # This must be set before calling _initialize_with_channels(). self._vi = self._initialize_with_channels(resource_name, channel_name, reset_device, options) - # Instantiate any repeated capability objects - self.channels = _RepeatedCapabilities(self, '') - self.script_triggers = _RepeatedCapabilities(self, 'ScriptTrigger') - self.markers = _RepeatedCapabilities(self, 'Marker') - self.tclk = nitclk.SessionReference(self._vi) # Store the parameter list for later printing in __repr__ diff --git a/generated/niscope/niscope/session.py b/generated/niscope/niscope/session.py index f50c1302c..3c008496b 100644 --- a/generated/niscope/niscope/session.py +++ b/generated/niscope/niscope/session.py @@ -90,15 +90,20 @@ def __exit__(self, exc_type, exc_value, traceback): class _RepeatedCapabilities(object): - def __init__(self, session, prefix): + def __init__(self, session, prefix, current_repeated_capability_list): self._session = session self._prefix = prefix + # We need at least one element. If we get an empty list, make the one element an empty string + self._current_repeated_capability_list = current_repeated_capability_list if len(current_repeated_capability_list) > 0 else [''] + # Now we know there is at lease one entry, so we look if it is an empty string or not + self._separator = '/' if len(self._current_repeated_capability_list[0]) > 0 else '' 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] - return _SessionBase(vi=self._session._vi, repeated_capability_list=rep_caps_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) + return _SessionBase(vi=self._session._vi, repeated_capability_list=complete_rep_cap_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) # This is a very simple context manager we can use when we need to set/get attributes @@ -1516,6 +1521,9 @@ def __init__(self, repeated_capability_list, vi, library, encoding, freeze_it=Fa param_list.append("encoding=" + pp.pformat(encoding)) self._param_list = ', '.join(param_list) + # Instantiate any repeated capability objects + self.channels = _RepeatedCapabilities(self, '', repeated_capability_list) + self._is_frozen = freeze_it def __repr__(self): @@ -3896,9 +3904,6 @@ def __init__(self, resource_name, id_query=False, reset_device=False, options={} self._vi = 0 # This must be set before calling _init_with_options(). self._vi = self._init_with_options(resource_name, id_query, reset_device, options) - # Instantiate any repeated capability objects - self.channels = _RepeatedCapabilities(self, '') - self.tclk = nitclk.SessionReference(self._vi) # Store the parameter list for later printing in __repr__ diff --git a/generated/nise/nise/session.py b/generated/nise/nise/session.py index 12857d7a2..3435b41e5 100644 --- a/generated/nise/nise/session.py +++ b/generated/nise/nise/session.py @@ -237,8 +237,6 @@ def __init__(self, virtual_device_name, options={}): self._vi = 0 # This must be set before calling _open_session(). self._vi = self._open_session(virtual_device_name, options) - # Instantiate any repeated capability objects - # Store the parameter list for later printing in __repr__ param_list = [] param_list.append("virtual_device_name=" + pp.pformat(virtual_device_name)) diff --git a/generated/niswitch/niswitch/session.py b/generated/niswitch/niswitch/session.py index b1cc907a8..e98a477cd 100644 --- a/generated/niswitch/niswitch/session.py +++ b/generated/niswitch/niswitch/session.py @@ -87,15 +87,20 @@ def __exit__(self, exc_type, exc_value, traceback): class _RepeatedCapabilities(object): - def __init__(self, session, prefix): + def __init__(self, session, prefix, current_repeated_capability_list): self._session = session self._prefix = prefix + # We need at least one element. If we get an empty list, make the one element an empty string + self._current_repeated_capability_list = current_repeated_capability_list if len(current_repeated_capability_list) > 0 else [''] + # Now we know there is at lease one entry, so we look if it is an empty string or not + self._separator = '/' if len(self._current_repeated_capability_list[0]) > 0 else '' 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] - return _SessionBase(vi=self._session._vi, repeated_capability_list=rep_caps_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) + return _SessionBase(vi=self._session._vi, repeated_capability_list=complete_rep_cap_list, library=self._session._library, encoding=self._session._encoding, freeze_it=True) # This is a very simple context manager we can use when we need to set/get attributes @@ -526,6 +531,9 @@ def __init__(self, repeated_capability_list, vi, library, encoding, freeze_it=Fa param_list.append("encoding=" + pp.pformat(encoding)) self._param_list = ', '.join(param_list) + # Instantiate any repeated capability objects + self.channels = _RepeatedCapabilities(self, '', repeated_capability_list) + self._is_frozen = freeze_it def __repr__(self): @@ -1445,9 +1453,6 @@ def __init__(self, resource_name, topology="Configured Topology", simulate=False self._vi = 0 # This must be set before calling _init_with_topology(). self._vi = self._init_with_topology(resource_name, topology, simulate, reset_device) - # Instantiate any repeated capability objects - self.channels = _RepeatedCapabilities(self, '') - # Store the parameter list for later printing in __repr__ param_list = [] param_list.append("resource_name=" + pp.pformat(resource_name)) diff --git a/src/nifake/metadata/config.py b/src/nifake/metadata/config.py index fb1ab66ed..ca6750ebf 100644 --- a/src/nifake/metadata/config.py +++ b/src/nifake/metadata/config.py @@ -49,7 +49,11 @@ { 'prefix': '', 'python_name': 'channels' - } + }, + { + 'prefix': 'site', + 'python_name': 'sites', + }, ], 'session_class_description': 'An NI-FAKE session to a fake MI driver whose sole purpose is to test nimi-python code generation', 'session_handle_parameter_name': 'vi', diff --git a/src/nifake/unit_tests/test_session.py b/src/nifake/unit_tests/test_session.py index 309012f0e..252907969 100644 --- a/src/nifake/unit_tests/test_session.py +++ b/src/nifake/unit_tests/test_session.py @@ -857,6 +857,21 @@ def test_repeated_capabilities_list(self): with nifake.Session('dev1') as session: assert session.channels['r0']._repeated_capability_list == ['r0'] + def test_chained_repeated_capabilities_list(self): + with nifake.Session('dev1') as session: + assert session.sites[0, 1].channels[2, 3]._repeated_capability_list == ['site0/2', 'site0/3', 'site1/2', 'site1/3'] + + def test_chained_repeated_capability_method_on_specific_channel(self): + test_maximum_time_ms = 10 # milliseconds + test_maximum_time = datetime.timedelta(milliseconds=test_maximum_time_ms) + test_reading = 5 + self.patched_library.niFake_ReadFromChannel.side_effect = self.side_effects_helper.niFake_ReadFromChannel + self.side_effects_helper['ReadFromChannel']['reading'] = test_reading + with nifake.Session('dev1') as session: + value = session.sites[0, 1].channels[2, 3].read_from_channel(test_maximum_time) + self.patched_library.niFake_ReadFromChannel.assert_called_once_with(_matchers.ViSessionMatcher(SESSION_NUM_FOR_TEST), _matchers.ViStringMatcher('site0/2,site0/3,site1/2,site1/3'), _matchers.ViInt32Matcher(test_maximum_time_ms), _matchers.ViReal64PointerMatcher()) + assert value == test_reading + # Attributes def test_get_attribute_int32(self):