From d4f95efbfd46def36a3c51c8beffdd8b66c3a90c Mon Sep 17 00:00:00 2001 From: sbethur <48041236+sbethur@users.noreply.github.com> Date: Sun, 29 Mar 2020 23:21:27 -0500 Subject: [PATCH] Update applicable methods in nidigital to use sites repeated capability Methods updated: - fetch_history_ram_cycle_information - get_history_ram_sample_count - is_site_enabled --- CHANGELOG.md | 1 + build/templates/_converters.py.mako | 118 +++--- docs/nidigital/class.rst | 49 +-- generated/nidcpower/nidcpower/_converters.py | 52 ++- generated/nidigital/nidigital/_converters.py | 65 ++- generated/nidigital/nidigital/session.py | 380 ++++++++++-------- .../nidigital/unit_tests/test_nidigital.py | 5 +- generated/nidmm/nidmm/_converters.py | 52 ++- generated/nifake/nifake/_converters.py | 62 ++- generated/nifgen/nifgen/_converters.py | 52 ++- generated/nimodinst/nimodinst/_converters.py | 35 +- generated/niscope/niscope/_converters.py | 52 ++- generated/nise/nise/_converters.py | 52 ++- generated/niswitch/niswitch/_converters.py | 52 ++- generated/nitclk/nitclk/_converters.py | 81 ++-- src/nidigital/metadata/functions.py | 18 +- src/nidigital/metadata/functions_addon.py | 21 +- .../system_tests/test_system_nidigital.py | 93 ++--- ...etch_history_ram_cycle_information.py.mako | 36 +- src/nidigital/unit_tests/test_nidigital.py | 5 +- 20 files changed, 816 insertions(+), 465 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02c089c3a..13c19d7f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ All notable changes to this project will be documented in this file. * Update the names of many enum types. See [#1330](https://github.com/ni/nimi-python/issues/1330) for the full list. * Added `WriteStaticPinState` enum type and changed the parameter type of `write_static` method to the newly added enum. * Added `SoftwareTrigger` enum type and changed the parameter type of `send_software_edge_trigger` method to the newly added enum. + * Update `fetch_history_ram_cycle_information`, `get_history_ram_sample_count`, and `is_site_enabled` to use `sites` repeated capability - [#1337](https://github.com/ni/nimi-python/issues/1337) * #### Removed * `get_pattern_pin_list`, `get_pattern_pin_indexes` and `get_pin_name` - [#1292](https://github.com/ni/nimi-python/issues/1292) * `get_site_results_site_numbers` method and `SiteResultType` enum - [#1298](https://github.com/ni/nimi-python/issues/1298) diff --git a/build/templates/_converters.py.mako b/build/templates/_converters.py.mako index 521f049fc..4607b7f0d 100644 --- a/build/templates/_converters.py.mako +++ b/build/templates/_converters.py.mako @@ -9,6 +9,7 @@ import ${module_name}._visatype as _visatype import ${module_name}.errors as errors import array +import collections import datetime import numbers @@ -117,7 +118,7 @@ def convert_repeated_capabilities(repeated_capability, prefix=''): prefix (str) - common prefix for all strings Returns: - rep_cal_list (list of str) - list of each repeated capability item with ranges expanded and prefix added + rep_cap_list (list of str) - list of each repeated capability item with ranges expanded and prefix added ''' # We need to explicitly handle None here. Everything else we can pass on to the singledispatch functions if repeated_capability is None: @@ -135,7 +136,7 @@ def convert_repeated_capabilities_from_init(repeated_capability): repeated_capability (str, list, tuple, slice, None) - Returns: - rep_cal (str) - comma delimited string of each repeated capability item with ranges expanded + rep_cap (str) - comma delimited string of each repeated capability item with ranges expanded ''' return ','.join(convert_repeated_capabilities(repeated_capability, '')) @@ -215,6 +216,54 @@ def convert_init_with_options_dictionary(values): return init_with_options_string +# convert value to bytes +@singledispatch +def _convert_to_bytes(value): # noqa: F811 + pass + + +@_convert_to_bytes.register(list) # noqa: F811 +@_convert_to_bytes.register(bytes) # noqa: F811 +@_convert_to_bytes.register(bytearray) # noqa: F811 +@_convert_to_bytes.register(array.array) # noqa: F811 +def _(value): + return value + + +@_convert_to_bytes.register(str) # noqa: F811 +def _(value): + return value.encode() + + +def convert_to_bytes(value): # noqa: F811 + return bytes(_convert_to_bytes(value)) + + +def convert_comma_separated_string_to_list(comma_separated_string): + return [x.strip() for x in comma_separated_string.split(',')] + + +def convert_chained_repeated_capability_to_parts(chained_repeated_capability): + '''Convert a chained repeated capabilities string to a list of comma-delimited repeated capabilities string. + + Converter assumes that the input contains the full cartesian product of its parts. + e.g. If chained_repeated_capability is 'site0/PinA,site0/PinB,site1/PinA,site1/PinB', + ['site0,site1', 'PinA,PinB'] is returned. + + Args: + chained_repeated_capability (str) - comma-delimited repeated capabilities string where each + item is a chain of slash-delimited repeated capabilities + + Returns: + rep_cap_list (list of str) - list of comma-delimited repeated capabilities string + ''' + chained_repeated_capability_items = convert_comma_separated_string_to_list(chained_repeated_capability) + repeated_capability_lists = [[] for _ in range(chained_repeated_capability_items[0].count('/') + 1)] + for item in chained_repeated_capability_items: + repeated_capability_lists = [x + [y] for x, y in zip(repeated_capability_lists, item.split('/'))] + return [','.join(collections.OrderedDict.fromkeys(x)) for x in repeated_capability_lists] + + <% # Beginning of module-specific converters %>\ @@ -259,53 +308,6 @@ def convert_double_each_element(numbers): % endif -<% -# There are some parameters in nidigital that cannot be made into a repeated capability because the -# methods already have a repeated capability (pins), and we want the parameter to behave similarly -# to repeated capabilities. -%>\ -% if config['module_name'] == 'nidigital': -def convert_site_to_string(site): - if isinstance(site, str): - if site.startswith('site'): - return site - else: - return convert_site_to_string(int(site)) - else: - if type(site) != int: - # Don't use assert here since this comes from the user - raise TypeError('site must be a string or an integer. Actual: {}'.format(type(site))) - return 'site' + str(site) - - -% endif -# convert value to bytes -@singledispatch -def _convert_to_bytes(value): # noqa: F811 - pass - - -def convert_comma_separated_string_to_list(comma_separated_string): - return [x.strip() for x in comma_separated_string.split(',')] - - -@_convert_to_bytes.register(list) # noqa: F811 -@_convert_to_bytes.register(bytes) # noqa: F811 -@_convert_to_bytes.register(bytearray) # noqa: F811 -@_convert_to_bytes.register(array.array) # noqa: F811 -def _(value): - return value - - -@_convert_to_bytes.register(str) # noqa: F811 -def _(value): - return value.encode() - - -def convert_to_bytes(value): # noqa: F811 - return bytes(_convert_to_bytes(value)) - - # Let's run some tests def test_convert_init_with_options_dictionary(): assert convert_init_with_options_dictionary('') == '' @@ -535,6 +537,23 @@ def test_repeated_capabilies_from_init(): assert test_result == '0,2,4,5,6,7,8,9,11,12,13,14,16,17' +def test_convert_chained_repeated_capability_to_parts_three_parts(): + chained_rep_cap = ('site0/test/PinA,site0/test/PinB,site0/test/PinC,' + 'site1/test/PinA,site1/test/PinB,site1/test/PinC') + rep_cap_list = convert_chained_repeated_capability_to_parts(chained_rep_cap) + assert rep_cap_list == ['site0,site1', 'test', 'PinA,PinB,PinC'] + + +def test_convert_chained_repeated_capability_to_parts_single_part(): + rep_cap_list = convert_chained_repeated_capability_to_parts('site0, site1') + assert rep_cap_list == ['site0,site1'] + + +def test_convert_chained_repeated_capability_to_parts_empty_string(): + rep_cap_list = convert_chained_repeated_capability_to_parts('') + assert rep_cap_list == [''] + + % endif def test_string_to_list_channel(): test_result = _convert_repeated_capabilities('r0', '') @@ -563,4 +582,3 @@ def test_string_to_list_prefix(): def test_convert_comma_separated_string_to_list(): out_list = convert_comma_separated_string_to_list(' PinA , PinB , PinC ') assert out_list == ['PinA', 'PinB', 'PinC'] - diff --git a/docs/nidigital/class.rst b/docs/nidigital/class.rst index c7c7a301e..0c4e959ea 100644 --- a/docs/nidigital/class.rst +++ b/docs/nidigital/class.rst @@ -1142,7 +1142,7 @@ fetch_history_ram_cycle_information .. py:currentmodule:: nidigital.Session - .. py:method:: fetch_history_ram_cycle_information(site, position, samples_to_read) + .. py:method:: fetch_history_ram_cycle_information(position, samples_to_read) Returns the pattern information acquired for the specified cycles. @@ -1150,9 +1150,16 @@ fetch_history_ram_cycle_information consist of multiple DUT cycles. When using pins with mixed edge multipliers, pins may return :py:data:`~nidigital.PinState.PIN_STATE_NOT_ACQUIRED` for DUT cycles where those pins do not have edges defined. + Site number on which to retrieve pattern information must be specified via sites repeated capability. + The method returns an error if more than one site is specified. + + Pins for which to retrieve pattern information must be specified via pins repeated capability. If pins are not specified, pin list from the pattern containing the start label is used. Call - :py:meth:`nidigital.Session.get_pattern_pin_names` with the start label to retrieve the pins - associated with the pattern burst. + :py:meth:`nidigital.Session.get_pattern_pin_names` with the start label to retrieve the pins associated with the pattern burst: + + .. code:: python + + session.sites[0].pins['PinA', 'PinB'].fetch_history_ram_cycle_information(0, -1) @@ -1163,16 +1170,6 @@ fetch_history_ram_cycle_information nidigital.Session repeated capabilities container, and calling this method on the result. - :param site: - - - Site on which to retrieve History RAM data. Specify site as a string in the form of siteN, - where N is the site number. The VI returns an error if more than one site is specified. - - - - - :type site: str or int :param position: @@ -1342,21 +1339,18 @@ get_history_ram_sample_count .. py:currentmodule:: nidigital.Session - .. py:method:: get_history_ram_sample_count(site) + .. py:method:: get_history_ram_sample_count() TBD + .. tip:: This method requires repeated capabilities. If called directly on the + nidigital.Session object, then the method will use all repeated capabilities in the session. + You can specify a subset of repeated capabilities using the Python index notation on an + nidigital.Session repeated capabilities container, and calling this method on the result. - :param site: - - - - - - :type site: str or int :rtype: int :return: @@ -1698,21 +1692,18 @@ is_site_enabled .. py:currentmodule:: nidigital.Session - .. py:method:: is_site_enabled(site) + .. py:method:: is_site_enabled() TBD + .. tip:: This method requires repeated capabilities. If called directly on the + nidigital.Session object, then the method will use all repeated capabilities in the session. + You can specify a subset of repeated capabilities using the Python index notation on an + nidigital.Session repeated capabilities container, and calling this method on the result. - :param site: - - - - - - :type site: str or int :rtype: bool :return: diff --git a/generated/nidcpower/nidcpower/_converters.py b/generated/nidcpower/nidcpower/_converters.py index 16ed86a13..684156f51 100644 --- a/generated/nidcpower/nidcpower/_converters.py +++ b/generated/nidcpower/nidcpower/_converters.py @@ -4,6 +4,7 @@ import nidcpower.errors as errors import array +import collections import datetime import numbers @@ -112,7 +113,7 @@ def convert_repeated_capabilities(repeated_capability, prefix=''): prefix (str) - common prefix for all strings Returns: - rep_cal_list (list of str) - list of each repeated capability item with ranges expanded and prefix added + rep_cap_list (list of str) - list of each repeated capability item with ranges expanded and prefix added ''' # We need to explicitly handle None here. Everything else we can pass on to the singledispatch functions if repeated_capability is None: @@ -130,7 +131,7 @@ def convert_repeated_capabilities_from_init(repeated_capability): repeated_capability (str, list, tuple, slice, None) - Returns: - rep_cal (str) - comma delimited string of each repeated capability item with ranges expanded + rep_cap (str) - comma delimited string of each repeated capability item with ranges expanded ''' return ','.join(convert_repeated_capabilities(repeated_capability, '')) @@ -216,10 +217,6 @@ def _convert_to_bytes(value): # noqa: F811 pass -def convert_comma_separated_string_to_list(comma_separated_string): - return [x.strip() for x in comma_separated_string.split(',')] - - @_convert_to_bytes.register(list) # noqa: F811 @_convert_to_bytes.register(bytes) # noqa: F811 @_convert_to_bytes.register(bytearray) # noqa: F811 @@ -237,6 +234,31 @@ def convert_to_bytes(value): # noqa: F811 return bytes(_convert_to_bytes(value)) +def convert_comma_separated_string_to_list(comma_separated_string): + return [x.strip() for x in comma_separated_string.split(',')] + + +def convert_chained_repeated_capability_to_parts(chained_repeated_capability): + '''Convert a chained repeated capabilities string to a list of comma-delimited repeated capabilities string. + + Converter assumes that the input contains the full cartesian product of its parts. + e.g. If chained_repeated_capability is 'site0/PinA,site0/PinB,site1/PinA,site1/PinB', + ['site0,site1', 'PinA,PinB'] is returned. + + Args: + chained_repeated_capability (str) - comma-delimited repeated capabilities string where each + item is a chain of slash-delimited repeated capabilities + + Returns: + rep_cap_list (list of str) - list of comma-delimited repeated capabilities string + ''' + chained_repeated_capability_items = convert_comma_separated_string_to_list(chained_repeated_capability) + repeated_capability_lists = [[] for _ in range(chained_repeated_capability_items[0].count('/') + 1)] + for item in chained_repeated_capability_items: + repeated_capability_lists = [x + [y] for x, y in zip(repeated_capability_lists, item.split('/'))] + return [','.join(collections.OrderedDict.fromkeys(x)) for x in repeated_capability_lists] + + # Let's run some tests def test_convert_init_with_options_dictionary(): assert convert_init_with_options_dictionary('') == '' @@ -461,6 +483,23 @@ def test_repeated_capabilies_from_init(): assert test_result == '0,2,4,5,6,7,8,9,11,12,13,14,16,17' +def test_convert_chained_repeated_capability_to_parts_three_parts(): + chained_rep_cap = ('site0/test/PinA,site0/test/PinB,site0/test/PinC,' + 'site1/test/PinA,site1/test/PinB,site1/test/PinC') + rep_cap_list = convert_chained_repeated_capability_to_parts(chained_rep_cap) + assert rep_cap_list == ['site0,site1', 'test', 'PinA,PinB,PinC'] + + +def test_convert_chained_repeated_capability_to_parts_single_part(): + rep_cap_list = convert_chained_repeated_capability_to_parts('site0, site1') + assert rep_cap_list == ['site0,site1'] + + +def test_convert_chained_repeated_capability_to_parts_empty_string(): + rep_cap_list = convert_chained_repeated_capability_to_parts('') + assert rep_cap_list == [''] + + def test_string_to_list_channel(): test_result = _convert_repeated_capabilities('r0', '') assert test_result == ['r0'] @@ -488,4 +527,3 @@ def test_string_to_list_prefix(): def test_convert_comma_separated_string_to_list(): out_list = convert_comma_separated_string_to_list(' PinA , PinB , PinC ') assert out_list == ['PinA', 'PinB', 'PinC'] - diff --git a/generated/nidigital/nidigital/_converters.py b/generated/nidigital/nidigital/_converters.py index ba61575c7..e6c9bb417 100644 --- a/generated/nidigital/nidigital/_converters.py +++ b/generated/nidigital/nidigital/_converters.py @@ -4,6 +4,7 @@ import nidigital.errors as errors import array +import collections import datetime import numbers @@ -112,7 +113,7 @@ def convert_repeated_capabilities(repeated_capability, prefix=''): prefix (str) - common prefix for all strings Returns: - rep_cal_list (list of str) - list of each repeated capability item with ranges expanded and prefix added + rep_cap_list (list of str) - list of each repeated capability item with ranges expanded and prefix added ''' # We need to explicitly handle None here. Everything else we can pass on to the singledispatch functions if repeated_capability is None: @@ -130,7 +131,7 @@ def convert_repeated_capabilities_from_init(repeated_capability): repeated_capability (str, list, tuple, slice, None) - Returns: - rep_cal (str) - comma delimited string of each repeated capability item with ranges expanded + rep_cap (str) - comma delimited string of each repeated capability item with ranges expanded ''' return ','.join(convert_repeated_capabilities(repeated_capability, '')) @@ -210,29 +211,12 @@ def convert_init_with_options_dictionary(values): return init_with_options_string -def convert_site_to_string(site): - if isinstance(site, str): - if site.startswith('site'): - return site - else: - return convert_site_to_string(int(site)) - else: - if type(site) != int: - # Don't use assert here since this comes from the user - raise TypeError('site must be a string or an integer. Actual: {}'.format(type(site))) - return 'site' + str(site) - - # convert value to bytes @singledispatch def _convert_to_bytes(value): # noqa: F811 pass -def convert_comma_separated_string_to_list(comma_separated_string): - return [x.strip() for x in comma_separated_string.split(',')] - - @_convert_to_bytes.register(list) # noqa: F811 @_convert_to_bytes.register(bytes) # noqa: F811 @_convert_to_bytes.register(bytearray) # noqa: F811 @@ -250,6 +234,31 @@ def convert_to_bytes(value): # noqa: F811 return bytes(_convert_to_bytes(value)) +def convert_comma_separated_string_to_list(comma_separated_string): + return [x.strip() for x in comma_separated_string.split(',')] + + +def convert_chained_repeated_capability_to_parts(chained_repeated_capability): + '''Convert a chained repeated capabilities string to a list of comma-delimited repeated capabilities string. + + Converter assumes that the input contains the full cartesian product of its parts. + e.g. If chained_repeated_capability is 'site0/PinA,site0/PinB,site1/PinA,site1/PinB', + ['site0,site1', 'PinA,PinB'] is returned. + + Args: + chained_repeated_capability (str) - comma-delimited repeated capabilities string where each + item is a chain of slash-delimited repeated capabilities + + Returns: + rep_cap_list (list of str) - list of comma-delimited repeated capabilities string + ''' + chained_repeated_capability_items = convert_comma_separated_string_to_list(chained_repeated_capability) + repeated_capability_lists = [[] for _ in range(chained_repeated_capability_items[0].count('/') + 1)] + for item in chained_repeated_capability_items: + repeated_capability_lists = [x + [y] for x, y in zip(repeated_capability_lists, item.split('/'))] + return [','.join(collections.OrderedDict.fromkeys(x)) for x in repeated_capability_lists] + + # Let's run some tests def test_convert_init_with_options_dictionary(): assert convert_init_with_options_dictionary('') == '' @@ -474,6 +483,23 @@ def test_repeated_capabilies_from_init(): assert test_result == '0,2,4,5,6,7,8,9,11,12,13,14,16,17' +def test_convert_chained_repeated_capability_to_parts_three_parts(): + chained_rep_cap = ('site0/test/PinA,site0/test/PinB,site0/test/PinC,' + 'site1/test/PinA,site1/test/PinB,site1/test/PinC') + rep_cap_list = convert_chained_repeated_capability_to_parts(chained_rep_cap) + assert rep_cap_list == ['site0,site1', 'test', 'PinA,PinB,PinC'] + + +def test_convert_chained_repeated_capability_to_parts_single_part(): + rep_cap_list = convert_chained_repeated_capability_to_parts('site0, site1') + assert rep_cap_list == ['site0,site1'] + + +def test_convert_chained_repeated_capability_to_parts_empty_string(): + rep_cap_list = convert_chained_repeated_capability_to_parts('') + assert rep_cap_list == [''] + + def test_string_to_list_channel(): test_result = _convert_repeated_capabilities('r0', '') assert test_result == ['r0'] @@ -501,4 +527,3 @@ def test_string_to_list_prefix(): def test_convert_comma_separated_string_to_list(): out_list = convert_comma_separated_string_to_list(' PinA , PinB , PinC ') assert out_list == ['PinA', 'PinB', 'PinC'] - diff --git a/generated/nidigital/nidigital/session.py b/generated/nidigital/nidigital/session.py index 2f080135c..2da097b56 100644 --- a/generated/nidigital/nidigital/session.py +++ b/generated/nidigital/nidigital/session.py @@ -1288,7 +1288,7 @@ def fetch_capture_waveform(self, waveform_name, samples_to_read, timeout=datetim return waveforms @ivi_synchronized - def fetch_history_ram_cycle_information(self, site, position, samples_to_read): + def fetch_history_ram_cycle_information(self, position, samples_to_read): '''fetch_history_ram_cycle_information Returns the pattern information acquired for the specified cycles. @@ -1297,9 +1297,16 @@ def fetch_history_ram_cycle_information(self, site, position, samples_to_read): consist of multiple DUT cycles. When using pins with mixed edge multipliers, pins may return PinState.PIN_STATE_NOT_ACQUIRED for DUT cycles where those pins do not have edges defined. + Site number on which to retrieve pattern information must be specified via sites repeated capability. + The method returns an error if more than one site is specified. + + Pins for which to retrieve pattern information must be specified via pins repeated capability. If pins are not specified, pin list from the pattern containing the start label is used. Call - get_pattern_pin_names with the start label to retrieve the pins - associated with the pattern burst. + get_pattern_pin_names with the start label to retrieve the pins associated with the pattern burst: + + .. code:: python + + session.sites[0].pins['PinA', 'PinB'].fetch_history_ram_cycle_information(0, -1) Tip: This method requires repeated capabilities. If called directly on the @@ -1308,9 +1315,6 @@ def fetch_history_ram_cycle_information(self, site, position, samples_to_read): nidigital.Session repeated capabilities container, and calling this method on the result. Args: - site (str or int): Site on which to retrieve History RAM data. Specify site as a string in the form of siteN, - where N is the site number. The VI returns an error if more than one site is specified. - position (int): Sample index from which to start fetching pattern information. samples_to_read (int): Number of samples to fetch. A value of -1 specifies to fetch all available samples. @@ -1345,21 +1349,34 @@ def fetch_history_ram_cycle_information(self, site, position, samples_to_read): Length of the inner list will be equal to the number of pins requested. ''' + # Extract the site number and pin list from repeated capability + repeated_capability_lists = _converters.convert_chained_repeated_capability_to_parts(self._repeated_capability) + site = repeated_capability_lists[0] + if not site.startswith('site'): + raise ValueError('Site number on which to retrieve pattern information must be specified via sites repeated capability.') + pins = '' if len(repeated_capability_lists) == 1 else repeated_capability_lists[1] + + # Put site back into repeated capability container; it will be used by other + # sites-rep-cap-based methods that will be called later. + self._repeated_capability = site + if position < 0: raise ValueError('position should be greater than or equal to 0.') if samples_to_read < -1: raise ValueError('samples_to_read should be greater than or equal to -1.') - samples_available = self.get_history_ram_sample_count(site) + # site is passed as repeated capability + samples_available = self.get_history_ram_sample_count() if position > samples_available: raise ValueError('position: Specified value = {0}, Maximum value = {1}.'.format(position, samples_available - 1)) if samples_to_read == -1: - if not self.history_ram_number_of_samples_is_finite: - raise RuntimeError( - 'Specifying -1 to fetch all History RAM samples is not supported when the digital pattern instrument is ' - 'configured for continuous History RAM acquisition. You must specify an exact number of samples to fetch.') + with _NoChannel(session=self): + if not self.history_ram_number_of_samples_is_finite: + raise RuntimeError( + 'Specifying -1 to fetch all History RAM samples is not supported when the digital pattern instrument is ' + 'configured for continuous History RAM acquisition. You must specify an exact number of samples to fetch.') samples_to_read = samples_available - position if position + samples_to_read > samples_available: @@ -1367,30 +1384,33 @@ def fetch_history_ram_cycle_information(self, site, position, samples_to_read): 'position: Specified value = {0}, samples_to_read: Specified value = {1}; Samples available = {2}.' .format(position, samples_to_read, samples_available - position)) - # Site can be 'N', N or 'siteN'. This will normalize all options to 'siteN' which is requried by the driver - site = _converters.convert_site_to_string(site) pattern_names = {} time_set_names = {} cycle_infos = [] for _ in range(samples_to_read): - pattern_index, time_set_index, vector_number, cycle_number, num_dut_cycles = self._fetch_history_ram_cycle_information(site, position) + # site is passed as repeated capability + pattern_index, time_set_index, vector_number, cycle_number, num_dut_cycles = self._fetch_history_ram_cycle_information(position) if pattern_index not in pattern_names: + # Repeated capability is not used pattern_names[pattern_index] = self.get_pattern_name(pattern_index) pattern_name = pattern_names[pattern_index] if time_set_index not in time_set_names: + # Repeated capability is not used time_set_names[time_set_index] = self.get_time_set_name(time_set_index) time_set_name = time_set_names[time_set_index] - scan_cycle_number = self._fetch_history_ram_scan_cycle_number(site, position) + # site is passed as repeated capability + scan_cycle_number = self._fetch_history_ram_scan_cycle_number(position) vector_expected_pin_states = [] vector_actual_pin_states = [] vector_per_pin_pass_fail = [] for dut_cycle_index in range(num_dut_cycles): - cycle_expected_pin_states, cycle_actual_pin_states, cycle_per_pin_pass_fail = self._fetch_history_ram_cycle_pin_data(site, position, dut_cycle_index) + # site is passed as repeated capability + cycle_expected_pin_states, cycle_actual_pin_states, cycle_per_pin_pass_fail = self._fetch_history_ram_cycle_pin_data(pins, position, dut_cycle_index) vector_expected_pin_states.append(cycle_expected_pin_states) vector_actual_pin_states.append(cycle_actual_pin_states) vector_per_pin_pass_fail.append(cycle_per_pin_pass_fail) @@ -1473,7 +1493,47 @@ def get_site_pass_fail(self): return dict(zip(site_list, result_list)) @ivi_synchronized - def _fetch_history_ram_cycle_pin_data(self, site, sample_index, dut_cycle_index): + def _fetch_history_ram_cycle_information(self, sample_index): + r'''_fetch_history_ram_cycle_information + + TBD + + Tip: + This method requires repeated capabilities. If called directly on the + nidigital.Session object, then the method will use all repeated capabilities in the session. + You can specify a subset of repeated capabilities using the Python index notation on an + nidigital.Session repeated capabilities container, and calling this method on the result. + + Args: + sample_index (int): + + + Returns: + pattern_index (int): + + time_set_index (int): + + vector_number (int): + + cycle_number (int): + + num_dut_cycles (int): + + ''' + vi_ctype = _visatype.ViSession(self._vi) # case S110 + site_ctype = ctypes.create_string_buffer(self._repeated_capability.encode(self._encoding)) # case C010 + sample_index_ctype = _visatype.ViInt64(sample_index) # case S150 + pattern_index_ctype = _visatype.ViInt32() # case S220 + time_set_index_ctype = _visatype.ViInt32() # case S220 + vector_number_ctype = _visatype.ViInt64() # case S220 + cycle_number_ctype = _visatype.ViInt64() # case S220 + num_dut_cycles_ctype = _visatype.ViInt32() # case S220 + error_code = self._library.niDigital_FetchHistoryRAMCycleInformation(vi_ctype, site_ctype, sample_index_ctype, None if pattern_index_ctype is None else (ctypes.pointer(pattern_index_ctype)), None if time_set_index_ctype is None else (ctypes.pointer(time_set_index_ctype)), None if vector_number_ctype is None else (ctypes.pointer(vector_number_ctype)), None if cycle_number_ctype is None else (ctypes.pointer(cycle_number_ctype)), None if num_dut_cycles_ctype is None else (ctypes.pointer(num_dut_cycles_ctype))) + errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) + return int(pattern_index_ctype.value), int(time_set_index_ctype.value), int(vector_number_ctype.value), int(cycle_number_ctype.value), int(num_dut_cycles_ctype.value) + + @ivi_synchronized + def _fetch_history_ram_cycle_pin_data(self, pin_list, sample_index, dut_cycle_index): r'''_fetch_history_ram_cycle_pin_data TBD @@ -1485,7 +1545,7 @@ def _fetch_history_ram_cycle_pin_data(self, site, sample_index, dut_cycle_index) nidigital.Session repeated capabilities container, and calling this method on the result. Args: - site (str): + pin_list (str): sample_index (int): @@ -1501,8 +1561,8 @@ def _fetch_history_ram_cycle_pin_data(self, site, sample_index, dut_cycle_index) ''' vi_ctype = _visatype.ViSession(self._vi) # case S110 - site_ctype = ctypes.create_string_buffer(site.encode(self._encoding)) # case C020 - pin_list_ctype = ctypes.create_string_buffer(self._repeated_capability.encode(self._encoding)) # case C010 + site_ctype = ctypes.create_string_buffer(self._repeated_capability.encode(self._encoding)) # case C010 + pin_list_ctype = ctypes.create_string_buffer(pin_list.encode(self._encoding)) # case C020 sample_index_ctype = _visatype.ViInt64(sample_index) # case S150 dut_cycle_index_ctype = _visatype.ViInt32(dut_cycle_index) # case S150 pin_data_buffer_size_ctype = _visatype.ViInt32(0) # case S190 @@ -1523,6 +1583,34 @@ def _fetch_history_ram_cycle_pin_data(self, site, sample_index, dut_cycle_index) errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) return [enums.PinState(expected_pin_states_ctype[i]) for i in range(pin_data_buffer_size_ctype.value)], [enums.PinState(actual_pin_states_ctype[i]) for i in range(pin_data_buffer_size_ctype.value)], [bool(per_pin_pass_fail_ctype[i]) for i in range(pin_data_buffer_size_ctype.value)] + @ivi_synchronized + def _fetch_history_ram_scan_cycle_number(self, sample_index): + r'''_fetch_history_ram_scan_cycle_number + + TBD + + Tip: + This method requires repeated capabilities. If called directly on the + nidigital.Session object, then the method will use all repeated capabilities in the session. + You can specify a subset of repeated capabilities using the Python index notation on an + nidigital.Session repeated capabilities container, and calling this method on the result. + + Args: + sample_index (int): + + + Returns: + scan_cycle_number (int): + + ''' + vi_ctype = _visatype.ViSession(self._vi) # case S110 + site_ctype = ctypes.create_string_buffer(self._repeated_capability.encode(self._encoding)) # case C010 + sample_index_ctype = _visatype.ViInt64(sample_index) # case S150 + scan_cycle_number_ctype = _visatype.ViInt64() # case S220 + error_code = self._library.niDigital_FetchHistoryRAMScanCycleNumber(vi_ctype, site_ctype, sample_index_ctype, None if scan_cycle_number_ctype is None else (ctypes.pointer(scan_cycle_number_ctype))) + errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) + return int(scan_cycle_number_ctype.value) + @ivi_synchronized def frequency_counter_measure_frequency(self): r'''frequency_counter_measure_frequency @@ -1777,6 +1865,55 @@ def get_fail_count(self): errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) return [int(failure_count_ctype[i]) for i in range(buffer_size_ctype.value)] + @ivi_synchronized + def get_history_ram_sample_count(self): + r'''get_history_ram_sample_count + + TBD + + Tip: + This method requires repeated capabilities. If called directly on the + nidigital.Session object, then the method will use all repeated capabilities in the session. + You can specify a subset of repeated capabilities using the Python index notation on an + nidigital.Session repeated capabilities container, and calling this method on the result. + + Returns: + sample_count (int): + + ''' + vi_ctype = _visatype.ViSession(self._vi) # case S110 + site_ctype = ctypes.create_string_buffer(self._repeated_capability.encode(self._encoding)) # case C010 + sample_count_ctype = _visatype.ViInt64() # case S220 + error_code = self._library.niDigital_GetHistoryRAMSampleCount(vi_ctype, site_ctype, None if sample_count_ctype is None else (ctypes.pointer(sample_count_ctype))) + errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) + return int(sample_count_ctype.value) + + @ivi_synchronized + def get_pattern_name(self, pattern_index): + r'''get_pattern_name + + TBD + + Args: + pattern_index (int): + + + Returns: + name (str): + + ''' + vi_ctype = _visatype.ViSession(self._vi) # case S110 + pattern_index_ctype = _visatype.ViInt32(pattern_index) # case S150 + name_buffer_size_ctype = _visatype.ViInt32() # case S170 + name_ctype = None # case C050 + error_code = self._library.niDigital_GetPatternName(vi_ctype, pattern_index_ctype, name_buffer_size_ctype, name_ctype) + errors.handle_error(self, error_code, ignore_warnings=True, is_error_handling=False) + name_buffer_size_ctype = _visatype.ViInt32(error_code) # case S180 + name_ctype = (_visatype.ViChar * name_buffer_size_ctype.value)() # case C060 + error_code = self._library.niDigital_GetPatternName(vi_ctype, pattern_index_ctype, name_buffer_size_ctype, name_ctype) + errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) + return name_ctype.value.decode(self._encoding) + @ivi_synchronized def _get_pin_name(self, pin_index): r'''_get_pin_name @@ -1999,6 +2136,55 @@ def get_time_set_edge_multiplier(self, time_set): errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) return int(edge_multiplier_ctype.value) + @ivi_synchronized + def get_time_set_name(self, time_set_index): + r'''get_time_set_name + + TBD + + Args: + time_set_index (int): + + + Returns: + name (str): + + ''' + vi_ctype = _visatype.ViSession(self._vi) # case S110 + time_set_index_ctype = _visatype.ViInt32(time_set_index) # case S150 + name_buffer_size_ctype = _visatype.ViInt32() # case S170 + name_ctype = None # case C050 + error_code = self._library.niDigital_GetTimeSetName(vi_ctype, time_set_index_ctype, name_buffer_size_ctype, name_ctype) + errors.handle_error(self, error_code, ignore_warnings=True, is_error_handling=False) + name_buffer_size_ctype = _visatype.ViInt32(error_code) # case S180 + name_ctype = (_visatype.ViChar * name_buffer_size_ctype.value)() # case C060 + error_code = self._library.niDigital_GetTimeSetName(vi_ctype, time_set_index_ctype, name_buffer_size_ctype, name_ctype) + errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) + return name_ctype.value.decode(self._encoding) + + @ivi_synchronized + def is_site_enabled(self): + r'''is_site_enabled + + TBD + + Tip: + This method requires repeated capabilities. If called directly on the + nidigital.Session object, then the method will use all repeated capabilities in the session. + You can specify a subset of repeated capabilities using the Python index notation on an + nidigital.Session repeated capabilities container, and calling this method on the result. + + Returns: + enable (bool): + + ''' + vi_ctype = _visatype.ViSession(self._vi) # case S110 + site_ctype = ctypes.create_string_buffer(self._repeated_capability.encode(self._encoding)) # case C010 + enable_ctype = _visatype.ViBoolean() # case S220 + error_code = self._library.niDigital_IsSiteEnabled(vi_ctype, site_ctype, None if enable_ctype is None else (ctypes.pointer(enable_ctype))) + errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) + return bool(enable_ctype.value) + def lock(self): '''lock @@ -2707,66 +2893,6 @@ def write_source_waveform_site_unique(self, waveform_name, waveform_data): self.sites[site_list]._write_source_waveform_site_unique_u32(waveform_name, len(waveform_data), actual_samples_per_waveform, data) - @ivi_synchronized - def _fetch_history_ram_cycle_information(self, site, sample_index): - r'''_fetch_history_ram_cycle_information - - TBD - - Args: - site (str): - - sample_index (int): - - - Returns: - pattern_index (int): - - time_set_index (int): - - vector_number (int): - - cycle_number (int): - - num_dut_cycles (int): - - ''' - vi_ctype = _visatype.ViSession(self._vi) # case S110 - site_ctype = ctypes.create_string_buffer(site.encode(self._encoding)) # case C020 - sample_index_ctype = _visatype.ViInt64(sample_index) # case S150 - pattern_index_ctype = _visatype.ViInt32() # case S220 - time_set_index_ctype = _visatype.ViInt32() # case S220 - vector_number_ctype = _visatype.ViInt64() # case S220 - cycle_number_ctype = _visatype.ViInt64() # case S220 - num_dut_cycles_ctype = _visatype.ViInt32() # case S220 - error_code = self._library.niDigital_FetchHistoryRAMCycleInformation(vi_ctype, site_ctype, sample_index_ctype, None if pattern_index_ctype is None else (ctypes.pointer(pattern_index_ctype)), None if time_set_index_ctype is None else (ctypes.pointer(time_set_index_ctype)), None if vector_number_ctype is None else (ctypes.pointer(vector_number_ctype)), None if cycle_number_ctype is None else (ctypes.pointer(cycle_number_ctype)), None if num_dut_cycles_ctype is None else (ctypes.pointer(num_dut_cycles_ctype))) - errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) - return int(pattern_index_ctype.value), int(time_set_index_ctype.value), int(vector_number_ctype.value), int(cycle_number_ctype.value), int(num_dut_cycles_ctype.value) - - @ivi_synchronized - def _fetch_history_ram_scan_cycle_number(self, site, sample_index): - r'''_fetch_history_ram_scan_cycle_number - - TBD - - Args: - site (str): - - sample_index (int): - - - Returns: - scan_cycle_number (int): - - ''' - vi_ctype = _visatype.ViSession(self._vi) # case S110 - site_ctype = ctypes.create_string_buffer(site.encode(self._encoding)) # case C020 - sample_index_ctype = _visatype.ViInt64(sample_index) # case S150 - scan_cycle_number_ctype = _visatype.ViInt64() # case S220 - error_code = self._library.niDigital_FetchHistoryRAMScanCycleNumber(vi_ctype, site_ctype, sample_index_ctype, None if scan_cycle_number_ctype is None else (ctypes.pointer(scan_cycle_number_ctype))) - errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) - return int(scan_cycle_number_ctype.value) - @ivi_synchronized def get_channel_name_from_string(self, index): r'''get_channel_name_from_string @@ -2793,53 +2919,6 @@ def get_channel_name_from_string(self, index): errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) return name_ctype.value.decode(self._encoding) - @ivi_synchronized - def get_history_ram_sample_count(self, site): - r'''get_history_ram_sample_count - - TBD - - Args: - site (str or int): - - - Returns: - sample_count (int): - - ''' - vi_ctype = _visatype.ViSession(self._vi) # case S110 - site_ctype = ctypes.create_string_buffer(site.encode(self._encoding)) # case C020 - sample_count_ctype = _visatype.ViInt64() # case S220 - error_code = self._library.niDigital_GetHistoryRAMSampleCount(vi_ctype, site_ctype, None if sample_count_ctype is None else (ctypes.pointer(sample_count_ctype))) - errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) - return int(sample_count_ctype.value) - - @ivi_synchronized - def get_pattern_name(self, pattern_index): - r'''get_pattern_name - - TBD - - Args: - pattern_index (int): - - - Returns: - name (str): - - ''' - vi_ctype = _visatype.ViSession(self._vi) # case S110 - pattern_index_ctype = _visatype.ViInt32(pattern_index) # case S150 - name_buffer_size_ctype = _visatype.ViInt32() # case S170 - name_ctype = None # case C050 - error_code = self._library.niDigital_GetPatternName(vi_ctype, pattern_index_ctype, name_buffer_size_ctype, name_ctype) - errors.handle_error(self, error_code, ignore_warnings=True, is_error_handling=False) - name_buffer_size_ctype = _visatype.ViInt32(error_code) # case S180 - name_ctype = (_visatype.ViChar * name_buffer_size_ctype.value)() # case C060 - error_code = self._library.niDigital_GetPatternName(vi_ctype, pattern_index_ctype, name_buffer_size_ctype, name_ctype) - errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) - return name_ctype.value.decode(self._encoding) - @ivi_synchronized def get_pattern_pin_names(self, start_label): r'''get_pattern_pin_names @@ -2866,32 +2945,6 @@ def get_pattern_pin_names(self, start_label): errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) return _converters.convert_comma_separated_string_to_list(pin_list_ctype.value.decode(self._encoding)) - @ivi_synchronized - def get_time_set_name(self, time_set_index): - r'''get_time_set_name - - TBD - - Args: - time_set_index (int): - - - Returns: - name (str): - - ''' - vi_ctype = _visatype.ViSession(self._vi) # case S110 - time_set_index_ctype = _visatype.ViInt32(time_set_index) # case S150 - name_buffer_size_ctype = _visatype.ViInt32() # case S170 - name_ctype = None # case C050 - error_code = self._library.niDigital_GetTimeSetName(vi_ctype, time_set_index_ctype, name_buffer_size_ctype, name_ctype) - errors.handle_error(self, error_code, ignore_warnings=True, is_error_handling=False) - name_buffer_size_ctype = _visatype.ViInt32(error_code) # case S180 - name_ctype = (_visatype.ViChar * name_buffer_size_ctype.value)() # case C060 - error_code = self._library.niDigital_GetTimeSetName(vi_ctype, time_set_index_ctype, name_buffer_size_ctype, name_ctype) - errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) - return name_ctype.value.decode(self._encoding) - @ivi_synchronized def get_time_set_period(self, time_set): r'''get_time_set_period @@ -2968,27 +3021,6 @@ def is_done(self): errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) return bool(done_ctype.value) - @ivi_synchronized - def is_site_enabled(self, site): - r'''is_site_enabled - - TBD - - Args: - site (str or int): - - - Returns: - enable (bool): - - ''' - vi_ctype = _visatype.ViSession(self._vi) # case S110 - site_ctype = ctypes.create_string_buffer(site.encode(self._encoding)) # case C020 - enable_ctype = _visatype.ViBoolean() # case S220 - error_code = self._library.niDigital_IsSiteEnabled(vi_ctype, site_ctype, None if enable_ctype is None else (ctypes.pointer(enable_ctype))) - errors.handle_error(self, error_code, ignore_warnings=False, is_error_handling=False) - return bool(enable_ctype.value) - @ivi_synchronized def load_levels(self, levels_file_path): r'''load_levels diff --git a/generated/nidigital/nidigital/unit_tests/test_nidigital.py b/generated/nidigital/nidigital/unit_tests/test_nidigital.py index 4c3edf3a3..16c0e7c8d 100644 --- a/generated/nidigital/nidigital/unit_tests/test_nidigital.py +++ b/generated/nidigital/nidigital/unit_tests/test_nidigital.py @@ -43,7 +43,4 @@ def test_fetch_history_ram_cycle_information_position_out_of_bound(self): self.side_effects_helper['GetHistoryRAMSampleCount']['sampleCount'] = 7 with nidigital.Session('') as session: with pytest.raises(ValueError, match='position: Specified value = 8, Maximum value = 6.'): - session.fetch_history_ram_cycle_information( - site='site1', - position=8, - samples_to_read=-1) + session.sites[1].fetch_history_ram_cycle_information(position=8, samples_to_read=-1) diff --git a/generated/nidmm/nidmm/_converters.py b/generated/nidmm/nidmm/_converters.py index 7984fbe00..306373a90 100644 --- a/generated/nidmm/nidmm/_converters.py +++ b/generated/nidmm/nidmm/_converters.py @@ -4,6 +4,7 @@ import nidmm.errors as errors import array +import collections import datetime import numbers @@ -112,7 +113,7 @@ def convert_repeated_capabilities(repeated_capability, prefix=''): prefix (str) - common prefix for all strings Returns: - rep_cal_list (list of str) - list of each repeated capability item with ranges expanded and prefix added + rep_cap_list (list of str) - list of each repeated capability item with ranges expanded and prefix added ''' # We need to explicitly handle None here. Everything else we can pass on to the singledispatch functions if repeated_capability is None: @@ -130,7 +131,7 @@ def convert_repeated_capabilities_from_init(repeated_capability): repeated_capability (str, list, tuple, slice, None) - Returns: - rep_cal (str) - comma delimited string of each repeated capability item with ranges expanded + rep_cap (str) - comma delimited string of each repeated capability item with ranges expanded ''' return ','.join(convert_repeated_capabilities(repeated_capability, '')) @@ -216,10 +217,6 @@ def _convert_to_bytes(value): # noqa: F811 pass -def convert_comma_separated_string_to_list(comma_separated_string): - return [x.strip() for x in comma_separated_string.split(',')] - - @_convert_to_bytes.register(list) # noqa: F811 @_convert_to_bytes.register(bytes) # noqa: F811 @_convert_to_bytes.register(bytearray) # noqa: F811 @@ -237,6 +234,31 @@ def convert_to_bytes(value): # noqa: F811 return bytes(_convert_to_bytes(value)) +def convert_comma_separated_string_to_list(comma_separated_string): + return [x.strip() for x in comma_separated_string.split(',')] + + +def convert_chained_repeated_capability_to_parts(chained_repeated_capability): + '''Convert a chained repeated capabilities string to a list of comma-delimited repeated capabilities string. + + Converter assumes that the input contains the full cartesian product of its parts. + e.g. If chained_repeated_capability is 'site0/PinA,site0/PinB,site1/PinA,site1/PinB', + ['site0,site1', 'PinA,PinB'] is returned. + + Args: + chained_repeated_capability (str) - comma-delimited repeated capabilities string where each + item is a chain of slash-delimited repeated capabilities + + Returns: + rep_cap_list (list of str) - list of comma-delimited repeated capabilities string + ''' + chained_repeated_capability_items = convert_comma_separated_string_to_list(chained_repeated_capability) + repeated_capability_lists = [[] for _ in range(chained_repeated_capability_items[0].count('/') + 1)] + for item in chained_repeated_capability_items: + repeated_capability_lists = [x + [y] for x, y in zip(repeated_capability_lists, item.split('/'))] + return [','.join(collections.OrderedDict.fromkeys(x)) for x in repeated_capability_lists] + + # Let's run some tests def test_convert_init_with_options_dictionary(): assert convert_init_with_options_dictionary('') == '' @@ -461,6 +483,23 @@ def test_repeated_capabilies_from_init(): assert test_result == '0,2,4,5,6,7,8,9,11,12,13,14,16,17' +def test_convert_chained_repeated_capability_to_parts_three_parts(): + chained_rep_cap = ('site0/test/PinA,site0/test/PinB,site0/test/PinC,' + 'site1/test/PinA,site1/test/PinB,site1/test/PinC') + rep_cap_list = convert_chained_repeated_capability_to_parts(chained_rep_cap) + assert rep_cap_list == ['site0,site1', 'test', 'PinA,PinB,PinC'] + + +def test_convert_chained_repeated_capability_to_parts_single_part(): + rep_cap_list = convert_chained_repeated_capability_to_parts('site0, site1') + assert rep_cap_list == ['site0,site1'] + + +def test_convert_chained_repeated_capability_to_parts_empty_string(): + rep_cap_list = convert_chained_repeated_capability_to_parts('') + assert rep_cap_list == [''] + + def test_string_to_list_channel(): test_result = _convert_repeated_capabilities('r0', '') assert test_result == ['r0'] @@ -488,4 +527,3 @@ def test_string_to_list_prefix(): def test_convert_comma_separated_string_to_list(): out_list = convert_comma_separated_string_to_list(' PinA , PinB , PinC ') assert out_list == ['PinA', 'PinB', 'PinC'] - diff --git a/generated/nifake/nifake/_converters.py b/generated/nifake/nifake/_converters.py index f955b07e3..4f295979e 100644 --- a/generated/nifake/nifake/_converters.py +++ b/generated/nifake/nifake/_converters.py @@ -4,6 +4,7 @@ import nifake.errors as errors import array +import collections import datetime import numbers @@ -112,7 +113,7 @@ def convert_repeated_capabilities(repeated_capability, prefix=''): prefix (str) - common prefix for all strings Returns: - rep_cal_list (list of str) - list of each repeated capability item with ranges expanded and prefix added + rep_cap_list (list of str) - list of each repeated capability item with ranges expanded and prefix added ''' # We need to explicitly handle None here. Everything else we can pass on to the singledispatch functions if repeated_capability is None: @@ -130,7 +131,7 @@ def convert_repeated_capabilities_from_init(repeated_capability): repeated_capability (str, list, tuple, slice, None) - Returns: - rep_cal (str) - comma delimited string of each repeated capability item with ranges expanded + rep_cap (str) - comma delimited string of each repeated capability item with ranges expanded ''' return ','.join(convert_repeated_capabilities(repeated_capability, '')) @@ -210,21 +211,12 @@ def convert_init_with_options_dictionary(values): return init_with_options_string -# nifake specific converter(s) - used only for testing -def convert_double_each_element(numbers): - return [x * 2 for x in numbers] - - # convert value to bytes @singledispatch def _convert_to_bytes(value): # noqa: F811 pass -def convert_comma_separated_string_to_list(comma_separated_string): - return [x.strip() for x in comma_separated_string.split(',')] - - @_convert_to_bytes.register(list) # noqa: F811 @_convert_to_bytes.register(bytes) # noqa: F811 @_convert_to_bytes.register(bytearray) # noqa: F811 @@ -242,6 +234,36 @@ def convert_to_bytes(value): # noqa: F811 return bytes(_convert_to_bytes(value)) +def convert_comma_separated_string_to_list(comma_separated_string): + return [x.strip() for x in comma_separated_string.split(',')] + + +def convert_chained_repeated_capability_to_parts(chained_repeated_capability): + '''Convert a chained repeated capabilities string to a list of comma-delimited repeated capabilities string. + + Converter assumes that the input contains the full cartesian product of its parts. + e.g. If chained_repeated_capability is 'site0/PinA,site0/PinB,site1/PinA,site1/PinB', + ['site0,site1', 'PinA,PinB'] is returned. + + Args: + chained_repeated_capability (str) - comma-delimited repeated capabilities string where each + item is a chain of slash-delimited repeated capabilities + + Returns: + rep_cap_list (list of str) - list of comma-delimited repeated capabilities string + ''' + chained_repeated_capability_items = convert_comma_separated_string_to_list(chained_repeated_capability) + repeated_capability_lists = [[] for _ in range(chained_repeated_capability_items[0].count('/') + 1)] + for item in chained_repeated_capability_items: + repeated_capability_lists = [x + [y] for x, y in zip(repeated_capability_lists, item.split('/'))] + return [','.join(collections.OrderedDict.fromkeys(x)) for x in repeated_capability_lists] + + +# nifake specific converter(s) - used only for testing +def convert_double_each_element(numbers): + return [x * 2 for x in numbers] + + # Let's run some tests def test_convert_init_with_options_dictionary(): assert convert_init_with_options_dictionary('') == '' @@ -466,6 +488,23 @@ def test_repeated_capabilies_from_init(): assert test_result == '0,2,4,5,6,7,8,9,11,12,13,14,16,17' +def test_convert_chained_repeated_capability_to_parts_three_parts(): + chained_rep_cap = ('site0/test/PinA,site0/test/PinB,site0/test/PinC,' + 'site1/test/PinA,site1/test/PinB,site1/test/PinC') + rep_cap_list = convert_chained_repeated_capability_to_parts(chained_rep_cap) + assert rep_cap_list == ['site0,site1', 'test', 'PinA,PinB,PinC'] + + +def test_convert_chained_repeated_capability_to_parts_single_part(): + rep_cap_list = convert_chained_repeated_capability_to_parts('site0, site1') + assert rep_cap_list == ['site0,site1'] + + +def test_convert_chained_repeated_capability_to_parts_empty_string(): + rep_cap_list = convert_chained_repeated_capability_to_parts('') + assert rep_cap_list == [''] + + def test_string_to_list_channel(): test_result = _convert_repeated_capabilities('r0', '') assert test_result == ['r0'] @@ -493,4 +532,3 @@ def test_string_to_list_prefix(): def test_convert_comma_separated_string_to_list(): out_list = convert_comma_separated_string_to_list(' PinA , PinB , PinC ') assert out_list == ['PinA', 'PinB', 'PinC'] - diff --git a/generated/nifgen/nifgen/_converters.py b/generated/nifgen/nifgen/_converters.py index 8d7582923..0cc19bdd2 100644 --- a/generated/nifgen/nifgen/_converters.py +++ b/generated/nifgen/nifgen/_converters.py @@ -4,6 +4,7 @@ import nifgen.errors as errors import array +import collections import datetime import numbers @@ -112,7 +113,7 @@ def convert_repeated_capabilities(repeated_capability, prefix=''): prefix (str) - common prefix for all strings Returns: - rep_cal_list (list of str) - list of each repeated capability item with ranges expanded and prefix added + rep_cap_list (list of str) - list of each repeated capability item with ranges expanded and prefix added ''' # We need to explicitly handle None here. Everything else we can pass on to the singledispatch functions if repeated_capability is None: @@ -130,7 +131,7 @@ def convert_repeated_capabilities_from_init(repeated_capability): repeated_capability (str, list, tuple, slice, None) - Returns: - rep_cal (str) - comma delimited string of each repeated capability item with ranges expanded + rep_cap (str) - comma delimited string of each repeated capability item with ranges expanded ''' return ','.join(convert_repeated_capabilities(repeated_capability, '')) @@ -216,10 +217,6 @@ def _convert_to_bytes(value): # noqa: F811 pass -def convert_comma_separated_string_to_list(comma_separated_string): - return [x.strip() for x in comma_separated_string.split(',')] - - @_convert_to_bytes.register(list) # noqa: F811 @_convert_to_bytes.register(bytes) # noqa: F811 @_convert_to_bytes.register(bytearray) # noqa: F811 @@ -237,6 +234,31 @@ def convert_to_bytes(value): # noqa: F811 return bytes(_convert_to_bytes(value)) +def convert_comma_separated_string_to_list(comma_separated_string): + return [x.strip() for x in comma_separated_string.split(',')] + + +def convert_chained_repeated_capability_to_parts(chained_repeated_capability): + '''Convert a chained repeated capabilities string to a list of comma-delimited repeated capabilities string. + + Converter assumes that the input contains the full cartesian product of its parts. + e.g. If chained_repeated_capability is 'site0/PinA,site0/PinB,site1/PinA,site1/PinB', + ['site0,site1', 'PinA,PinB'] is returned. + + Args: + chained_repeated_capability (str) - comma-delimited repeated capabilities string where each + item is a chain of slash-delimited repeated capabilities + + Returns: + rep_cap_list (list of str) - list of comma-delimited repeated capabilities string + ''' + chained_repeated_capability_items = convert_comma_separated_string_to_list(chained_repeated_capability) + repeated_capability_lists = [[] for _ in range(chained_repeated_capability_items[0].count('/') + 1)] + for item in chained_repeated_capability_items: + repeated_capability_lists = [x + [y] for x, y in zip(repeated_capability_lists, item.split('/'))] + return [','.join(collections.OrderedDict.fromkeys(x)) for x in repeated_capability_lists] + + # Let's run some tests def test_convert_init_with_options_dictionary(): assert convert_init_with_options_dictionary('') == '' @@ -461,6 +483,23 @@ def test_repeated_capabilies_from_init(): assert test_result == '0,2,4,5,6,7,8,9,11,12,13,14,16,17' +def test_convert_chained_repeated_capability_to_parts_three_parts(): + chained_rep_cap = ('site0/test/PinA,site0/test/PinB,site0/test/PinC,' + 'site1/test/PinA,site1/test/PinB,site1/test/PinC') + rep_cap_list = convert_chained_repeated_capability_to_parts(chained_rep_cap) + assert rep_cap_list == ['site0,site1', 'test', 'PinA,PinB,PinC'] + + +def test_convert_chained_repeated_capability_to_parts_single_part(): + rep_cap_list = convert_chained_repeated_capability_to_parts('site0, site1') + assert rep_cap_list == ['site0,site1'] + + +def test_convert_chained_repeated_capability_to_parts_empty_string(): + rep_cap_list = convert_chained_repeated_capability_to_parts('') + assert rep_cap_list == [''] + + def test_string_to_list_channel(): test_result = _convert_repeated_capabilities('r0', '') assert test_result == ['r0'] @@ -488,4 +527,3 @@ def test_string_to_list_prefix(): def test_convert_comma_separated_string_to_list(): out_list = convert_comma_separated_string_to_list(' PinA , PinB , PinC ') assert out_list == ['PinA', 'PinB', 'PinC'] - diff --git a/generated/nimodinst/nimodinst/_converters.py b/generated/nimodinst/nimodinst/_converters.py index 5c84c1254..65f5030bf 100644 --- a/generated/nimodinst/nimodinst/_converters.py +++ b/generated/nimodinst/nimodinst/_converters.py @@ -4,6 +4,7 @@ import nimodinst.errors as errors import array +import collections import datetime import numbers @@ -112,7 +113,7 @@ def convert_repeated_capabilities(repeated_capability, prefix=''): prefix (str) - common prefix for all strings Returns: - rep_cal_list (list of str) - list of each repeated capability item with ranges expanded and prefix added + rep_cap_list (list of str) - list of each repeated capability item with ranges expanded and prefix added ''' # We need to explicitly handle None here. Everything else we can pass on to the singledispatch functions if repeated_capability is None: @@ -130,7 +131,7 @@ def convert_repeated_capabilities_from_init(repeated_capability): repeated_capability (str, list, tuple, slice, None) - Returns: - rep_cal (str) - comma delimited string of each repeated capability item with ranges expanded + rep_cap (str) - comma delimited string of each repeated capability item with ranges expanded ''' return ','.join(convert_repeated_capabilities(repeated_capability, '')) @@ -216,10 +217,6 @@ def _convert_to_bytes(value): # noqa: F811 pass -def convert_comma_separated_string_to_list(comma_separated_string): - return [x.strip() for x in comma_separated_string.split(',')] - - @_convert_to_bytes.register(list) # noqa: F811 @_convert_to_bytes.register(bytes) # noqa: F811 @_convert_to_bytes.register(bytearray) # noqa: F811 @@ -237,6 +234,31 @@ def convert_to_bytes(value): # noqa: F811 return bytes(_convert_to_bytes(value)) +def convert_comma_separated_string_to_list(comma_separated_string): + return [x.strip() for x in comma_separated_string.split(',')] + + +def convert_chained_repeated_capability_to_parts(chained_repeated_capability): + '''Convert a chained repeated capabilities string to a list of comma-delimited repeated capabilities string. + + Converter assumes that the input contains the full cartesian product of its parts. + e.g. If chained_repeated_capability is 'site0/PinA,site0/PinB,site1/PinA,site1/PinB', + ['site0,site1', 'PinA,PinB'] is returned. + + Args: + chained_repeated_capability (str) - comma-delimited repeated capabilities string where each + item is a chain of slash-delimited repeated capabilities + + Returns: + rep_cap_list (list of str) - list of comma-delimited repeated capabilities string + ''' + chained_repeated_capability_items = convert_comma_separated_string_to_list(chained_repeated_capability) + repeated_capability_lists = [[] for _ in range(chained_repeated_capability_items[0].count('/') + 1)] + for item in chained_repeated_capability_items: + repeated_capability_lists = [x + [y] for x, y in zip(repeated_capability_lists, item.split('/'))] + return [','.join(collections.OrderedDict.fromkeys(x)) for x in repeated_capability_lists] + + # Let's run some tests def test_convert_init_with_options_dictionary(): assert convert_init_with_options_dictionary('') == '' @@ -326,4 +348,3 @@ def test_string_to_list_prefix(): def test_convert_comma_separated_string_to_list(): out_list = convert_comma_separated_string_to_list(' PinA , PinB , PinC ') assert out_list == ['PinA', 'PinB', 'PinC'] - diff --git a/generated/niscope/niscope/_converters.py b/generated/niscope/niscope/_converters.py index 9dd05df30..56922e784 100644 --- a/generated/niscope/niscope/_converters.py +++ b/generated/niscope/niscope/_converters.py @@ -4,6 +4,7 @@ import niscope.errors as errors import array +import collections import datetime import numbers @@ -112,7 +113,7 @@ def convert_repeated_capabilities(repeated_capability, prefix=''): prefix (str) - common prefix for all strings Returns: - rep_cal_list (list of str) - list of each repeated capability item with ranges expanded and prefix added + rep_cap_list (list of str) - list of each repeated capability item with ranges expanded and prefix added ''' # We need to explicitly handle None here. Everything else we can pass on to the singledispatch functions if repeated_capability is None: @@ -130,7 +131,7 @@ def convert_repeated_capabilities_from_init(repeated_capability): repeated_capability (str, list, tuple, slice, None) - Returns: - rep_cal (str) - comma delimited string of each repeated capability item with ranges expanded + rep_cap (str) - comma delimited string of each repeated capability item with ranges expanded ''' return ','.join(convert_repeated_capabilities(repeated_capability, '')) @@ -216,10 +217,6 @@ def _convert_to_bytes(value): # noqa: F811 pass -def convert_comma_separated_string_to_list(comma_separated_string): - return [x.strip() for x in comma_separated_string.split(',')] - - @_convert_to_bytes.register(list) # noqa: F811 @_convert_to_bytes.register(bytes) # noqa: F811 @_convert_to_bytes.register(bytearray) # noqa: F811 @@ -237,6 +234,31 @@ def convert_to_bytes(value): # noqa: F811 return bytes(_convert_to_bytes(value)) +def convert_comma_separated_string_to_list(comma_separated_string): + return [x.strip() for x in comma_separated_string.split(',')] + + +def convert_chained_repeated_capability_to_parts(chained_repeated_capability): + '''Convert a chained repeated capabilities string to a list of comma-delimited repeated capabilities string. + + Converter assumes that the input contains the full cartesian product of its parts. + e.g. If chained_repeated_capability is 'site0/PinA,site0/PinB,site1/PinA,site1/PinB', + ['site0,site1', 'PinA,PinB'] is returned. + + Args: + chained_repeated_capability (str) - comma-delimited repeated capabilities string where each + item is a chain of slash-delimited repeated capabilities + + Returns: + rep_cap_list (list of str) - list of comma-delimited repeated capabilities string + ''' + chained_repeated_capability_items = convert_comma_separated_string_to_list(chained_repeated_capability) + repeated_capability_lists = [[] for _ in range(chained_repeated_capability_items[0].count('/') + 1)] + for item in chained_repeated_capability_items: + repeated_capability_lists = [x + [y] for x, y in zip(repeated_capability_lists, item.split('/'))] + return [','.join(collections.OrderedDict.fromkeys(x)) for x in repeated_capability_lists] + + # Let's run some tests def test_convert_init_with_options_dictionary(): assert convert_init_with_options_dictionary('') == '' @@ -461,6 +483,23 @@ def test_repeated_capabilies_from_init(): assert test_result == '0,2,4,5,6,7,8,9,11,12,13,14,16,17' +def test_convert_chained_repeated_capability_to_parts_three_parts(): + chained_rep_cap = ('site0/test/PinA,site0/test/PinB,site0/test/PinC,' + 'site1/test/PinA,site1/test/PinB,site1/test/PinC') + rep_cap_list = convert_chained_repeated_capability_to_parts(chained_rep_cap) + assert rep_cap_list == ['site0,site1', 'test', 'PinA,PinB,PinC'] + + +def test_convert_chained_repeated_capability_to_parts_single_part(): + rep_cap_list = convert_chained_repeated_capability_to_parts('site0, site1') + assert rep_cap_list == ['site0,site1'] + + +def test_convert_chained_repeated_capability_to_parts_empty_string(): + rep_cap_list = convert_chained_repeated_capability_to_parts('') + assert rep_cap_list == [''] + + def test_string_to_list_channel(): test_result = _convert_repeated_capabilities('r0', '') assert test_result == ['r0'] @@ -488,4 +527,3 @@ def test_string_to_list_prefix(): def test_convert_comma_separated_string_to_list(): out_list = convert_comma_separated_string_to_list(' PinA , PinB , PinC ') assert out_list == ['PinA', 'PinB', 'PinC'] - diff --git a/generated/nise/nise/_converters.py b/generated/nise/nise/_converters.py index 6beada483..5bb989780 100644 --- a/generated/nise/nise/_converters.py +++ b/generated/nise/nise/_converters.py @@ -4,6 +4,7 @@ import nise.errors as errors import array +import collections import datetime import numbers @@ -112,7 +113,7 @@ def convert_repeated_capabilities(repeated_capability, prefix=''): prefix (str) - common prefix for all strings Returns: - rep_cal_list (list of str) - list of each repeated capability item with ranges expanded and prefix added + rep_cap_list (list of str) - list of each repeated capability item with ranges expanded and prefix added ''' # We need to explicitly handle None here. Everything else we can pass on to the singledispatch functions if repeated_capability is None: @@ -130,7 +131,7 @@ def convert_repeated_capabilities_from_init(repeated_capability): repeated_capability (str, list, tuple, slice, None) - Returns: - rep_cal (str) - comma delimited string of each repeated capability item with ranges expanded + rep_cap (str) - comma delimited string of each repeated capability item with ranges expanded ''' return ','.join(convert_repeated_capabilities(repeated_capability, '')) @@ -216,10 +217,6 @@ def _convert_to_bytes(value): # noqa: F811 pass -def convert_comma_separated_string_to_list(comma_separated_string): - return [x.strip() for x in comma_separated_string.split(',')] - - @_convert_to_bytes.register(list) # noqa: F811 @_convert_to_bytes.register(bytes) # noqa: F811 @_convert_to_bytes.register(bytearray) # noqa: F811 @@ -237,6 +234,31 @@ def convert_to_bytes(value): # noqa: F811 return bytes(_convert_to_bytes(value)) +def convert_comma_separated_string_to_list(comma_separated_string): + return [x.strip() for x in comma_separated_string.split(',')] + + +def convert_chained_repeated_capability_to_parts(chained_repeated_capability): + '''Convert a chained repeated capabilities string to a list of comma-delimited repeated capabilities string. + + Converter assumes that the input contains the full cartesian product of its parts. + e.g. If chained_repeated_capability is 'site0/PinA,site0/PinB,site1/PinA,site1/PinB', + ['site0,site1', 'PinA,PinB'] is returned. + + Args: + chained_repeated_capability (str) - comma-delimited repeated capabilities string where each + item is a chain of slash-delimited repeated capabilities + + Returns: + rep_cap_list (list of str) - list of comma-delimited repeated capabilities string + ''' + chained_repeated_capability_items = convert_comma_separated_string_to_list(chained_repeated_capability) + repeated_capability_lists = [[] for _ in range(chained_repeated_capability_items[0].count('/') + 1)] + for item in chained_repeated_capability_items: + repeated_capability_lists = [x + [y] for x, y in zip(repeated_capability_lists, item.split('/'))] + return [','.join(collections.OrderedDict.fromkeys(x)) for x in repeated_capability_lists] + + # Let's run some tests def test_convert_init_with_options_dictionary(): assert convert_init_with_options_dictionary('') == '' @@ -461,6 +483,23 @@ def test_repeated_capabilies_from_init(): assert test_result == '0,2,4,5,6,7,8,9,11,12,13,14,16,17' +def test_convert_chained_repeated_capability_to_parts_three_parts(): + chained_rep_cap = ('site0/test/PinA,site0/test/PinB,site0/test/PinC,' + 'site1/test/PinA,site1/test/PinB,site1/test/PinC') + rep_cap_list = convert_chained_repeated_capability_to_parts(chained_rep_cap) + assert rep_cap_list == ['site0,site1', 'test', 'PinA,PinB,PinC'] + + +def test_convert_chained_repeated_capability_to_parts_single_part(): + rep_cap_list = convert_chained_repeated_capability_to_parts('site0, site1') + assert rep_cap_list == ['site0,site1'] + + +def test_convert_chained_repeated_capability_to_parts_empty_string(): + rep_cap_list = convert_chained_repeated_capability_to_parts('') + assert rep_cap_list == [''] + + def test_string_to_list_channel(): test_result = _convert_repeated_capabilities('r0', '') assert test_result == ['r0'] @@ -488,4 +527,3 @@ def test_string_to_list_prefix(): def test_convert_comma_separated_string_to_list(): out_list = convert_comma_separated_string_to_list(' PinA , PinB , PinC ') assert out_list == ['PinA', 'PinB', 'PinC'] - diff --git a/generated/niswitch/niswitch/_converters.py b/generated/niswitch/niswitch/_converters.py index 5614fa519..774d4dfe5 100644 --- a/generated/niswitch/niswitch/_converters.py +++ b/generated/niswitch/niswitch/_converters.py @@ -4,6 +4,7 @@ import niswitch.errors as errors import array +import collections import datetime import numbers @@ -112,7 +113,7 @@ def convert_repeated_capabilities(repeated_capability, prefix=''): prefix (str) - common prefix for all strings Returns: - rep_cal_list (list of str) - list of each repeated capability item with ranges expanded and prefix added + rep_cap_list (list of str) - list of each repeated capability item with ranges expanded and prefix added ''' # We need to explicitly handle None here. Everything else we can pass on to the singledispatch functions if repeated_capability is None: @@ -130,7 +131,7 @@ def convert_repeated_capabilities_from_init(repeated_capability): repeated_capability (str, list, tuple, slice, None) - Returns: - rep_cal (str) - comma delimited string of each repeated capability item with ranges expanded + rep_cap (str) - comma delimited string of each repeated capability item with ranges expanded ''' return ','.join(convert_repeated_capabilities(repeated_capability, '')) @@ -216,10 +217,6 @@ def _convert_to_bytes(value): # noqa: F811 pass -def convert_comma_separated_string_to_list(comma_separated_string): - return [x.strip() for x in comma_separated_string.split(',')] - - @_convert_to_bytes.register(list) # noqa: F811 @_convert_to_bytes.register(bytes) # noqa: F811 @_convert_to_bytes.register(bytearray) # noqa: F811 @@ -237,6 +234,31 @@ def convert_to_bytes(value): # noqa: F811 return bytes(_convert_to_bytes(value)) +def convert_comma_separated_string_to_list(comma_separated_string): + return [x.strip() for x in comma_separated_string.split(',')] + + +def convert_chained_repeated_capability_to_parts(chained_repeated_capability): + '''Convert a chained repeated capabilities string to a list of comma-delimited repeated capabilities string. + + Converter assumes that the input contains the full cartesian product of its parts. + e.g. If chained_repeated_capability is 'site0/PinA,site0/PinB,site1/PinA,site1/PinB', + ['site0,site1', 'PinA,PinB'] is returned. + + Args: + chained_repeated_capability (str) - comma-delimited repeated capabilities string where each + item is a chain of slash-delimited repeated capabilities + + Returns: + rep_cap_list (list of str) - list of comma-delimited repeated capabilities string + ''' + chained_repeated_capability_items = convert_comma_separated_string_to_list(chained_repeated_capability) + repeated_capability_lists = [[] for _ in range(chained_repeated_capability_items[0].count('/') + 1)] + for item in chained_repeated_capability_items: + repeated_capability_lists = [x + [y] for x, y in zip(repeated_capability_lists, item.split('/'))] + return [','.join(collections.OrderedDict.fromkeys(x)) for x in repeated_capability_lists] + + # Let's run some tests def test_convert_init_with_options_dictionary(): assert convert_init_with_options_dictionary('') == '' @@ -461,6 +483,23 @@ def test_repeated_capabilies_from_init(): assert test_result == '0,2,4,5,6,7,8,9,11,12,13,14,16,17' +def test_convert_chained_repeated_capability_to_parts_three_parts(): + chained_rep_cap = ('site0/test/PinA,site0/test/PinB,site0/test/PinC,' + 'site1/test/PinA,site1/test/PinB,site1/test/PinC') + rep_cap_list = convert_chained_repeated_capability_to_parts(chained_rep_cap) + assert rep_cap_list == ['site0,site1', 'test', 'PinA,PinB,PinC'] + + +def test_convert_chained_repeated_capability_to_parts_single_part(): + rep_cap_list = convert_chained_repeated_capability_to_parts('site0, site1') + assert rep_cap_list == ['site0,site1'] + + +def test_convert_chained_repeated_capability_to_parts_empty_string(): + rep_cap_list = convert_chained_repeated_capability_to_parts('') + assert rep_cap_list == [''] + + def test_string_to_list_channel(): test_result = _convert_repeated_capabilities('r0', '') assert test_result == ['r0'] @@ -488,4 +527,3 @@ def test_string_to_list_prefix(): def test_convert_comma_separated_string_to_list(): out_list = convert_comma_separated_string_to_list(' PinA , PinB , PinC ') assert out_list == ['PinA', 'PinB', 'PinC'] - diff --git a/generated/nitclk/nitclk/_converters.py b/generated/nitclk/nitclk/_converters.py index a9a3af8d5..2e0ac1d5a 100644 --- a/generated/nitclk/nitclk/_converters.py +++ b/generated/nitclk/nitclk/_converters.py @@ -4,6 +4,7 @@ import nitclk.errors as errors import array +import collections import datetime import numbers @@ -112,7 +113,7 @@ def convert_repeated_capabilities(repeated_capability, prefix=''): prefix (str) - common prefix for all strings Returns: - rep_cal_list (list of str) - list of each repeated capability item with ranges expanded and prefix added + rep_cap_list (list of str) - list of each repeated capability item with ranges expanded and prefix added ''' # We need to explicitly handle None here. Everything else we can pass on to the singledispatch functions if repeated_capability is None: @@ -130,7 +131,7 @@ def convert_repeated_capabilities_from_init(repeated_capability): repeated_capability (str, list, tuple, slice, None) - Returns: - rep_cal (str) - comma delimited string of each repeated capability item with ranges expanded + rep_cap (str) - comma delimited string of each repeated capability item with ranges expanded ''' return ','.join(convert_repeated_capabilities(repeated_capability, '')) @@ -210,6 +211,54 @@ def convert_init_with_options_dictionary(values): return init_with_options_string +# convert value to bytes +@singledispatch +def _convert_to_bytes(value): # noqa: F811 + pass + + +@_convert_to_bytes.register(list) # noqa: F811 +@_convert_to_bytes.register(bytes) # noqa: F811 +@_convert_to_bytes.register(bytearray) # noqa: F811 +@_convert_to_bytes.register(array.array) # noqa: F811 +def _(value): + return value + + +@_convert_to_bytes.register(str) # noqa: F811 +def _(value): + return value.encode() + + +def convert_to_bytes(value): # noqa: F811 + return bytes(_convert_to_bytes(value)) + + +def convert_comma_separated_string_to_list(comma_separated_string): + return [x.strip() for x in comma_separated_string.split(',')] + + +def convert_chained_repeated_capability_to_parts(chained_repeated_capability): + '''Convert a chained repeated capabilities string to a list of comma-delimited repeated capabilities string. + + Converter assumes that the input contains the full cartesian product of its parts. + e.g. If chained_repeated_capability is 'site0/PinA,site0/PinB,site1/PinA,site1/PinB', + ['site0,site1', 'PinA,PinB'] is returned. + + Args: + chained_repeated_capability (str) - comma-delimited repeated capabilities string where each + item is a chain of slash-delimited repeated capabilities + + Returns: + rep_cap_list (list of str) - list of comma-delimited repeated capabilities string + ''' + chained_repeated_capability_items = convert_comma_separated_string_to_list(chained_repeated_capability) + repeated_capability_lists = [[] for _ in range(chained_repeated_capability_items[0].count('/') + 1)] + for item in chained_repeated_capability_items: + repeated_capability_lists = [x + [y] for x, y in zip(repeated_capability_lists, item.split('/'))] + return [','.join(collections.OrderedDict.fromkeys(x)) for x in repeated_capability_lists] + + # nitclk specific converters def convert_to_nitclk_session_number(item): '''Convert from supported objects to NI-TClk Session Num @@ -236,33 +285,6 @@ def convert_to_nitclk_session_number_list(item_list): return [convert_to_nitclk_session_number(i) for i in item_list] -# convert value to bytes -@singledispatch -def _convert_to_bytes(value): # noqa: F811 - pass - - -def convert_comma_separated_string_to_list(comma_separated_string): - return [x.strip() for x in comma_separated_string.split(',')] - - -@_convert_to_bytes.register(list) # noqa: F811 -@_convert_to_bytes.register(bytes) # noqa: F811 -@_convert_to_bytes.register(bytearray) # noqa: F811 -@_convert_to_bytes.register(array.array) # noqa: F811 -def _(value): - return value - - -@_convert_to_bytes.register(str) # noqa: F811 -def _(value): - return value.encode() - - -def convert_to_bytes(value): # noqa: F811 - return bytes(_convert_to_bytes(value)) - - # Let's run some tests def test_convert_init_with_options_dictionary(): assert convert_init_with_options_dictionary('') == '' @@ -352,4 +374,3 @@ def test_string_to_list_prefix(): def test_convert_comma_separated_string_to_list(): out_list = convert_comma_separated_string_to_list(' PinA , PinB , PinC ') assert out_list == ['PinA', 'PinB', 'PinC'] - diff --git a/src/nidigital/metadata/functions.py b/src/nidigital/metadata/functions.py index a93c9a7fd..308dbf8f0 100644 --- a/src/nidigital/metadata/functions.py +++ b/src/nidigital/metadata/functions.py @@ -1025,6 +1025,8 @@ }, { 'direction': 'in', + 'is_repeated_capability': True, + 'repeated_capability_type': 'sites', 'name': 'site', 'type': 'ViConstString' }, @@ -1074,13 +1076,13 @@ }, { 'direction': 'in', + 'is_repeated_capability': True, + 'repeated_capability_type': 'sites', 'name': 'site', 'type': 'ViConstString' }, { 'direction': 'in', - 'is_repeated_capability': True, - 'repeated_capability_type': 'pins', 'name': 'pinList', 'type': 'ViConstString' }, @@ -1152,6 +1154,8 @@ }, { 'direction': 'in', + 'is_repeated_capability': True, + 'repeated_capability_type': 'sites', 'name': 'site', 'type': 'ViConstString' }, @@ -1511,8 +1515,8 @@ }, { 'direction': 'in', - 'python_api_converter_name': 'convert_site_to_string', - 'type_in_documentation': 'str or int', + 'is_repeated_capability': True, + 'repeated_capability_type': 'sites', 'name': 'site', 'type': 'ViConstString' }, @@ -1554,6 +1558,7 @@ 'type': 'ViChar[]' } ], + 'render_in_session_base': True, # Called from FancyFetchHistoryRAMCycleInformation() which uses rep cap 'returns': 'ViStatus' }, 'GetPatternPinList': { @@ -1898,6 +1903,7 @@ 'type': 'ViChar[]' } ], + 'render_in_session_base': True, # Called from FancyFetchHistoryRAMCycleInformation() which uses rep cap 'returns': 'ViStatus' }, 'GetTimeSetPeriod': { @@ -2009,8 +2015,8 @@ }, { 'direction': 'in', - 'python_api_converter_name': 'convert_site_to_string', - 'type_in_documentation': 'str or int', + 'is_repeated_capability': True, + 'repeated_capability_type': 'sites', 'name': 'site', 'type': 'ViConstString' }, diff --git a/src/nidigital/metadata/functions_addon.py b/src/nidigital/metadata/functions_addon.py index 0b7bf4f69..cf3a69fbb 100644 --- a/src/nidigital/metadata/functions_addon.py +++ b/src/nidigital/metadata/functions_addon.py @@ -283,9 +283,16 @@ consist of multiple DUT cycles. When using pins with mixed edge multipliers, pins may return NIDIGITAL_VAL_PIN_STATE_NOT_ACQUIRED for DUT cycles where those pins do not have edges defined. +Site number on which to retrieve pattern information must be specified via sites repeated capability. +The method returns an error if more than one site is specified. + +Pins for which to retrieve pattern information must be specified via pins repeated capability. If pins are not specified, pin list from the pattern containing the start label is used. Call -niDigital_GetPatternPinList with the start label to retrieve the pins -associated with the pattern burst. +niDigital_GetPatternPinList with the start label to retrieve the pins associated with the pattern burst: + +.. code:: python + + session.sites[0].pins['PinA', 'PinB'].fetch_history_ram_cycle_information(0, -1) """ }, 'parameters': [ @@ -297,20 +304,20 @@ { 'direction': 'in', 'documentation': { - 'description': 'Site on which to retrieve History RAM data. Specify site as a string in the form of siteN,\nwhere N is the site number. The VI returns an error if more than one site is specified.' + 'description': 'Site on which to retrieve History RAM data. The method returns an error if more than one site is specified.' }, + 'is_repeated_capability': True, + 'repeated_capability_type': 'sites', 'name': 'site', - 'python_api_converter_name': 'convert_site_to_string', # This won't actually change any code generation but is here for completeness - 'type_in_documentation': 'str or int', 'type': 'ViConstString' }, { 'direction': 'in', - 'is_repeated_capability': True, - 'repeated_capability_type': 'pins', 'documentation': { 'description': 'Pins for which to retrieve History RAM data. If empty, the pin list from the pattern\ncontaining the start label is used. Call niDigital_GetPatternPinList with the start\nlabel to retrieve the pins associated with the pattern burst.' }, + 'is_repeated_capability': True, + 'repeated_capability_type': 'pins', 'name': 'pinList', 'type': 'ViConstString' }, diff --git a/src/nidigital/system_tests/test_system_nidigital.py b/src/nidigital/system_tests/test_system_nidigital.py index bc6fbf819..924d26b34 100644 --- a/src/nidigital/system_tests/test_system_nidigital.py +++ b/src/nidigital/system_tests/test_system_nidigital.py @@ -283,14 +283,18 @@ def test_history_ram_cycle_information_representation(): assert str(recreated_cycle_info) == str(cycle_info) +def test_fetch_history_ram_cycle_information_without_site(multi_instrument_session): + configure_for_history_ram_test(multi_instrument_session) + + with pytest.raises(ValueError, match='Site number on which to retrieve pattern information must be specified via sites repeated capability.'): + multi_instrument_session.fetch_history_ram_cycle_information(position=-1, samples_to_read=-1) + + def test_fetch_history_ram_cycle_information_position_negative(multi_instrument_session): configure_for_history_ram_test(multi_instrument_session) with pytest.raises(ValueError, match='position should be greater than or equal to 0.'): - multi_instrument_session.fetch_history_ram_cycle_information( - site='site1', - position=-1, - samples_to_read=-1) + multi_instrument_session.sites[1].fetch_history_ram_cycle_information(position=-1, samples_to_read=-1) def configure_for_history_ram_test(session): @@ -312,18 +316,14 @@ def test_fetch_history_ram_cycle_information_position_out_of_bound(multi_instrum configure_for_history_ram_test(multi_instrument_session) with pytest.raises(ValueError, match='position: Specified value = 8, Maximum value = 6.'): - multi_instrument_session.fetch_history_ram_cycle_information( - site='site1', - position=8, - samples_to_read=-1) + multi_instrument_session.sites[1].fetch_history_ram_cycle_information(position=8, samples_to_read=-1) @pytest.mark.skip(reason="TODO(sbethur): Enable running on simulated session. GitHub issue #1273") def test_fetch_history_ram_cycle_information_position_last(multi_instrument_session): configure_for_history_ram_test(multi_instrument_session) - history_ram_cycle_info = multi_instrument_session.fetch_history_ram_cycle_information( - site='site1', + history_ram_cycle_info = multi_instrument_session.sites[1].fetch_history_ram_cycle_information( position=6, samples_to_read=-1) @@ -341,49 +341,35 @@ def test_fetch_history_ram_cycle_information_is_finite_invalid(multi_instrument_ 'Specifying -1 to fetch all History RAM samples is not supported when the digital pattern instrument ' 'is configured for continuous History RAM acquisition. You must specify an exact number of samples to fetch.') with pytest.raises(RuntimeError, match=expected_error_description): - multi_instrument_session.fetch_history_ram_cycle_information( - site='site1', - position=0, - samples_to_read=-1) + multi_instrument_session.sites[1].fetch_history_ram_cycle_information(position=0, samples_to_read=-1) @pytest.mark.skip(reason="TODO(sbethur): Enable running on simulated session. GitHub issue #1273") def test_fetch_history_ram_cycle_information_samples_to_read_too_much(multi_instrument_session): configure_for_history_ram_test(multi_instrument_session) - site = 'site1' - assert multi_instrument_session.get_history_ram_sample_count(site) == 7 + assert multi_instrument_session.sites[1].get_history_ram_sample_count() == 7 - multi_instrument_session.fetch_history_ram_cycle_information( - site=site, - position=0, - samples_to_read=3) + multi_instrument_session.sites[1].fetch_history_ram_cycle_information(position=0, samples_to_read=3) expected_error_description = ( 'position: Specified value = 3, samples_to_read: Specified value = 5; Samples available = 4.') with pytest.raises(ValueError, match=expected_error_description): - multi_instrument_session.fetch_history_ram_cycle_information( - site=site, - position=3, - samples_to_read=5) + multi_instrument_session.sites[1].fetch_history_ram_cycle_information(position=3, samples_to_read=5) def test_fetch_history_ram_cycle_information_samples_to_read_negative(multi_instrument_session): configure_for_history_ram_test(multi_instrument_session) with pytest.raises(ValueError, match='samples_to_read should be greater than or equal to -1.'): - multi_instrument_session.fetch_history_ram_cycle_information( - site='site1', - position=0, - samples_to_read=-2) + multi_instrument_session.sites[1].fetch_history_ram_cycle_information(position=0, samples_to_read=-2) @pytest.mark.skip(reason="TODO(sbethur): Enable running on simulated session. GitHub issue #1273") def test_fetch_history_ram_cycle_information_samples_to_read_zero(multi_instrument_session): configure_for_history_ram_test(multi_instrument_session) - history_ram_cycle_info = multi_instrument_session.fetch_history_ram_cycle_information( - site='site1', + history_ram_cycle_info = multi_instrument_session.sites[1].fetch_history_ram_cycle_information( position=0, samples_to_read=0) @@ -394,8 +380,7 @@ def test_fetch_history_ram_cycle_information_samples_to_read_zero(multi_instrume def test_fetch_history_ram_cycle_information_samples_to_read_all(multi_instrument_session): configure_for_history_ram_test(multi_instrument_session) - history_ram_cycle_info = multi_instrument_session.fetch_history_ram_cycle_information( - site='site1', + history_ram_cycle_info = multi_instrument_session.sites[1].fetch_history_ram_cycle_information( position=0, samples_to_read=-1) @@ -466,10 +451,14 @@ def test_fetch_history_ram_cycle_information_no_failures(multi_instrument_sessio multi_instrument_session.load_pattern(get_test_file_path(test_name, 'pattern.digipat')) multi_instrument_session.burst_pattern(start_label='new_pattern') - history_ram_cycle_info = multi_instrument_session.fetch_history_ram_cycle_information(site='site0', position=0, samples_to_read=-1) + history_ram_cycle_info = multi_instrument_session.sites[0].fetch_history_ram_cycle_information( + position=0, + samples_to_read=-1) assert len(history_ram_cycle_info) == 0 - history_ram_cycle_info = multi_instrument_session.fetch_history_ram_cycle_information(site='site0', position=0, samples_to_read=0) + history_ram_cycle_info = multi_instrument_session.sites[0].fetch_history_ram_cycle_information( + position=0, + samples_to_read=0) assert len(history_ram_cycle_info) == 0 @@ -484,42 +473,6 @@ def test_get_pattern_pin_names(multi_instrument_session): assert pattern_pin_names == ['LO' + str(i) for i in range(4)] + ['HI' + str(i) for i in range(4)] -# nidigital specific converter tests -# We are specifically using a "private" module to get to the converters so we can test the -# nidigital specific one -def test_convert_site_string(): - test_result = nidigital._converters.convert_site_to_string('1') - assert test_result == 'site1' - test_result = nidigital._converters.convert_site_to_string(1) - assert test_result == 'site1' - test_result = nidigital._converters.convert_site_to_string('site1') - assert test_result == 'site1' - test_result = nidigital._converters.convert_site_to_string('42') - assert test_result == 'site42' - test_result = nidigital._converters.convert_site_to_string(42) - assert test_result == 'site42' - test_result = nidigital._converters.convert_site_to_string('site42') - assert test_result == 'site42' - - -def test_convert_site_string_errors(): - try: - nidigital._converters.convert_site_to_string(1.0) - assert False - except TypeError: - pass - try: - nidigital._converters.convert_site_to_string(['1']) - assert False - except TypeError: - pass - try: - nidigital._converters.convert_site_to_string(False) - assert False - except TypeError: - pass - - def test_get_site_pass_fail(multi_instrument_session): test_files_folder = 'simple_pattern' configure_session(multi_instrument_session, test_files_folder) diff --git a/src/nidigital/templates/session.py/fancy_fetch_history_ram_cycle_information.py.mako b/src/nidigital/templates/session.py/fancy_fetch_history_ram_cycle_information.py.mako index 18348dd60..1884942f4 100644 --- a/src/nidigital/templates/session.py/fancy_fetch_history_ram_cycle_information.py.mako +++ b/src/nidigital/templates/session.py/fancy_fetch_history_ram_cycle_information.py.mako @@ -8,21 +8,34 @@ ${helper.get_function_docstring(f, False, config, indent=8)} ''' + # Extract the site number and pin list from repeated capability + repeated_capability_lists = _converters.convert_chained_repeated_capability_to_parts(self._repeated_capability) + site = repeated_capability_lists[0] + if not site.startswith('site'): + raise ValueError('Site number on which to retrieve pattern information must be specified via sites repeated capability.') + pins = '' if len(repeated_capability_lists) == 1 else repeated_capability_lists[1] + + # Put site back into repeated capability container; it will be used by other + # sites-rep-cap-based methods that will be called later. + self._repeated_capability = site + if position < 0: raise ValueError('position should be greater than or equal to 0.') if samples_to_read < -1: raise ValueError('samples_to_read should be greater than or equal to -1.') - samples_available = self.get_history_ram_sample_count(site) + # site is passed as repeated capability + samples_available = self.get_history_ram_sample_count() if position > samples_available: raise ValueError('position: Specified value = {0}, Maximum value = {1}.'.format(position, samples_available - 1)) if samples_to_read == -1: - if not self.history_ram_number_of_samples_is_finite: - raise RuntimeError( - 'Specifying -1 to fetch all History RAM samples is not supported when the digital pattern instrument is ' - 'configured for continuous History RAM acquisition. You must specify an exact number of samples to fetch.') + with _NoChannel(session=self): + if not self.history_ram_number_of_samples_is_finite: + raise RuntimeError( + 'Specifying -1 to fetch all History RAM samples is not supported when the digital pattern instrument is ' + 'configured for continuous History RAM acquisition. You must specify an exact number of samples to fetch.') samples_to_read = samples_available - position if position + samples_to_read > samples_available: @@ -30,30 +43,33 @@ 'position: Specified value = {0}, samples_to_read: Specified value = {1}; Samples available = {2}.' .format(position, samples_to_read, samples_available - position)) - # Site can be 'N', N or 'siteN'. This will normalize all options to 'siteN' which is requried by the driver - site = _converters.convert_site_to_string(site) pattern_names = {} time_set_names = {} cycle_infos = [] for _ in range(samples_to_read): - pattern_index, time_set_index, vector_number, cycle_number, num_dut_cycles = self._${f['python_name']}(site, position) + # site is passed as repeated capability + pattern_index, time_set_index, vector_number, cycle_number, num_dut_cycles = self._${f['python_name']}(position) if pattern_index not in pattern_names: + # Repeated capability is not used pattern_names[pattern_index] = self.get_pattern_name(pattern_index) pattern_name = pattern_names[pattern_index] if time_set_index not in time_set_names: + # Repeated capability is not used time_set_names[time_set_index] = self.get_time_set_name(time_set_index) time_set_name = time_set_names[time_set_index] - scan_cycle_number = self._fetch_history_ram_scan_cycle_number(site, position) + # site is passed as repeated capability + scan_cycle_number = self._fetch_history_ram_scan_cycle_number(position) vector_expected_pin_states = [] vector_actual_pin_states = [] vector_per_pin_pass_fail = [] for dut_cycle_index in range(num_dut_cycles): - cycle_expected_pin_states, cycle_actual_pin_states, cycle_per_pin_pass_fail = self._fetch_history_ram_cycle_pin_data(site, position, dut_cycle_index) + # site is passed as repeated capability + cycle_expected_pin_states, cycle_actual_pin_states, cycle_per_pin_pass_fail = self._fetch_history_ram_cycle_pin_data(pins, position, dut_cycle_index) vector_expected_pin_states.append(cycle_expected_pin_states) vector_actual_pin_states.append(cycle_actual_pin_states) vector_per_pin_pass_fail.append(cycle_per_pin_pass_fail) diff --git a/src/nidigital/unit_tests/test_nidigital.py b/src/nidigital/unit_tests/test_nidigital.py index 4c3edf3a3..16c0e7c8d 100644 --- a/src/nidigital/unit_tests/test_nidigital.py +++ b/src/nidigital/unit_tests/test_nidigital.py @@ -43,7 +43,4 @@ def test_fetch_history_ram_cycle_information_position_out_of_bound(self): self.side_effects_helper['GetHistoryRAMSampleCount']['sampleCount'] = 7 with nidigital.Session('') as session: with pytest.raises(ValueError, match='position: Specified value = 8, Maximum value = 6.'): - session.fetch_history_ram_cycle_information( - site='site1', - position=8, - samples_to_read=-1) + session.sites[1].fetch_history_ram_cycle_information(position=8, samples_to_read=-1)