From e9b6f72ffc6017882028383118d1be3bf0e4deeb Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald Date: Fri, 21 Jan 2022 16:50:22 -0600 Subject: [PATCH 01/18] Repeated Capabilites documentation improvements There are several issues open against the way we document usage of repeated capabilites in our rep_caps.rst pages. Summary of Issues * We present implementation details that the user doesn't care about - These may be useful to contributors, but to everyone else they're just distracting. * We list all of the possible types that can be passed to the indexing operator but don't make it clear what the recommend or "python" types are. - This information is worth keeping, but we need to provide better guidance. * We use channel_enabled in all of our examples, though it may not actually support the repeated capability in the example code. The approach to fixing this is as follows: * Turn documentation related to implementation details into comments only viewable in the raw source * Explicilty recommend what types to pass to the indexing operator. * Present examples which demonstrate accessing the repeated capability with our recommended types. - Do not present examples using other types. * Add a note that channel_enabled may not actually supported the repeated capability and to check individual property and method documentation. --- build/templates/rep_caps.rst.mako | 47 ++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/build/templates/rep_caps.rst.mako b/build/templates/rep_caps.rst.mako index 179d56e1fc..7a1e22022f 100644 --- a/build/templates/rep_caps.rst.mako +++ b/build/templates/rep_caps.rst.mako @@ -25,10 +25,15 @@ ${helper.get_rst_header_snippet('Repeated Capabilities', '=')} Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` + an integer. - Some repeated capabilities use a prefix before the number and this is optional + .. + If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or + :python:`'0:2'` + + Some repeated capabilities use a prefix before the number and this is optional. + + The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. % for rep_cap in config['repeated_capabilities']: <% @@ -40,27 +45,43 @@ ${helper.get_rst_header_snippet(name, '-')} .. py:attribute:: ${module_name}.Session.${name}[] % if len(prefix) > 0: - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. + .. + If no prefix is added to the items in the parameter, the correct prefix will be added when + the driver function call is made. - .. code:: python + .. code:: python + + session.${name}['0-2'].channel_enabled = True + + passes a string of :python:`'${prefix}0, ${prefix}1, ${prefix}2'` to the set attribute function. - session.${name}['0-2'].channel_enabled = True + If an invalid repeated capability is passed to the driver, the driver will return an error. - passes a string of :python:`'${prefix}0, ${prefix}1, ${prefix}2'` to the set attribute function. + You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix + for the specific repeated capability. - If an invalid repeated capability is passed to the driver, the driver will return an error. + .. code:: python - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. + session.${name}['${prefix}0-${prefix}2'].channel_enabled = True + + passes a string of :python:`'${prefix}0, ${prefix}1, ${prefix}2'` to the set attribute function. % endif .. code:: python - session.${name}['${prefix}0-${prefix}2'].channel_enabled = True + session.${name}[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for ${name} 0. + + .. code:: python - passes a string of :python:`'${prefix}0, ${prefix}1, ${prefix}2'` to the set attribute function. + session.${name}[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for ${name} 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. % endfor From 7b3a1a54942040f1db15d8fbad80d8435a0a58d7 Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald Date: Mon, 24 Jan 2022 13:17:06 -0600 Subject: [PATCH 02/18] codegen with rep_caps.rst changes --- docs/nidcpower/rep_caps.rst | 37 ++++-- docs/nidigital/rep_caps.rst | 230 +++++++++++++++++++++++++++--------- docs/nifgen/rep_caps.rst | 132 +++++++++++++++------ docs/niscope/rep_caps.rst | 37 ++++-- docs/niswitch/rep_caps.rst | 24 +++- 5 files changed, 347 insertions(+), 113 deletions(-) diff --git a/docs/nidcpower/rep_caps.rst b/docs/nidcpower/rep_caps.rst index 6078e4deab..3c8ef674cb 100644 --- a/docs/nidcpower/rep_caps.rst +++ b/docs/nidcpower/rep_caps.rst @@ -18,10 +18,15 @@ Repeated Capabilities Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` + an integer. - Some repeated capabilities use a prefix before the number and this is optional + .. + If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or + :python:`'0:2'` + + Some repeated capabilities use a prefix before the number and this is optional. + + The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. channels -------- @@ -30,10 +35,19 @@ channels .. code:: python - session.channels['0-2'].channel_enabled = True + session.channels[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for channels 0. + + .. code:: python - passes a string of :python:`'0, 1, 2'` to the set attribute function. + session.channels[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. instruments ----------- @@ -42,9 +56,18 @@ instruments .. code:: python - session.instruments['0-2'].channel_enabled = True + session.instruments[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for instruments 0. + + .. code:: python - passes a string of :python:`'0, 1, 2'` to the set attribute function. + session.instruments[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for instruments 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. diff --git a/docs/nidigital/rep_caps.rst b/docs/nidigital/rep_caps.rst index 32550fc4f8..5673bb45be 100644 --- a/docs/nidigital/rep_caps.rst +++ b/docs/nidigital/rep_caps.rst @@ -18,10 +18,15 @@ Repeated Capabilities Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` + an integer. - Some repeated capabilities use a prefix before the number and this is optional + .. + If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or + :python:`'0:2'` + + Some repeated capabilities use a prefix before the number and this is optional. + + The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. channels -------- @@ -30,10 +35,19 @@ channels .. code:: python - session.channels['0-2'].channel_enabled = True + session.channels[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for channels 0. - passes a string of :python:`'0, 1, 2'` to the set attribute function. + .. code:: python + + session.channels[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. pins ---- @@ -42,10 +56,19 @@ pins .. code:: python - session.pins['0-2'].channel_enabled = True + session.pins[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for pins 0. - passes a string of :python:`'0, 1, 2'` to the set attribute function. + .. code:: python + + session.pins[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for pins 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. instruments ----------- @@ -54,139 +77,228 @@ instruments .. code:: python - session.instruments['0-2'].channel_enabled = True + session.instruments[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for instruments 0. - passes a string of :python:`'0, 1, 2'` to the set attribute function. + .. code:: python + + session.instruments[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for instruments 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. pattern_opcode_events --------------------- .. py:attribute:: nidigital.Session.pattern_opcode_events[] - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. + .. + If no prefix is added to the items in the parameter, the correct prefix will be added when + the driver function call is made. - .. code:: python + .. code:: python - session.pattern_opcode_events['0-2'].channel_enabled = True + session.pattern_opcode_events['0-2'].channel_enabled = True - passes a string of :python:`'patternOpcodeEvent0, patternOpcodeEvent1, patternOpcodeEvent2'` to the set attribute function. + passes a string of :python:`'patternOpcodeEvent0, patternOpcodeEvent1, patternOpcodeEvent2'` to the set attribute function. - If an invalid repeated capability is passed to the driver, the driver will return an error. + If an invalid repeated capability is passed to the driver, the driver will return an error. - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. + You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix + for the specific repeated capability. + + .. code:: python + + session.pattern_opcode_events['patternOpcodeEvent0-patternOpcodeEvent2'].channel_enabled = True + + passes a string of :python:`'patternOpcodeEvent0, patternOpcodeEvent1, patternOpcodeEvent2'` to the set attribute function. .. code:: python - session.pattern_opcode_events['patternOpcodeEvent0-patternOpcodeEvent2'].channel_enabled = True + session.pattern_opcode_events[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for pattern_opcode_events 0. + + .. code:: python - passes a string of :python:`'patternOpcodeEvent0, patternOpcodeEvent1, patternOpcodeEvent2'` to the set attribute function. + session.pattern_opcode_events[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for pattern_opcode_events 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. conditional_jump_triggers ------------------------- .. py:attribute:: nidigital.Session.conditional_jump_triggers[] - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. + .. + If no prefix is added to the items in the parameter, the correct prefix will be added when + the driver function call is made. - .. code:: python + .. code:: python + + session.conditional_jump_triggers['0-2'].channel_enabled = True + + passes a string of :python:`'conditionalJumpTrigger0, conditionalJumpTrigger1, conditionalJumpTrigger2'` to the set attribute function. - session.conditional_jump_triggers['0-2'].channel_enabled = True + If an invalid repeated capability is passed to the driver, the driver will return an error. - passes a string of :python:`'conditionalJumpTrigger0, conditionalJumpTrigger1, conditionalJumpTrigger2'` to the set attribute function. + You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix + for the specific repeated capability. - If an invalid repeated capability is passed to the driver, the driver will return an error. + .. code:: python - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. + session.conditional_jump_triggers['conditionalJumpTrigger0-conditionalJumpTrigger2'].channel_enabled = True + + passes a string of :python:`'conditionalJumpTrigger0, conditionalJumpTrigger1, conditionalJumpTrigger2'` to the set attribute function. .. code:: python - session.conditional_jump_triggers['conditionalJumpTrigger0-conditionalJumpTrigger2'].channel_enabled = True + session.conditional_jump_triggers[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for conditional_jump_triggers 0. - passes a string of :python:`'conditionalJumpTrigger0, conditionalJumpTrigger1, conditionalJumpTrigger2'` to the set attribute function. + .. code:: python + + session.conditional_jump_triggers[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for conditional_jump_triggers 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. sites ----- .. py:attribute:: nidigital.Session.sites[] - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. + .. + If no prefix is added to the items in the parameter, the correct prefix will be added when + the driver function call is made. - .. code:: python + .. code:: python + + session.sites['0-2'].channel_enabled = True + + passes a string of :python:`'site0, site1, site2'` to the set attribute function. + + If an invalid repeated capability is passed to the driver, the driver will return an error. - session.sites['0-2'].channel_enabled = True + You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix + for the specific repeated capability. - passes a string of :python:`'site0, site1, site2'` to the set attribute function. + .. code:: python - If an invalid repeated capability is passed to the driver, the driver will return an error. + session.sites['site0-site2'].channel_enabled = True - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. + passes a string of :python:`'site0, site1, site2'` to the set attribute function. .. code:: python - session.sites['site0-site2'].channel_enabled = True + session.sites[0].channel_enabled = True - passes a string of :python:`'site0, site1, site2'` to the set attribute function. + sets :py:attr:`channel_enabled` to :python:`True` for sites 0. + .. code:: python + + session.sites[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for sites 0, 1, 2. + + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. rio_events ---------- .. py:attribute:: nidigital.Session.rio_events[] - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. + .. + If no prefix is added to the items in the parameter, the correct prefix will be added when + the driver function call is made. - .. code:: python + .. code:: python + + session.rio_events['0-2'].channel_enabled = True + + passes a string of :python:`'RIOEvent0, RIOEvent1, RIOEvent2'` to the set attribute function. - session.rio_events['0-2'].channel_enabled = True + If an invalid repeated capability is passed to the driver, the driver will return an error. - passes a string of :python:`'RIOEvent0, RIOEvent1, RIOEvent2'` to the set attribute function. + You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix + for the specific repeated capability. - If an invalid repeated capability is passed to the driver, the driver will return an error. + .. code:: python - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. + session.rio_events['RIOEvent0-RIOEvent2'].channel_enabled = True + + passes a string of :python:`'RIOEvent0, RIOEvent1, RIOEvent2'` to the set attribute function. .. code:: python - session.rio_events['RIOEvent0-RIOEvent2'].channel_enabled = True + session.rio_events[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for rio_events 0. + + .. code:: python - passes a string of :python:`'RIOEvent0, RIOEvent1, RIOEvent2'` to the set attribute function. + session.rio_events[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for rio_events 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. rio_triggers ------------ .. py:attribute:: nidigital.Session.rio_triggers[] - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. + .. + If no prefix is added to the items in the parameter, the correct prefix will be added when + the driver function call is made. - .. code:: python + .. code:: python + + session.rio_triggers['0-2'].channel_enabled = True - session.rio_triggers['0-2'].channel_enabled = True + passes a string of :python:`'RIOTrigger0, RIOTrigger1, RIOTrigger2'` to the set attribute function. - passes a string of :python:`'RIOTrigger0, RIOTrigger1, RIOTrigger2'` to the set attribute function. + If an invalid repeated capability is passed to the driver, the driver will return an error. - If an invalid repeated capability is passed to the driver, the driver will return an error. + You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix + for the specific repeated capability. - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. + .. code:: python + + session.rio_triggers['RIOTrigger0-RIOTrigger2'].channel_enabled = True + + passes a string of :python:`'RIOTrigger0, RIOTrigger1, RIOTrigger2'` to the set attribute function. .. code:: python - session.rio_triggers['RIOTrigger0-RIOTrigger2'].channel_enabled = True + session.rio_triggers[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for rio_triggers 0. + + .. code:: python - passes a string of :python:`'RIOTrigger0, RIOTrigger1, RIOTrigger2'` to the set attribute function. + session.rio_triggers[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for rio_triggers 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. diff --git a/docs/nifgen/rep_caps.rst b/docs/nifgen/rep_caps.rst index 5890a432ea..67d22d84b9 100644 --- a/docs/nifgen/rep_caps.rst +++ b/docs/nifgen/rep_caps.rst @@ -18,10 +18,15 @@ Repeated Capabilities Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` + an integer. - Some repeated capabilities use a prefix before the number and this is optional + .. + If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or + :python:`'0:2'` + + Some repeated capabilities use a prefix before the number and this is optional. + + The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. channels -------- @@ -30,87 +35,144 @@ channels .. code:: python - session.channels['0-2'].channel_enabled = True + session.channels[0].channel_enabled = True - passes a string of :python:`'0, 1, 2'` to the set attribute function. + sets :py:attr:`channel_enabled` to :python:`True` for channels 0. + + .. code:: python + session.channels[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1, 2. + + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. script_triggers --------------- .. py:attribute:: nifgen.Session.script_triggers[] - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. + .. + If no prefix is added to the items in the parameter, the correct prefix will be added when + the driver function call is made. - .. code:: python + .. code:: python + + session.script_triggers['0-2'].channel_enabled = True - session.script_triggers['0-2'].channel_enabled = True + passes a string of :python:`'ScriptTrigger0, ScriptTrigger1, ScriptTrigger2'` to the set attribute function. - passes a string of :python:`'ScriptTrigger0, ScriptTrigger1, ScriptTrigger2'` to the set attribute function. + If an invalid repeated capability is passed to the driver, the driver will return an error. - If an invalid repeated capability is passed to the driver, the driver will return an error. + You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix + for the specific repeated capability. - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. + .. code:: python + + session.script_triggers['ScriptTrigger0-ScriptTrigger2'].channel_enabled = True + + passes a string of :python:`'ScriptTrigger0, ScriptTrigger1, ScriptTrigger2'` to the set attribute function. .. code:: python - session.script_triggers['ScriptTrigger0-ScriptTrigger2'].channel_enabled = True + session.script_triggers[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for script_triggers 0. - passes a string of :python:`'ScriptTrigger0, ScriptTrigger1, ScriptTrigger2'` to the set attribute function. + .. code:: python + + session.script_triggers[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for script_triggers 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. markers ------- .. py:attribute:: nifgen.Session.markers[] - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. + .. + If no prefix is added to the items in the parameter, the correct prefix will be added when + the driver function call is made. - .. code:: python + .. code:: python - session.markers['0-2'].channel_enabled = True + session.markers['0-2'].channel_enabled = True - passes a string of :python:`'Marker0, Marker1, Marker2'` to the set attribute function. + passes a string of :python:`'Marker0, Marker1, Marker2'` to the set attribute function. - If an invalid repeated capability is passed to the driver, the driver will return an error. + If an invalid repeated capability is passed to the driver, the driver will return an error. - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. + You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix + for the specific repeated capability. + + .. code:: python + + session.markers['Marker0-Marker2'].channel_enabled = True + + passes a string of :python:`'Marker0, Marker1, Marker2'` to the set attribute function. .. code:: python - session.markers['Marker0-Marker2'].channel_enabled = True + session.markers[0].channel_enabled = True - passes a string of :python:`'Marker0, Marker1, Marker2'` to the set attribute function. + sets :py:attr:`channel_enabled` to :python:`True` for markers 0. + .. code:: python + + session.markers[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for markers 0, 1, 2. + + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. data_markers ------------ .. py:attribute:: nifgen.Session.data_markers[] - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. + .. + If no prefix is added to the items in the parameter, the correct prefix will be added when + the driver function call is made. - .. code:: python + .. code:: python - session.data_markers['0-2'].channel_enabled = True + session.data_markers['0-2'].channel_enabled = True - passes a string of :python:`'DataMarker0, DataMarker1, DataMarker2'` to the set attribute function. + passes a string of :python:`'DataMarker0, DataMarker1, DataMarker2'` to the set attribute function. - If an invalid repeated capability is passed to the driver, the driver will return an error. + If an invalid repeated capability is passed to the driver, the driver will return an error. - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. + You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix + for the specific repeated capability. + + .. code:: python + + session.data_markers['DataMarker0-DataMarker2'].channel_enabled = True + + passes a string of :python:`'DataMarker0, DataMarker1, DataMarker2'` to the set attribute function. .. code:: python - session.data_markers['DataMarker0-DataMarker2'].channel_enabled = True + session.data_markers[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for data_markers 0. + + .. code:: python - passes a string of :python:`'DataMarker0, DataMarker1, DataMarker2'` to the set attribute function. + session.data_markers[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for data_markers 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. diff --git a/docs/niscope/rep_caps.rst b/docs/niscope/rep_caps.rst index 19169bc085..1bfc310384 100644 --- a/docs/niscope/rep_caps.rst +++ b/docs/niscope/rep_caps.rst @@ -18,10 +18,15 @@ Repeated Capabilities Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` + an integer. - Some repeated capabilities use a prefix before the number and this is optional + .. + If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or + :python:`'0:2'` + + Some repeated capabilities use a prefix before the number and this is optional. + + The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. channels -------- @@ -30,10 +35,19 @@ channels .. code:: python - session.channels['0-2'].channel_enabled = True + session.channels[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for channels 0. + + .. code:: python - passes a string of :python:`'0, 1, 2'` to the set attribute function. + session.channels[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. instruments ----------- @@ -42,9 +56,18 @@ instruments .. code:: python - session.instruments['0-2'].channel_enabled = True + session.instruments[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for instruments 0. + + .. code:: python - passes a string of :python:`'0, 1, 2'` to the set attribute function. + session.instruments[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for instruments 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. diff --git a/docs/niswitch/rep_caps.rst b/docs/niswitch/rep_caps.rst index 7f141fa26b..440cd3d956 100644 --- a/docs/niswitch/rep_caps.rst +++ b/docs/niswitch/rep_caps.rst @@ -18,10 +18,15 @@ Repeated Capabilities Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` + an integer. - Some repeated capabilities use a prefix before the number and this is optional + .. + If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or + :python:`'0:2'` + + Some repeated capabilities use a prefix before the number and this is optional. + + The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. channels -------- @@ -30,9 +35,18 @@ channels .. code:: python - session.channels['0-2'].channel_enabled = True + session.channels[0].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for channels 0. + + .. code:: python - passes a string of :python:`'0, 1, 2'` to the set attribute function. + session.channels[0:2].channel_enabled = True + + sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1, 2. + Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which + supports this repeated capability. See documentation for individual properties and methods to + learn what repeated capabilites they support, if any. From 8bc69bcaafc7814fa3327989f7b9d9a7222bf80e Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald Date: Fri, 28 Jan 2022 12:19:52 -0600 Subject: [PATCH 03/18] Remove comment containing tips we decided weren't useful --- build/templates/rep_caps.rst.mako | 6 ------ docs/nidcpower/rep_caps.rst | 6 ------ docs/nidigital/rep_caps.rst | 6 ------ docs/nifgen/rep_caps.rst | 6 ------ docs/niscope/rep_caps.rst | 6 ------ docs/niswitch/rep_caps.rst | 6 ------ 6 files changed, 36 deletions(-) diff --git a/build/templates/rep_caps.rst.mako b/build/templates/rep_caps.rst.mako index 7a1e22022f..a08835738f 100644 --- a/build/templates/rep_caps.rst.mako +++ b/build/templates/rep_caps.rst.mako @@ -27,12 +27,6 @@ ${helper.get_rst_header_snippet('Repeated Capabilities', '=')} The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or an integer. - .. - If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` - - Some repeated capabilities use a prefix before the number and this is optional. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. % for rep_cap in config['repeated_capabilities']: diff --git a/docs/nidcpower/rep_caps.rst b/docs/nidcpower/rep_caps.rst index 3c8ef674cb..101ac63dff 100644 --- a/docs/nidcpower/rep_caps.rst +++ b/docs/nidcpower/rep_caps.rst @@ -20,12 +20,6 @@ Repeated Capabilities The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or an integer. - .. - If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` - - Some repeated capabilities use a prefix before the number and this is optional. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. channels diff --git a/docs/nidigital/rep_caps.rst b/docs/nidigital/rep_caps.rst index 5673bb45be..cc79bf5666 100644 --- a/docs/nidigital/rep_caps.rst +++ b/docs/nidigital/rep_caps.rst @@ -20,12 +20,6 @@ Repeated Capabilities The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or an integer. - .. - If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` - - Some repeated capabilities use a prefix before the number and this is optional. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. channels diff --git a/docs/nifgen/rep_caps.rst b/docs/nifgen/rep_caps.rst index 67d22d84b9..94cc4d39bc 100644 --- a/docs/nifgen/rep_caps.rst +++ b/docs/nifgen/rep_caps.rst @@ -20,12 +20,6 @@ Repeated Capabilities The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or an integer. - .. - If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` - - Some repeated capabilities use a prefix before the number and this is optional. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. channels diff --git a/docs/niscope/rep_caps.rst b/docs/niscope/rep_caps.rst index 1bfc310384..2e5c40c16e 100644 --- a/docs/niscope/rep_caps.rst +++ b/docs/niscope/rep_caps.rst @@ -20,12 +20,6 @@ Repeated Capabilities The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or an integer. - .. - If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` - - Some repeated capabilities use a prefix before the number and this is optional. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. channels diff --git a/docs/niswitch/rep_caps.rst b/docs/niswitch/rep_caps.rst index 440cd3d956..ef78e3206c 100644 --- a/docs/niswitch/rep_caps.rst +++ b/docs/niswitch/rep_caps.rst @@ -20,12 +20,6 @@ Repeated Capabilities The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or an integer. - .. - If it is a string, you can indicate a range using the same format as the driver: :python:`'0-2'` or - :python:`'0:2'` - - Some repeated capabilities use a prefix before the number and this is optional. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. channels From 93d62f188f83e2d63d0cba7101392923a59ac967 Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald Date: Fri, 28 Jan 2022 13:39:46 -0600 Subject: [PATCH 04/18] Update general description of repeated capabilities. --- build/templates/rep_caps.rst.mako | 17 +++++++++++------ docs/nidcpower/rep_caps.rst | 13 +++++++------ docs/nidigital/rep_caps.rst | 21 ++++++++++++++------- docs/nifgen/rep_caps.rst | 15 +++++++++------ docs/niscope/rep_caps.rst | 13 +++++++------ docs/niswitch/rep_caps.rst | 12 ++++++------ 6 files changed, 54 insertions(+), 37 deletions(-) diff --git a/build/templates/rep_caps.rst.mako b/build/templates/rep_caps.rst.mako index a08835738f..31e436eee9 100644 --- a/build/templates/rep_caps.rst.mako +++ b/build/templates/rep_caps.rst.mako @@ -19,13 +19,18 @@ ${helper.get_rst_header_snippet('Repeated Capabilities', '=')} - Repeated capabilities attributes are used to set the `channel_string` parameter to the - underlying driver function call. This can be the actual function based on the :py:class:`Session` - method being called, or it can be the appropriate Get/Set Attribute function, such as :c:`${config['c_function_prefix']}SetAttributeViInt32()`. + :py:class:`${module_name}.Session` supports "Repeated Capabilities", which are multiple instances of the same type of + functionality. The repeated capabilities supported by :py:class:`${module_name}.Session` are: - Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. - The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. +% for rep_cap in config['repeated_capabilities']: +<% +name = rep_cap['python_name'] +%>\ + #. ${name}_ +% endfor + + Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. diff --git a/docs/nidcpower/rep_caps.rst b/docs/nidcpower/rep_caps.rst index 101ac63dff..4d87ee95b2 100644 --- a/docs/nidcpower/rep_caps.rst +++ b/docs/nidcpower/rep_caps.rst @@ -12,13 +12,14 @@ Repeated Capabilities ===================== - Repeated capabilities attributes are used to set the `channel_string` parameter to the - underlying driver function call. This can be the actual function based on the :py:class:`Session` - method being called, or it can be the appropriate Get/Set Attribute function, such as :c:`niDCPower_SetAttributeViInt32()`. + :py:class:`nidcpower.Session` supports "Repeated Capabilities", which are multiple instances of the same type of + functionality. The repeated capabilities supported by :py:class:`nidcpower.Session` are: - Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. - The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. + #. channels_ + #. instruments_ + + Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. diff --git a/docs/nidigital/rep_caps.rst b/docs/nidigital/rep_caps.rst index cc79bf5666..fdefa0b426 100644 --- a/docs/nidigital/rep_caps.rst +++ b/docs/nidigital/rep_caps.rst @@ -12,13 +12,20 @@ Repeated Capabilities ===================== - Repeated capabilities attributes are used to set the `channel_string` parameter to the - underlying driver function call. This can be the actual function based on the :py:class:`Session` - method being called, or it can be the appropriate Get/Set Attribute function, such as :c:`niDigital_SetAttributeViInt32()`. - - Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. - The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. + :py:class:`nidigital.Session` supports "Repeated Capabilities", which are multiple instances of the same type of + functionality. The repeated capabilities supported by :py:class:`nidigital.Session` are: + + #. channels_ + #. pins_ + #. instruments_ + #. pattern_opcode_events_ + #. conditional_jump_triggers_ + #. sites_ + #. rio_events_ + #. rio_triggers_ + + Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. diff --git a/docs/nifgen/rep_caps.rst b/docs/nifgen/rep_caps.rst index 94cc4d39bc..089864079b 100644 --- a/docs/nifgen/rep_caps.rst +++ b/docs/nifgen/rep_caps.rst @@ -12,13 +12,16 @@ Repeated Capabilities ===================== - Repeated capabilities attributes are used to set the `channel_string` parameter to the - underlying driver function call. This can be the actual function based on the :py:class:`Session` - method being called, or it can be the appropriate Get/Set Attribute function, such as :c:`niFgen_SetAttributeViInt32()`. + :py:class:`nifgen.Session` supports "Repeated Capabilities", which are multiple instances of the same type of + functionality. The repeated capabilities supported by :py:class:`nifgen.Session` are: - Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. - The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. + #. channels_ + #. script_triggers_ + #. markers_ + #. data_markers_ + + Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. diff --git a/docs/niscope/rep_caps.rst b/docs/niscope/rep_caps.rst index 2e5c40c16e..ef90c8f454 100644 --- a/docs/niscope/rep_caps.rst +++ b/docs/niscope/rep_caps.rst @@ -12,13 +12,14 @@ Repeated Capabilities ===================== - Repeated capabilities attributes are used to set the `channel_string` parameter to the - underlying driver function call. This can be the actual function based on the :py:class:`Session` - method being called, or it can be the appropriate Get/Set Attribute function, such as :c:`niScope_SetAttributeViInt32()`. + :py:class:`niscope.Session` supports "Repeated Capabilities", which are multiple instances of the same type of + functionality. The repeated capabilities supported by :py:class:`niscope.Session` are: - Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. - The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. + #. channels_ + #. instruments_ + + Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. diff --git a/docs/niswitch/rep_caps.rst b/docs/niswitch/rep_caps.rst index ef78e3206c..a28b0d6d8a 100644 --- a/docs/niswitch/rep_caps.rst +++ b/docs/niswitch/rep_caps.rst @@ -12,13 +12,13 @@ Repeated Capabilities ===================== - Repeated capabilities attributes are used to set the `channel_string` parameter to the - underlying driver function call. This can be the actual function based on the :py:class:`Session` - method being called, or it can be the appropriate Get/Set Attribute function, such as :c:`niSwitch_SetAttributeViInt32()`. + :py:class:`niswitch.Session` supports "Repeated Capabilities", which are multiple instances of the same type of + functionality. The repeated capabilities supported by :py:class:`niswitch.Session` are: - Repeated capabilities attributes use the indexing operator :python:`[]` to indicate the repeated capabilities. - The parameter can be a string, list, tuple, or slice (range). Each element of those can be a string or - an integer. + #. channels_ + + Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. From 4fda89a0643f2ea0563d7b74747d4946bfb94f21 Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Mon, 3 Apr 2023 09:09:46 -0500 Subject: [PATCH 05/18] indexing is for repeated capability **instance** --- build/templates/rep_caps.rst.mako | 2 +- docs/nidcpower/rep_caps.rst | 2 +- docs/nidigital/rep_caps.rst | 2 +- docs/nifgen/rep_caps.rst | 2 +- docs/niscope/rep_caps.rst | 2 +- docs/niswitch/rep_caps.rst | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/templates/rep_caps.rst.mako b/build/templates/rep_caps.rst.mako index 31e436eee9..fd7d97814f 100644 --- a/build/templates/rep_caps.rst.mako +++ b/build/templates/rep_caps.rst.mako @@ -29,7 +29,7 @@ name = rep_cap['python_name'] #. ${name}_ % endfor - Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. diff --git a/docs/nidcpower/rep_caps.rst b/docs/nidcpower/rep_caps.rst index 4d87ee95b2..cb8b9ea18c 100644 --- a/docs/nidcpower/rep_caps.rst +++ b/docs/nidcpower/rep_caps.rst @@ -18,7 +18,7 @@ Repeated Capabilities #. channels_ #. instruments_ - Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. diff --git a/docs/nidigital/rep_caps.rst b/docs/nidigital/rep_caps.rst index fdefa0b426..b02027c4ce 100644 --- a/docs/nidigital/rep_caps.rst +++ b/docs/nidigital/rep_caps.rst @@ -24,7 +24,7 @@ Repeated Capabilities #. rio_events_ #. rio_triggers_ - Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. diff --git a/docs/nifgen/rep_caps.rst b/docs/nifgen/rep_caps.rst index 089864079b..4491f378cb 100644 --- a/docs/nifgen/rep_caps.rst +++ b/docs/nifgen/rep_caps.rst @@ -20,7 +20,7 @@ Repeated Capabilities #. markers_ #. data_markers_ - Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. diff --git a/docs/niscope/rep_caps.rst b/docs/niscope/rep_caps.rst index ef90c8f454..01caa24a52 100644 --- a/docs/niscope/rep_caps.rst +++ b/docs/niscope/rep_caps.rst @@ -18,7 +18,7 @@ Repeated Capabilities #. channels_ #. instruments_ - Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. diff --git a/docs/niswitch/rep_caps.rst b/docs/niswitch/rep_caps.rst index a28b0d6d8a..a6189b9b35 100644 --- a/docs/niswitch/rep_caps.rst +++ b/docs/niswitch/rep_caps.rst @@ -17,7 +17,7 @@ Repeated Capabilities #. channels_ - Use the indexing operator :python:`[]` to indicate which repeated capability you are trying to access. + Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be an integer, a string, a list, a tuple, or slice (range). The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. From 948db7a241c90c3e5a02188d219d9da7b0aa1fe0 Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Mon, 3 Apr 2023 09:50:12 -0500 Subject: [PATCH 06/18] Remove commented section for non-0-length prefixes --- build/templates/rep_caps.rst.mako | 23 ------- docs/nidigital/rep_caps.rst | 105 ------------------------------ docs/nifgen/rep_caps.rst | 63 ------------------ 3 files changed, 191 deletions(-) diff --git a/build/templates/rep_caps.rst.mako b/build/templates/rep_caps.rst.mako index fd7d97814f..2d21d4ff4d 100644 --- a/build/templates/rep_caps.rst.mako +++ b/build/templates/rep_caps.rst.mako @@ -43,29 +43,6 @@ ${helper.get_rst_header_snippet(name, '-')} .. py:attribute:: ${module_name}.Session.${name}[] -% if len(prefix) > 0: - .. - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. - - .. code:: python - - session.${name}['0-2'].channel_enabled = True - - passes a string of :python:`'${prefix}0, ${prefix}1, ${prefix}2'` to the set attribute function. - - If an invalid repeated capability is passed to the driver, the driver will return an error. - - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. - - .. code:: python - - session.${name}['${prefix}0-${prefix}2'].channel_enabled = True - - passes a string of :python:`'${prefix}0, ${prefix}1, ${prefix}2'` to the set attribute function. - -% endif .. code:: python session.${name}[0].channel_enabled = True diff --git a/docs/nidigital/rep_caps.rst b/docs/nidigital/rep_caps.rst index b02027c4ce..f952263389 100644 --- a/docs/nidigital/rep_caps.rst +++ b/docs/nidigital/rep_caps.rst @@ -97,27 +97,6 @@ pattern_opcode_events .. py:attribute:: nidigital.Session.pattern_opcode_events[] - .. - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. - - .. code:: python - - session.pattern_opcode_events['0-2'].channel_enabled = True - - passes a string of :python:`'patternOpcodeEvent0, patternOpcodeEvent1, patternOpcodeEvent2'` to the set attribute function. - - If an invalid repeated capability is passed to the driver, the driver will return an error. - - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. - - .. code:: python - - session.pattern_opcode_events['patternOpcodeEvent0-patternOpcodeEvent2'].channel_enabled = True - - passes a string of :python:`'patternOpcodeEvent0, patternOpcodeEvent1, patternOpcodeEvent2'` to the set attribute function. - .. code:: python session.pattern_opcode_events[0].channel_enabled = True @@ -139,27 +118,6 @@ conditional_jump_triggers .. py:attribute:: nidigital.Session.conditional_jump_triggers[] - .. - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. - - .. code:: python - - session.conditional_jump_triggers['0-2'].channel_enabled = True - - passes a string of :python:`'conditionalJumpTrigger0, conditionalJumpTrigger1, conditionalJumpTrigger2'` to the set attribute function. - - If an invalid repeated capability is passed to the driver, the driver will return an error. - - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. - - .. code:: python - - session.conditional_jump_triggers['conditionalJumpTrigger0-conditionalJumpTrigger2'].channel_enabled = True - - passes a string of :python:`'conditionalJumpTrigger0, conditionalJumpTrigger1, conditionalJumpTrigger2'` to the set attribute function. - .. code:: python session.conditional_jump_triggers[0].channel_enabled = True @@ -181,27 +139,6 @@ sites .. py:attribute:: nidigital.Session.sites[] - .. - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. - - .. code:: python - - session.sites['0-2'].channel_enabled = True - - passes a string of :python:`'site0, site1, site2'` to the set attribute function. - - If an invalid repeated capability is passed to the driver, the driver will return an error. - - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. - - .. code:: python - - session.sites['site0-site2'].channel_enabled = True - - passes a string of :python:`'site0, site1, site2'` to the set attribute function. - .. code:: python session.sites[0].channel_enabled = True @@ -223,27 +160,6 @@ rio_events .. py:attribute:: nidigital.Session.rio_events[] - .. - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. - - .. code:: python - - session.rio_events['0-2'].channel_enabled = True - - passes a string of :python:`'RIOEvent0, RIOEvent1, RIOEvent2'` to the set attribute function. - - If an invalid repeated capability is passed to the driver, the driver will return an error. - - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. - - .. code:: python - - session.rio_events['RIOEvent0-RIOEvent2'].channel_enabled = True - - passes a string of :python:`'RIOEvent0, RIOEvent1, RIOEvent2'` to the set attribute function. - .. code:: python session.rio_events[0].channel_enabled = True @@ -265,27 +181,6 @@ rio_triggers .. py:attribute:: nidigital.Session.rio_triggers[] - .. - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. - - .. code:: python - - session.rio_triggers['0-2'].channel_enabled = True - - passes a string of :python:`'RIOTrigger0, RIOTrigger1, RIOTrigger2'` to the set attribute function. - - If an invalid repeated capability is passed to the driver, the driver will return an error. - - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. - - .. code:: python - - session.rio_triggers['RIOTrigger0-RIOTrigger2'].channel_enabled = True - - passes a string of :python:`'RIOTrigger0, RIOTrigger1, RIOTrigger2'` to the set attribute function. - .. code:: python session.rio_triggers[0].channel_enabled = True diff --git a/docs/nifgen/rep_caps.rst b/docs/nifgen/rep_caps.rst index 4491f378cb..e4810ff469 100644 --- a/docs/nifgen/rep_caps.rst +++ b/docs/nifgen/rep_caps.rst @@ -51,27 +51,6 @@ script_triggers .. py:attribute:: nifgen.Session.script_triggers[] - .. - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. - - .. code:: python - - session.script_triggers['0-2'].channel_enabled = True - - passes a string of :python:`'ScriptTrigger0, ScriptTrigger1, ScriptTrigger2'` to the set attribute function. - - If an invalid repeated capability is passed to the driver, the driver will return an error. - - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. - - .. code:: python - - session.script_triggers['ScriptTrigger0-ScriptTrigger2'].channel_enabled = True - - passes a string of :python:`'ScriptTrigger0, ScriptTrigger1, ScriptTrigger2'` to the set attribute function. - .. code:: python session.script_triggers[0].channel_enabled = True @@ -93,27 +72,6 @@ markers .. py:attribute:: nifgen.Session.markers[] - .. - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. - - .. code:: python - - session.markers['0-2'].channel_enabled = True - - passes a string of :python:`'Marker0, Marker1, Marker2'` to the set attribute function. - - If an invalid repeated capability is passed to the driver, the driver will return an error. - - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. - - .. code:: python - - session.markers['Marker0-Marker2'].channel_enabled = True - - passes a string of :python:`'Marker0, Marker1, Marker2'` to the set attribute function. - .. code:: python session.markers[0].channel_enabled = True @@ -135,27 +93,6 @@ data_markers .. py:attribute:: nifgen.Session.data_markers[] - .. - If no prefix is added to the items in the parameter, the correct prefix will be added when - the driver function call is made. - - .. code:: python - - session.data_markers['0-2'].channel_enabled = True - - passes a string of :python:`'DataMarker0, DataMarker1, DataMarker2'` to the set attribute function. - - If an invalid repeated capability is passed to the driver, the driver will return an error. - - You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix - for the specific repeated capability. - - .. code:: python - - session.data_markers['DataMarker0-DataMarker2'].channel_enabled = True - - passes a string of :python:`'DataMarker0, DataMarker1, DataMarker2'` to the set attribute function. - .. code:: python session.data_markers[0].channel_enabled = True From d48cfc9f1dd8196697ca22cf4473979c20f729c8 Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:45:14 -0500 Subject: [PATCH 07/18] generate correct snippets for nidigital --- build/helper/__init__.py | 2 + build/helper/documentation_helper.py | 103 +++++++++++++++++ build/templates/rep_caps.rst.mako | 24 ++-- build/unit_tests/test_documentation_helper.py | 106 ++++++++++++++++++ docs/nidcpower/rep_caps.rst | 23 ++-- docs/nidigital/rep_caps.rst | 103 ++++++----------- docs/nifgen/rep_caps.rst | 39 +++---- docs/niscope/rep_caps.rst | 23 ++-- docs/niswitch/rep_caps.rst | 15 ++- src/nidigital/metadata/config_addon.py | 62 ++++++++++ 10 files changed, 361 insertions(+), 139 deletions(-) diff --git a/build/helper/__init__.py b/build/helper/__init__.py index f6d8dbcfa1..f0829cd9f3 100644 --- a/build/helper/__init__.py +++ b/build/helper/__init__.py @@ -23,6 +23,8 @@ from build.helper.documentation_helper import get_function_docstring # noqa: F401 from build.helper.documentation_helper import get_function_rst # noqa: F401 from build.helper.documentation_helper import get_indented_docstring_snippet # noqa: F401 +from build.helper.documentation_helper import get_repeated_capability_single_index_python_example # noqa: F401 +from build.helper.documentation_helper import get_repeated_capability_tuple_index_python_example # noqa: F401 from build.helper.documentation_helper import get_rst_header_snippet # noqa: F401 from build.helper.documentation_helper import get_rst_picture_reference # noqa: F401 from build.helper.documentation_helper import module_supports_repeated_caps # noqa: F401 diff --git a/build/helper/documentation_helper.py b/build/helper/documentation_helper.py index 1aade68d01..2398b85103 100644 --- a/build/helper/documentation_helper.py +++ b/build/helper/documentation_helper.py @@ -56,6 +56,109 @@ def get_indented_docstring_snippet(d, indent=4): return ret_val +def get_repeated_capability_single_index_python_example(rep_cap_config): + '''Returns a python code snippet and explanation for example usage of a repeated capability.''' + rep_cap_name = rep_cap_config['python_name'] + + # TODO(ni-jfitzger): Handle read-only properties (snippet to print the value) + + # defaults + attr_for_example = 'channel_enabled' + attr_type_for_example = 'property' + class_attr_ref = f':py:attr:`{attr_for_example}`' + index = 0 + value = True + value_type = bool + + if 'attr_for_docs_example' in rep_cap_config and rep_cap_config['attr_for_docs_example']: + attr_for_example = rep_cap_config['attr_for_docs_example'] + if 'attr_type_for_docs_example' in rep_cap_config and rep_cap_config['attr_type_for_docs_example']: + attr_type_for_example = rep_cap_config['attr_type_for_docs_example'] + if attr_type_for_example == 'property': + class_attr_ref = f':py:attr:`{attr_for_example}`' + elif attr_type_for_example == 'method': + class_attr_ref = f':py:meth:`{attr_for_example}`' + if 'string_indices_for_docs_example' in rep_cap_config: + index = repr(rep_cap_config["string_indices_for_docs_example"][0]) + if 'value_for_docs_example' in rep_cap_config: + value = rep_cap_config['value_for_docs_example'] + value_type = type(value) + if 'value_type_for_docs_example' in rep_cap_config: + value_type = rep_cap_config['value_type_for_docs_example'] + if not value_type == 'enum' and isinstance(value, str): + value = repr(value) + + explanation_value = f':python:`{value}`' + if value_type == 'enum': + explanation_value = f':py:data:`~{value}`' + + if attr_type_for_example == "property": + snippet = f'session.{rep_cap_name}[{index}].{attr_for_example} = {value}' + explanation = f"sets {class_attr_ref} to {explanation_value} for {rep_cap_name} {index}." + elif attr_type_for_example == "method": + if value is None: + snippet = f'session.{rep_cap_name}[{index}].{attr_for_example}()' + explanation = f"calls {class_attr_ref} for {rep_cap_name} {index}." + else: + snippet = f'session.{rep_cap_name}[{index}].{attr_for_example}({value})' + explanation = f"calls {class_attr_ref} with {explanation_value} for {rep_cap_name} {index}." + else: + raise ValueError(f"Ilegal value {attr_type_for_example} in {repr(rep_cap_config)}.") + return snippet, explanation + + +def get_repeated_capability_tuple_index_python_example(rep_cap_config): + '''Returns a python code snippet and explanation for example usage of a repeated capability.''' + rep_cap_name = rep_cap_config['python_name'] + + # TODO(ni-jfitzger): Handle read-only properties (snippet to print the value) + + # defaults + attr_for_example = 'channel_enabled' + attr_type_for_example = 'property' + class_attr_ref = f':py:attr:`{attr_for_example}`' + indices = ["0", "2"] # use strings so that we can call join + value = True + value_type = bool + + # TODO (ni-jfitzger): reduce code duplication between this and other function + if 'attr_for_docs_example' in rep_cap_config and rep_cap_config['attr_for_docs_example']: + attr_for_example = rep_cap_config['attr_for_docs_example'] + if 'attr_type_for_docs_example' in rep_cap_config and rep_cap_config['attr_type_for_docs_example']: + attr_type_for_example = rep_cap_config['attr_type_for_docs_example'] + if attr_type_for_example == 'property': + class_attr_ref = f':py:attr:`{attr_for_example}`' + elif attr_type_for_example == 'method': + class_attr_ref = f':py:meth:`{attr_for_example}`' + if 'string_indices_for_docs_example' in rep_cap_config: + indices = [repr(index) for index in rep_cap_config['string_indices_for_docs_example']] + if 'value_for_docs_example' in rep_cap_config: + value = rep_cap_config['value_for_docs_example'] + value_type = type(value) + if 'value_type_for_docs_example' in rep_cap_config: + value_type = rep_cap_config['value_type_for_docs_example'] + if not value_type == 'enum' and isinstance(value, str): + value = repr(value) + + explanation_value = f':python:`{value}`' + if value_type == 'enum': + explanation_value = f':py:data:`~{value}`' + + if attr_type_for_example == "property": + snippet = f'session.{rep_cap_name}[{", ".join(indices)}].{attr_for_example} = {value}' + explanation = f"sets {class_attr_ref} to {explanation_value} for {rep_cap_name} {', '.join(indices)}." + elif attr_type_for_example == "method": + if value is None: + snippet = f'session.{rep_cap_name}[{", ".join(indices)}].{attr_for_example}()' + explanation = f"calls {class_attr_ref} for {rep_cap_name} {', '.join(indices)}." + else: + snippet = f'session.{rep_cap_name}[{", ".join(indices)}].{attr_for_example}({value})' + explanation = f"calls {class_attr_ref} with {explanation_value} for {rep_cap_name} {', '.join(indices)}." + else: + raise ValueError(f"Ilegal value {attr_type_for_example} in {repr(rep_cap_config)}.") + return snippet, explanation + + def get_rst_header_snippet(t, header_level='='): '''Get rst formatted heading''' ret_val = t + '\n' diff --git a/build/templates/rep_caps.rst.mako b/build/templates/rep_caps.rst.mako index 2d21d4ff4d..b98599f889 100644 --- a/build/templates/rep_caps.rst.mako +++ b/build/templates/rep_caps.rst.mako @@ -30,14 +30,20 @@ name = rep_cap['python_name'] % endfor Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be an integer, a string, a list, a tuple, or slice (range). + The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. + The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` + for those that don't support integers. + + The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. % for rep_cap in config['repeated_capabilities']: <% name = rep_cap['python_name'] -prefix = rep_cap['prefix'] + +single_index_snippet, single_index_explanation = helper.get_repeated_capability_single_index_python_example(rep_cap) +tuple_index_snippet, tuple_index_explanation = helper.get_repeated_capability_tuple_index_python_example(rep_cap) + %>\ ${helper.get_rst_header_snippet(name, '-')} @@ -45,19 +51,15 @@ ${helper.get_rst_header_snippet(name, '-')} .. code:: python - session.${name}[0].channel_enabled = True + ${single_index_snippet} - sets :py:attr:`channel_enabled` to :python:`True` for ${name} 0. + ${single_index_explanation} .. code:: python - session.${name}[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for ${name} 0, 1, 2. + ${tuple_index_snippet} - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + ${tuple_index_explanation} % endfor diff --git a/build/unit_tests/test_documentation_helper.py b/build/unit_tests/test_documentation_helper.py index f87abb97ee..85fff3c052 100644 --- a/build/unit_tests/test_documentation_helper.py +++ b/build/unit_tests/test_documentation_helper.py @@ -727,3 +727,109 @@ def test_add_notes_re_links(): assert attr_note_text in local_config['functions']['MakeAFoo']['parameters'][1]['documentation']['note'] assert enum_note_text in local_config['functions']['MakeAFoo']['parameters'][1]['documentation']['note'] + +def test_get_repeated_capability_single_index_python_example(): + basic_rep_cap = {'prefix': '', 'python_name': 'channels'} + basic_snippet = 'session.channels[0].channel_enabled = True' + basic_explanation = 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0.' + assert (basic_snippet, basic_explanation) == get_repeated_capability_single_index_python_example(basic_rep_cap) + + property_with_string_val_rep_cap = { + 'attr_for_docs_example': 'exported_pattern_opcode_event_output_terminal', + 'attr_type_for_docs_example': 'property', + 'prefix': 'patternOpcodeEvent', + 'python_name': 'pattern_opcode_events', + 'value_for_docs_example': '/Dev1/PXI_Trig0', + } + property_with_string_val_snippet = "session.pattern_opcode_events[0].exported_pattern_opcode_event_output_terminal = '/Dev1/PXI_Trig0'" + property_with_string_val_explanation = "sets :py:attr:`exported_pattern_opcode_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for pattern_opcode_events 0." + assert (property_with_string_val_snippet, property_with_string_val_explanation) == get_repeated_capability_single_index_python_example(property_with_string_val_rep_cap) + + string_indices_with_numerical_val_rep_cap = { + 'attr_for_docs_example': 'vil', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'pins', + 'string_indices_for_docs_example': ["PinA", "PinB", "CPin"], + 'value_for_docs_example': 2, + } + string_indices_with_numerical_val_snippet = "session.pins['PinA'].vil = 2" + string_indices_with_numerical_val_explanation = "sets :py:attr:`vil` to :python:`2` for pins 'PinA'." + assert (string_indices_with_numerical_val_snippet, string_indices_with_numerical_val_explanation) == get_repeated_capability_single_index_python_example(string_indices_with_numerical_val_rep_cap) + + method_no_val_rep_cap = { + 'attr_for_docs_example': 'disable_sites', + 'attr_type_for_docs_example': 'method', + 'prefix': 'site', + 'python_name': 'sites', + 'value_for_docs_example': None, + } + method_no_val_snippet = "session.sites[0].disable_sites()" + method_no_val_explanation = "calls :py:meth:`disable_sites` for sites 0." + assert (method_no_val_snippet, method_no_val_explanation) == get_repeated_capability_single_index_python_example(method_no_val_rep_cap) + + enum_val_rep_cap = { + 'attr_for_docs_example': 'conditional_jump_trigger_type', + 'attr_type_for_docs_example': 'property', + 'prefix': 'conditionalJumpTrigger', + 'python_name': 'conditional_jump_triggers', + 'value_for_docs_example': 'nidigital.TriggerType.DIGITAL_EDGE', + 'value_type_for_docs_example': 'enum', + } + enum_val_snippet = "session.conditional_jump_triggers[0].conditional_jump_trigger_type = nidigital.TriggerType.DIGITAL_EDGE" + enum_val_explanation = "sets :py:attr:`conditional_jump_trigger_type` to :py:data:`~nidigital.TriggerType.DIGITAL_EDGE` for conditional_jump_triggers 0." + assert (enum_val_snippet, enum_val_explanation) == get_repeated_capability_single_index_python_example(enum_val_rep_cap) + + +def test_get_repeated_capability_tuple_index_python_example(): + basic_rep_cap = {'prefix': '', 'python_name': 'channels'} + basic_snippet = 'session.channels[0, 2].channel_enabled = True' + basic_explanation = 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 2.' + assert (basic_snippet, basic_explanation) == get_repeated_capability_tuple_index_python_example(basic_rep_cap) + + property_with_string_val_rep_cap = { + 'attr_for_docs_example': 'exported_pattern_opcode_event_output_terminal', + 'attr_type_for_docs_example': 'property', + 'prefix': 'patternOpcodeEvent', + 'python_name': 'pattern_opcode_events', + 'value_for_docs_example': '/Dev1/PXI_Trig0', + } + property_with_string_val_snippet = "session.pattern_opcode_events[0, 2].exported_pattern_opcode_event_output_terminal = '/Dev1/PXI_Trig0'" + property_with_string_val_explanation = "sets :py:attr:`exported_pattern_opcode_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for pattern_opcode_events 0, 2." + assert (property_with_string_val_snippet, property_with_string_val_explanation) == get_repeated_capability_tuple_index_python_example(property_with_string_val_rep_cap) + + string_indices_with_numerical_val_rep_cap = { + 'attr_for_docs_example': 'vil', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'pins', + 'string_indices_for_docs_example': ["PinA", "PinB", "CPin"], + 'value_for_docs_example': 2, + } + string_indices_with_numerical_val_snippet = "session.pins['PinA', 'PinB', 'CPin'].vil = 2" + string_indices_with_numerical_val_explanation = "sets :py:attr:`vil` to :python:`2` for pins 'PinA', 'PinB', 'CPin'." + assert (string_indices_with_numerical_val_snippet, string_indices_with_numerical_val_explanation) == get_repeated_capability_tuple_index_python_example(string_indices_with_numerical_val_rep_cap) + + method_no_val_rep_cap = { + 'attr_for_docs_example': 'disable_sites', + 'attr_type_for_docs_example': 'method', + 'prefix': 'site', + 'python_name': 'sites', + 'value_for_docs_example': None, + } + method_no_val_snippet = "session.sites[0, 2].disable_sites()" + method_no_val_explanation = "calls :py:meth:`disable_sites` for sites 0, 2." + assert (method_no_val_snippet, method_no_val_explanation) == get_repeated_capability_tuple_index_python_example(method_no_val_rep_cap) + + enum_val_rep_cap = { + 'attr_for_docs_example': 'conditional_jump_trigger_type', + 'attr_type_for_docs_example': 'property', + 'prefix': 'conditionalJumpTrigger', + 'python_name': 'conditional_jump_triggers', + 'value_for_docs_example': 'nidigital.TriggerType.DIGITAL_EDGE', + 'value_type_for_docs_example': 'enum', + } + enum_val_snippet = "session.conditional_jump_triggers[0, 2].conditional_jump_trigger_type = nidigital.TriggerType.DIGITAL_EDGE" + enum_val_explanation = "sets :py:attr:`conditional_jump_trigger_type` to :py:data:`~nidigital.TriggerType.DIGITAL_EDGE` for conditional_jump_triggers 0, 2." + assert (enum_val_snippet, enum_val_explanation) == get_repeated_capability_tuple_index_python_example(enum_val_rep_cap) + diff --git a/docs/nidcpower/rep_caps.rst b/docs/nidcpower/rep_caps.rst index cb8b9ea18c..fb63d72de9 100644 --- a/docs/nidcpower/rep_caps.rst +++ b/docs/nidcpower/rep_caps.rst @@ -19,9 +19,12 @@ Repeated Capabilities #. instruments_ Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be an integer, a string, a list, a tuple, or slice (range). + The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. + The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` + for those that don't support integers. + + The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. channels -------- @@ -36,13 +39,9 @@ channels .. code:: python - session.channels[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1, 2. + session.channels[0, 2].channel_enabled = True - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 2. instruments ----------- @@ -57,12 +56,8 @@ instruments .. code:: python - session.instruments[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for instruments 0, 1, 2. + session.instruments[0, 2].channel_enabled = True - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`channel_enabled` to :python:`True` for instruments 0, 2. diff --git a/docs/nidigital/rep_caps.rst b/docs/nidigital/rep_caps.rst index f952263389..f31b94baf8 100644 --- a/docs/nidigital/rep_caps.rst +++ b/docs/nidigital/rep_caps.rst @@ -25,9 +25,12 @@ Repeated Capabilities #. rio_triggers_ Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be an integer, a string, a list, a tuple, or slice (range). + The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. + The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` + for those that don't support integers. + + The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. channels -------- @@ -36,19 +39,15 @@ channels .. code:: python - session.channels[0].channel_enabled = True + session.channels[0].vil = 2 - sets :py:attr:`channel_enabled` to :python:`True` for channels 0. + sets :py:attr:`vil` to :python:`2` for channels 0. .. code:: python - session.channels[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1, 2. + session.channels[0, 2].vil = 2 - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`vil` to :python:`2` for channels 0, 2. pins ---- @@ -57,19 +56,15 @@ pins .. code:: python - session.pins[0].channel_enabled = True + session.pins['PinA'].vil = 2 - sets :py:attr:`channel_enabled` to :python:`True` for pins 0. + sets :py:attr:`vil` to :python:`2` for pins 'PinA'. .. code:: python - session.pins[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for pins 0, 1, 2. + session.pins['PinA', 'PinB', 'CPin'].vil = 2 - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`vil` to :python:`2` for pins 'PinA', 'PinB', 'CPin'. instruments ----------- @@ -78,19 +73,15 @@ instruments .. code:: python - session.instruments[0].channel_enabled = True + session.instruments['Dev1'].timing_absolute_delay = 5e-09 - sets :py:attr:`channel_enabled` to :python:`True` for instruments 0. + sets :py:attr:`timing_absolute_delay` to :python:`5e-09` for instruments 'Dev1'. .. code:: python - session.instruments[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for instruments 0, 1, 2. + session.instruments['Dev1', 'Dev2', '3rdDevice'].timing_absolute_delay = 5e-09 - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`timing_absolute_delay` to :python:`5e-09` for instruments 'Dev1', 'Dev2', '3rdDevice'. pattern_opcode_events --------------------- @@ -99,19 +90,15 @@ pattern_opcode_events .. code:: python - session.pattern_opcode_events[0].channel_enabled = True + session.pattern_opcode_events[0].exported_pattern_opcode_event_output_terminal = '/Dev1/PXI_Trig0' - sets :py:attr:`channel_enabled` to :python:`True` for pattern_opcode_events 0. + sets :py:attr:`exported_pattern_opcode_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for pattern_opcode_events 0. .. code:: python - session.pattern_opcode_events[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for pattern_opcode_events 0, 1, 2. + session.pattern_opcode_events[0, 2].exported_pattern_opcode_event_output_terminal = '/Dev1/PXI_Trig0' - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`exported_pattern_opcode_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for pattern_opcode_events 0, 2. conditional_jump_triggers ------------------------- @@ -120,19 +107,15 @@ conditional_jump_triggers .. code:: python - session.conditional_jump_triggers[0].channel_enabled = True + session.conditional_jump_triggers[0].conditional_jump_trigger_type = nidigital.TriggerType.DIGITAL_EDGE - sets :py:attr:`channel_enabled` to :python:`True` for conditional_jump_triggers 0. + sets :py:attr:`conditional_jump_trigger_type` to :py:data:`~nidigital.TriggerType.DIGITAL_EDGE` for conditional_jump_triggers 0. .. code:: python - session.conditional_jump_triggers[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for conditional_jump_triggers 0, 1, 2. + session.conditional_jump_triggers[0, 2].conditional_jump_trigger_type = nidigital.TriggerType.DIGITAL_EDGE - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`conditional_jump_trigger_type` to :py:data:`~nidigital.TriggerType.DIGITAL_EDGE` for conditional_jump_triggers 0, 2. sites ----- @@ -141,19 +124,15 @@ sites .. code:: python - session.sites[0].channel_enabled = True + session.sites[0].disable_sites() - sets :py:attr:`channel_enabled` to :python:`True` for sites 0. + calls :py:meth:`disable_sites` for sites 0. .. code:: python - session.sites[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for sites 0, 1, 2. + session.sites[0, 2].disable_sites() - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + calls :py:meth:`disable_sites` for sites 0, 2. rio_events ---------- @@ -162,19 +141,15 @@ rio_events .. code:: python - session.rio_events[0].channel_enabled = True + session.rio_events[0].exported_rio_event_output_terminal = '/Dev1/PXI_Trig0' - sets :py:attr:`channel_enabled` to :python:`True` for rio_events 0. + sets :py:attr:`exported_rio_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for rio_events 0. .. code:: python - session.rio_events[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for rio_events 0, 1, 2. + session.rio_events[0, 2].exported_rio_event_output_terminal = '/Dev1/PXI_Trig0' - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`exported_rio_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for rio_events 0, 2. rio_triggers ------------ @@ -183,18 +158,14 @@ rio_triggers .. code:: python - session.rio_triggers[0].channel_enabled = True + session.rio_triggers[0].rio_trigger_type = nidigital.TriggerType.DIGITAL_EDGE - sets :py:attr:`channel_enabled` to :python:`True` for rio_triggers 0. + sets :py:attr:`rio_trigger_type` to :py:data:`~nidigital.TriggerType.DIGITAL_EDGE` for rio_triggers 0. .. code:: python - session.rio_triggers[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for rio_triggers 0, 1, 2. + session.rio_triggers[0, 2].rio_trigger_type = nidigital.TriggerType.DIGITAL_EDGE - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`rio_trigger_type` to :py:data:`~nidigital.TriggerType.DIGITAL_EDGE` for rio_triggers 0, 2. diff --git a/docs/nifgen/rep_caps.rst b/docs/nifgen/rep_caps.rst index e4810ff469..59a1189e83 100644 --- a/docs/nifgen/rep_caps.rst +++ b/docs/nifgen/rep_caps.rst @@ -21,9 +21,12 @@ Repeated Capabilities #. data_markers_ Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be an integer, a string, a list, a tuple, or slice (range). + The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. + The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` + for those that don't support integers. + + The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. channels -------- @@ -38,13 +41,9 @@ channels .. code:: python - session.channels[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1, 2. + session.channels[0, 2].channel_enabled = True - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 2. script_triggers --------------- @@ -59,13 +58,9 @@ script_triggers .. code:: python - session.script_triggers[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for script_triggers 0, 1, 2. + session.script_triggers[0, 2].channel_enabled = True - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`channel_enabled` to :python:`True` for script_triggers 0, 2. markers ------- @@ -80,13 +75,9 @@ markers .. code:: python - session.markers[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for markers 0, 1, 2. + session.markers[0, 2].channel_enabled = True - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`channel_enabled` to :python:`True` for markers 0, 2. data_markers ------------ @@ -101,12 +92,8 @@ data_markers .. code:: python - session.data_markers[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for data_markers 0, 1, 2. + session.data_markers[0, 2].channel_enabled = True - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`channel_enabled` to :python:`True` for data_markers 0, 2. diff --git a/docs/niscope/rep_caps.rst b/docs/niscope/rep_caps.rst index 01caa24a52..69f0f26af4 100644 --- a/docs/niscope/rep_caps.rst +++ b/docs/niscope/rep_caps.rst @@ -19,9 +19,12 @@ Repeated Capabilities #. instruments_ Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be an integer, a string, a list, a tuple, or slice (range). + The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. + The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` + for those that don't support integers. + + The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. channels -------- @@ -36,13 +39,9 @@ channels .. code:: python - session.channels[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1, 2. + session.channels[0, 2].channel_enabled = True - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 2. instruments ----------- @@ -57,12 +56,8 @@ instruments .. code:: python - session.instruments[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for instruments 0, 1, 2. + session.instruments[0, 2].channel_enabled = True - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`channel_enabled` to :python:`True` for instruments 0, 2. diff --git a/docs/niswitch/rep_caps.rst b/docs/niswitch/rep_caps.rst index a6189b9b35..8cf95a4896 100644 --- a/docs/niswitch/rep_caps.rst +++ b/docs/niswitch/rep_caps.rst @@ -18,9 +18,12 @@ Repeated Capabilities #. channels_ Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be an integer, a string, a list, a tuple, or slice (range). + The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing repeated capabilities is with an integer :python:`[0]` or range :python:`[0:2]`. + The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` + for those that don't support integers. + + The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. channels -------- @@ -35,12 +38,8 @@ channels .. code:: python - session.channels[0:2].channel_enabled = True - - sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1, 2. + session.channels[0, 2].channel_enabled = True - Note that :py:attr:`channel_enabled` is only used as an example and is not necessarily a property which - supports this repeated capability. See documentation for individual properties and methods to - learn what repeated capabilites they support, if any. + sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 2. diff --git a/src/nidigital/metadata/config_addon.py b/src/nidigital/metadata/config_addon.py index 53400d192a..1f627ff715 100644 --- a/src/nidigital/metadata/config_addon.py +++ b/src/nidigital/metadata/config_addon.py @@ -10,4 +10,66 @@ 'python_name': 'HistoryRAMCycleInformation' } ], + 'repeated_capabilities': [ + { + 'attr_for_docs_example': 'vil', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'channels', + 'value_for_docs_example': 2, + }, + { + 'attr_for_docs_example': 'vil', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'pins', + 'string_indices_for_docs_example': ["PinA", "PinB", "CPin"], + 'value_for_docs_example': 2, + }, + { + 'attr_for_docs_example': 'timing_absolute_delay', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'instruments', + 'string_indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], + 'value_for_docs_example': 5e-09, + }, + { + 'attr_for_docs_example': 'exported_pattern_opcode_event_output_terminal', + 'attr_type_for_docs_example': 'property', + 'prefix': 'patternOpcodeEvent', + 'python_name': 'pattern_opcode_events', + 'value_for_docs_example': '/Dev1/PXI_Trig0', + }, + { + 'attr_for_docs_example': 'conditional_jump_trigger_type', + 'attr_type_for_docs_example': 'property', + 'prefix': 'conditionalJumpTrigger', + 'python_name': 'conditional_jump_triggers', + 'value_for_docs_example': 'nidigital.TriggerType.DIGITAL_EDGE', + 'value_type_for_docs_example': 'enum', + }, + { + 'attr_for_docs_example': 'disable_sites', + 'attr_type_for_docs_example': 'method', + 'prefix': 'site', + 'python_name': 'sites', + 'value_for_docs_example': None, + }, + { + 'attr_for_docs_example': 'exported_rio_event_output_terminal', + 'attr_type_for_docs_example': 'property', + 'prefix': 'RIOEvent', + 'python_name': 'rio_events', + 'value_for_docs_example': '/Dev1/PXI_Trig0', + }, + { + 'attr_for_docs_example': 'rio_trigger_type', + 'attr_type_for_docs_example': 'property', + 'prefix': 'RIOTrigger', + 'python_name': 'rio_triggers', + 'value_for_docs_example': 'nidigital.TriggerType.DIGITAL_EDGE', + 'value_type_for_docs_example': 'enum', + } + ], } From 1cc9cf4c16d68ed81a092bdf1d1695f2413158b9 Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:34:49 -0500 Subject: [PATCH 08/18] generate correct rep cap documentation for nidcpower --- build/helper/documentation_helper.py | 22 ++++++++++------- build/unit_tests/test_documentation_helper.py | 24 +++++++++++++++++++ docs/nidcpower/rep_caps.rst | 16 ++++++------- src/nidcpower/metadata/config_addon.py | 18 ++++++++++++++ 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/build/helper/documentation_helper.py b/build/helper/documentation_helper.py index 2398b85103..5abc6a53bf 100644 --- a/build/helper/documentation_helper.py +++ b/build/helper/documentation_helper.py @@ -60,8 +60,6 @@ def get_repeated_capability_single_index_python_example(rep_cap_config): '''Returns a python code snippet and explanation for example usage of a repeated capability.''' rep_cap_name = rep_cap_config['python_name'] - # TODO(ni-jfitzger): Handle read-only properties (snippet to print the value) - # defaults attr_for_example = 'channel_enabled' attr_type_for_example = 'property' @@ -93,8 +91,12 @@ def get_repeated_capability_single_index_python_example(rep_cap_config): explanation_value = f':py:data:`~{value}`' if attr_type_for_example == "property": - snippet = f'session.{rep_cap_name}[{index}].{attr_for_example} = {value}' - explanation = f"sets {class_attr_ref} to {explanation_value} for {rep_cap_name} {index}." + if value is None: + snippet = f'print(session.{rep_cap_name}[{index}].{attr_for_example})' + explanation = f"prints {class_attr_ref} for {rep_cap_name} {index}." + else: + snippet = f'session.{rep_cap_name}[{index}].{attr_for_example} = {value}' + explanation = f"sets {class_attr_ref} to {explanation_value} for {rep_cap_name} {index}." elif attr_type_for_example == "method": if value is None: snippet = f'session.{rep_cap_name}[{index}].{attr_for_example}()' @@ -111,8 +113,6 @@ def get_repeated_capability_tuple_index_python_example(rep_cap_config): '''Returns a python code snippet and explanation for example usage of a repeated capability.''' rep_cap_name = rep_cap_config['python_name'] - # TODO(ni-jfitzger): Handle read-only properties (snippet to print the value) - # defaults attr_for_example = 'channel_enabled' attr_type_for_example = 'property' @@ -121,7 +121,7 @@ def get_repeated_capability_tuple_index_python_example(rep_cap_config): value = True value_type = bool - # TODO (ni-jfitzger): reduce code duplication between this and other function + # TODO(ni-jfitzger): reduce code duplication between this and other function if 'attr_for_docs_example' in rep_cap_config and rep_cap_config['attr_for_docs_example']: attr_for_example = rep_cap_config['attr_for_docs_example'] if 'attr_type_for_docs_example' in rep_cap_config and rep_cap_config['attr_type_for_docs_example']: @@ -145,8 +145,12 @@ def get_repeated_capability_tuple_index_python_example(rep_cap_config): explanation_value = f':py:data:`~{value}`' if attr_type_for_example == "property": - snippet = f'session.{rep_cap_name}[{", ".join(indices)}].{attr_for_example} = {value}' - explanation = f"sets {class_attr_ref} to {explanation_value} for {rep_cap_name} {', '.join(indices)}." + if value is None: + snippet = f'print(session.{rep_cap_name}[{", ".join(indices)}].{attr_for_example})' + explanation = f"prints {class_attr_ref} for {rep_cap_name} {', '.join(indices)} or errors if the value is not the same for all." + else: + snippet = f'session.{rep_cap_name}[{", ".join(indices)}].{attr_for_example} = {value}' + explanation = f"sets {class_attr_ref} to {explanation_value} for {rep_cap_name} {', '.join(indices)}." elif attr_type_for_example == "method": if value is None: snippet = f'session.{rep_cap_name}[{", ".join(indices)}].{attr_for_example}()' diff --git a/build/unit_tests/test_documentation_helper.py b/build/unit_tests/test_documentation_helper.py index 85fff3c052..9e8250ca55 100644 --- a/build/unit_tests/test_documentation_helper.py +++ b/build/unit_tests/test_documentation_helper.py @@ -768,6 +768,18 @@ def test_get_repeated_capability_single_index_python_example(): method_no_val_explanation = "calls :py:meth:`disable_sites` for sites 0." assert (method_no_val_snippet, method_no_val_explanation) == get_repeated_capability_single_index_python_example(method_no_val_rep_cap) + property_no_val_rep_cap = { + 'attr_for_docs_example': 'serial_number', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'instruments', + 'string_indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], + 'value_for_docs_example': None, + } + property_no_val_snippet = "print(session.instruments['Dev1'].serial_number)" + property_no_val_explanation = "prints :py:attr:`serial_number` for instruments 'Dev1'." + assert (property_no_val_snippet, property_no_val_explanation) == get_repeated_capability_single_index_python_example(property_no_val_rep_cap) + enum_val_rep_cap = { 'attr_for_docs_example': 'conditional_jump_trigger_type', 'attr_type_for_docs_example': 'property', @@ -821,6 +833,18 @@ def test_get_repeated_capability_tuple_index_python_example(): method_no_val_explanation = "calls :py:meth:`disable_sites` for sites 0, 2." assert (method_no_val_snippet, method_no_val_explanation) == get_repeated_capability_tuple_index_python_example(method_no_val_rep_cap) + property_no_val_rep_cap = { + 'attr_for_docs_example': 'serial_number', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'instruments', + 'string_indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], + 'value_for_docs_example': None, + } + property_no_val_snippet = "print(session.instruments['Dev1', 'Dev2', '3rdDevice'].serial_number)" + property_no_val_explanation = "prints :py:attr:`serial_number` for instruments 'Dev1', 'Dev2', '3rdDevice' or errors if the value is not the same for all." + assert (property_no_val_snippet, property_no_val_explanation) == get_repeated_capability_tuple_index_python_example(property_no_val_rep_cap) + enum_val_rep_cap = { 'attr_for_docs_example': 'conditional_jump_trigger_type', 'attr_type_for_docs_example': 'property', diff --git a/docs/nidcpower/rep_caps.rst b/docs/nidcpower/rep_caps.rst index fb63d72de9..d9520d1918 100644 --- a/docs/nidcpower/rep_caps.rst +++ b/docs/nidcpower/rep_caps.rst @@ -33,15 +33,15 @@ channels .. code:: python - session.channels[0].channel_enabled = True + session.channels[0].output_function = nidcpower.OutputFunction.DC_CURRENT - sets :py:attr:`channel_enabled` to :python:`True` for channels 0. + sets :py:attr:`output_function` to :py:data:`~nidcpower.OutputFunction.DC_CURRENT` for channels 0. .. code:: python - session.channels[0, 2].channel_enabled = True + session.channels[0, 2].output_function = nidcpower.OutputFunction.DC_CURRENT - sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 2. + sets :py:attr:`output_function` to :py:data:`~nidcpower.OutputFunction.DC_CURRENT` for channels 0, 2. instruments ----------- @@ -50,14 +50,14 @@ instruments .. code:: python - session.instruments[0].channel_enabled = True + print(session.instruments['Dev1'].serial_number) - sets :py:attr:`channel_enabled` to :python:`True` for instruments 0. + prints :py:attr:`serial_number` for instruments 'Dev1'. .. code:: python - session.instruments[0, 2].channel_enabled = True + print(session.instruments['Dev1', 'Dev2', '3rdDevice'].serial_number) - sets :py:attr:`channel_enabled` to :python:`True` for instruments 0, 2. + prints :py:attr:`serial_number` for instruments 'Dev1', 'Dev2', '3rdDevice' or errors if the value is not the same for all. diff --git a/src/nidcpower/metadata/config_addon.py b/src/nidcpower/metadata/config_addon.py index c8631d95aa..5e3553d48d 100644 --- a/src/nidcpower/metadata/config_addon.py +++ b/src/nidcpower/metadata/config_addon.py @@ -3,4 +3,22 @@ 'module_version': '1.4.6.dev0', 'latest_runtime_version_tested_against': '2023 Q2', 'initial_release_year': '2017', + 'repeated_capabilities': [ + { + 'attr_for_docs_example': 'output_function', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'channels', + 'value_for_docs_example': 'nidcpower.OutputFunction.DC_CURRENT', + 'value_type_for_docs_example': 'enum', + }, + { + 'attr_for_docs_example': 'serial_number', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'instruments', + 'string_indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], + 'value_for_docs_example': None, + } + ], } From ce93c561699599b7b659e4f09e82a1e0b084355f Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:32:13 -0500 Subject: [PATCH 09/18] generate correct rep cap documentation for nifgen --- build/helper/documentation_helper.py | 44 +++++++++++-------- build/unit_tests/test_documentation_helper.py | 18 ++++++++ docs/nifgen/rep_caps.rst | 32 +++++++------- src/nifgen/metadata/config_addon.py | 32 ++++++++++++++ 4 files changed, 92 insertions(+), 34 deletions(-) diff --git a/build/helper/documentation_helper.py b/build/helper/documentation_helper.py index 5abc6a53bf..855e466398 100644 --- a/build/helper/documentation_helper.py +++ b/build/helper/documentation_helper.py @@ -76,15 +76,19 @@ def get_repeated_capability_single_index_python_example(rep_cap_config): class_attr_ref = f':py:attr:`{attr_for_example}`' elif attr_type_for_example == 'method': class_attr_ref = f':py:meth:`{attr_for_example}`' - if 'string_indices_for_docs_example' in rep_cap_config: - index = repr(rep_cap_config["string_indices_for_docs_example"][0]) - if 'value_for_docs_example' in rep_cap_config: - value = rep_cap_config['value_for_docs_example'] - value_type = type(value) - if 'value_type_for_docs_example' in rep_cap_config: - value_type = rep_cap_config['value_type_for_docs_example'] - if not value_type == 'enum' and isinstance(value, str): - value = repr(value) + + if 'indices_for_docs_example' in rep_cap_config: + index = rep_cap_config["indices_for_docs_example"][0] + elif 'string_indices_for_docs_example' in rep_cap_config: + index = repr(rep_cap_config["string_indices_for_docs_example"][0]) + + if 'value_for_docs_example' in rep_cap_config: + value = rep_cap_config['value_for_docs_example'] + value_type = type(value) + if 'value_type_for_docs_example' in rep_cap_config: + value_type = rep_cap_config['value_type_for_docs_example'] + if not value_type == 'enum' and isinstance(value, str): + value = repr(value) explanation_value = f':python:`{value}`' if value_type == 'enum': @@ -130,15 +134,19 @@ def get_repeated_capability_tuple_index_python_example(rep_cap_config): class_attr_ref = f':py:attr:`{attr_for_example}`' elif attr_type_for_example == 'method': class_attr_ref = f':py:meth:`{attr_for_example}`' - if 'string_indices_for_docs_example' in rep_cap_config: - indices = [repr(index) for index in rep_cap_config['string_indices_for_docs_example']] - if 'value_for_docs_example' in rep_cap_config: - value = rep_cap_config['value_for_docs_example'] - value_type = type(value) - if 'value_type_for_docs_example' in rep_cap_config: - value_type = rep_cap_config['value_type_for_docs_example'] - if not value_type == 'enum' and isinstance(value, str): - value = repr(value) + + if 'indices_for_docs_example' in rep_cap_config: + indices = [repr(index) for index in rep_cap_config["indices_for_docs_example"]] + elif 'string_indices_for_docs_example' in rep_cap_config: + indices = [repr(index) for index in rep_cap_config['string_indices_for_docs_example']] + + if 'value_for_docs_example' in rep_cap_config: + value = rep_cap_config['value_for_docs_example'] + value_type = type(value) + if 'value_type_for_docs_example' in rep_cap_config: + value_type = rep_cap_config['value_type_for_docs_example'] + if not value_type == 'enum' and isinstance(value, str): + value = repr(value) explanation_value = f':python:`{value}`' if value_type == 'enum': diff --git a/build/unit_tests/test_documentation_helper.py b/build/unit_tests/test_documentation_helper.py index 9e8250ca55..6b8d657335 100644 --- a/build/unit_tests/test_documentation_helper.py +++ b/build/unit_tests/test_documentation_helper.py @@ -745,6 +745,15 @@ def test_get_repeated_capability_single_index_python_example(): property_with_string_val_explanation = "sets :py:attr:`exported_pattern_opcode_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for pattern_opcode_events 0." assert (property_with_string_val_snippet, property_with_string_val_explanation) == get_repeated_capability_single_index_python_example(property_with_string_val_rep_cap) + custom_indices_rep_cap = { + 'indices_for_docs_example': [0, 1], + 'prefix': '', + 'python_name': 'channels', + } + custom_indices_snippet = 'session.channels[0].channel_enabled = True' + custom_indices_explanation = 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0.' + assert (custom_indices_snippet, custom_indices_explanation) == get_repeated_capability_single_index_python_example(custom_indices_rep_cap) + string_indices_with_numerical_val_rep_cap = { 'attr_for_docs_example': 'vil', 'attr_type_for_docs_example': 'property', @@ -810,6 +819,15 @@ def test_get_repeated_capability_tuple_index_python_example(): property_with_string_val_explanation = "sets :py:attr:`exported_pattern_opcode_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for pattern_opcode_events 0, 2." assert (property_with_string_val_snippet, property_with_string_val_explanation) == get_repeated_capability_tuple_index_python_example(property_with_string_val_rep_cap) + custom_indices_rep_cap = { + 'indices_for_docs_example': [0, 1], + 'prefix': '', + 'python_name': 'channels', + } + custom_indices_snippet = 'session.channels[0, 1].channel_enabled = True' + custom_indices_explanation = 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1.' + assert (custom_indices_snippet, custom_indices_explanation) == get_repeated_capability_tuple_index_python_example(custom_indices_rep_cap) + string_indices_with_numerical_val_rep_cap = { 'attr_for_docs_example': 'vil', 'attr_type_for_docs_example': 'property', diff --git a/docs/nifgen/rep_caps.rst b/docs/nifgen/rep_caps.rst index 59a1189e83..8410374abe 100644 --- a/docs/nifgen/rep_caps.rst +++ b/docs/nifgen/rep_caps.rst @@ -35,15 +35,15 @@ channels .. code:: python - session.channels[0].channel_enabled = True + session.channels[0].func_amplitude = 0.5 - sets :py:attr:`channel_enabled` to :python:`True` for channels 0. + sets :py:attr:`func_amplitude` to :python:`0.5` for channels 0. .. code:: python - session.channels[0, 2].channel_enabled = True + session.channels[0, 1].func_amplitude = 0.5 - sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 2. + sets :py:attr:`func_amplitude` to :python:`0.5` for channels 0, 1. script_triggers --------------- @@ -52,15 +52,15 @@ script_triggers .. code:: python - session.script_triggers[0].channel_enabled = True + session.script_triggers[0].exported_script_trigger_output_terminal = '/Dev1/PXI_Trig0' - sets :py:attr:`channel_enabled` to :python:`True` for script_triggers 0. + sets :py:attr:`exported_script_trigger_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for script_triggers 0. .. code:: python - session.script_triggers[0, 2].channel_enabled = True + session.script_triggers[0, 2].exported_script_trigger_output_terminal = '/Dev1/PXI_Trig0' - sets :py:attr:`channel_enabled` to :python:`True` for script_triggers 0, 2. + sets :py:attr:`exported_script_trigger_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for script_triggers 0, 2. markers ------- @@ -69,15 +69,15 @@ markers .. code:: python - session.markers[0].channel_enabled = True + session.markers[0].marker_event_output_terminal = '/Dev1/PXI_Trig0' - sets :py:attr:`channel_enabled` to :python:`True` for markers 0. + sets :py:attr:`marker_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for markers 0. .. code:: python - session.markers[0, 2].channel_enabled = True + session.markers[0, 2].marker_event_output_terminal = '/Dev1/PXI_Trig0' - sets :py:attr:`channel_enabled` to :python:`True` for markers 0, 2. + sets :py:attr:`marker_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for markers 0, 2. data_markers ------------ @@ -86,14 +86,14 @@ data_markers .. code:: python - session.data_markers[0].channel_enabled = True + session.data_markers[0].data_marker_event_level_polarity = nifgen.DataMarkerEventLevelPolarity.LOW - sets :py:attr:`channel_enabled` to :python:`True` for data_markers 0. + sets :py:attr:`data_marker_event_level_polarity` to :py:data:`~nifgen.DataMarkerEventLevelPolarity.LOW` for data_markers 0. .. code:: python - session.data_markers[0, 2].channel_enabled = True + session.data_markers[0, 2].data_marker_event_level_polarity = nifgen.DataMarkerEventLevelPolarity.LOW - sets :py:attr:`channel_enabled` to :python:`True` for data_markers 0, 2. + sets :py:attr:`data_marker_event_level_polarity` to :py:data:`~nifgen.DataMarkerEventLevelPolarity.LOW` for data_markers 0, 2. diff --git a/src/nifgen/metadata/config_addon.py b/src/nifgen/metadata/config_addon.py index 219a685a3c..51285ea100 100644 --- a/src/nifgen/metadata/config_addon.py +++ b/src/nifgen/metadata/config_addon.py @@ -3,4 +3,36 @@ 'module_version': '1.4.6.dev0', 'latest_runtime_version_tested_against': '2023 Q1.1', 'initial_release_year': '2017', + 'repeated_capabilities': [ + { + 'attr_for_docs_example': 'func_amplitude', + 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': [0, 1], + 'prefix': '', + 'python_name': 'channels', + 'value_for_docs_example': 0.5, + }, + { + 'attr_for_docs_example': 'exported_script_trigger_output_terminal', + 'attr_type_for_docs_example': 'property', + 'prefix': 'ScriptTrigger', + 'python_name': 'script_triggers', + 'value_for_docs_example': '/Dev1/PXI_Trig0', + }, + { + 'attr_for_docs_example': 'marker_event_output_terminal', + 'attr_type_for_docs_example': 'property', + 'prefix': 'Marker', + 'python_name': 'markers', + 'value_for_docs_example': '/Dev1/PXI_Trig0', + }, + { + 'attr_for_docs_example': 'data_marker_event_level_polarity', + 'attr_type_for_docs_example': 'property', + 'prefix': 'DataMarker', + 'python_name': 'data_markers', + 'value_for_docs_example': 'nifgen.DataMarkerEventLevelPolarity.LOW', + 'value_type_for_docs_example': 'enum', + } + ], } From 8e8833cb7f7178889cc8a92e8dc318d1d4a3b26d Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:50:50 -0500 Subject: [PATCH 10/18] merge indices, string_indices fields --- build/helper/documentation_helper.py | 6 ++---- build/unit_tests/test_documentation_helper.py | 8 ++++---- src/nidcpower/metadata/config_addon.py | 2 +- src/nidigital/metadata/config_addon.py | 4 ++-- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/build/helper/documentation_helper.py b/build/helper/documentation_helper.py index 855e466398..f02b083163 100644 --- a/build/helper/documentation_helper.py +++ b/build/helper/documentation_helper.py @@ -79,8 +79,8 @@ def get_repeated_capability_single_index_python_example(rep_cap_config): if 'indices_for_docs_example' in rep_cap_config: index = rep_cap_config["indices_for_docs_example"][0] - elif 'string_indices_for_docs_example' in rep_cap_config: - index = repr(rep_cap_config["string_indices_for_docs_example"][0]) + if isinstance(index, str): + index = repr(index) if 'value_for_docs_example' in rep_cap_config: value = rep_cap_config['value_for_docs_example'] @@ -137,8 +137,6 @@ def get_repeated_capability_tuple_index_python_example(rep_cap_config): if 'indices_for_docs_example' in rep_cap_config: indices = [repr(index) for index in rep_cap_config["indices_for_docs_example"]] - elif 'string_indices_for_docs_example' in rep_cap_config: - indices = [repr(index) for index in rep_cap_config['string_indices_for_docs_example']] if 'value_for_docs_example' in rep_cap_config: value = rep_cap_config['value_for_docs_example'] diff --git a/build/unit_tests/test_documentation_helper.py b/build/unit_tests/test_documentation_helper.py index 6b8d657335..12a177ae0b 100644 --- a/build/unit_tests/test_documentation_helper.py +++ b/build/unit_tests/test_documentation_helper.py @@ -757,9 +757,9 @@ def test_get_repeated_capability_single_index_python_example(): string_indices_with_numerical_val_rep_cap = { 'attr_for_docs_example': 'vil', 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["PinA", "PinB", "CPin"], 'prefix': '', 'python_name': 'pins', - 'string_indices_for_docs_example': ["PinA", "PinB", "CPin"], 'value_for_docs_example': 2, } string_indices_with_numerical_val_snippet = "session.pins['PinA'].vil = 2" @@ -780,9 +780,9 @@ def test_get_repeated_capability_single_index_python_example(): property_no_val_rep_cap = { 'attr_for_docs_example': 'serial_number', 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], 'prefix': '', 'python_name': 'instruments', - 'string_indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], 'value_for_docs_example': None, } property_no_val_snippet = "print(session.instruments['Dev1'].serial_number)" @@ -831,9 +831,9 @@ def test_get_repeated_capability_tuple_index_python_example(): string_indices_with_numerical_val_rep_cap = { 'attr_for_docs_example': 'vil', 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["PinA", "PinB", "CPin"], 'prefix': '', 'python_name': 'pins', - 'string_indices_for_docs_example': ["PinA", "PinB", "CPin"], 'value_for_docs_example': 2, } string_indices_with_numerical_val_snippet = "session.pins['PinA', 'PinB', 'CPin'].vil = 2" @@ -854,9 +854,9 @@ def test_get_repeated_capability_tuple_index_python_example(): property_no_val_rep_cap = { 'attr_for_docs_example': 'serial_number', 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], 'prefix': '', 'python_name': 'instruments', - 'string_indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], 'value_for_docs_example': None, } property_no_val_snippet = "print(session.instruments['Dev1', 'Dev2', '3rdDevice'].serial_number)" diff --git a/src/nidcpower/metadata/config_addon.py b/src/nidcpower/metadata/config_addon.py index 5e3553d48d..048118a438 100644 --- a/src/nidcpower/metadata/config_addon.py +++ b/src/nidcpower/metadata/config_addon.py @@ -15,9 +15,9 @@ { 'attr_for_docs_example': 'serial_number', 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], 'prefix': '', 'python_name': 'instruments', - 'string_indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], 'value_for_docs_example': None, } ], diff --git a/src/nidigital/metadata/config_addon.py b/src/nidigital/metadata/config_addon.py index 1f627ff715..8b5969c0b4 100644 --- a/src/nidigital/metadata/config_addon.py +++ b/src/nidigital/metadata/config_addon.py @@ -21,17 +21,17 @@ { 'attr_for_docs_example': 'vil', 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["PinA", "PinB", "CPin"], 'prefix': '', 'python_name': 'pins', - 'string_indices_for_docs_example': ["PinA", "PinB", "CPin"], 'value_for_docs_example': 2, }, { 'attr_for_docs_example': 'timing_absolute_delay', 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], 'prefix': '', 'python_name': 'instruments', - 'string_indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], 'value_for_docs_example': 5e-09, }, { From cf13613fa4a15faf150effd59850151735abb368 Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Tue, 11 Jul 2023 13:01:10 -0500 Subject: [PATCH 11/18] genereate correct rep cap documentation for niscope --- docs/niscope/rep_caps.rst | 8 ++++---- src/niscope/metadata/config_addon.py | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/docs/niscope/rep_caps.rst b/docs/niscope/rep_caps.rst index 69f0f26af4..188390abc2 100644 --- a/docs/niscope/rep_caps.rst +++ b/docs/niscope/rep_caps.rst @@ -50,14 +50,14 @@ instruments .. code:: python - session.instruments[0].channel_enabled = True + print(session.instruments['Dev1'].serial_number) - sets :py:attr:`channel_enabled` to :python:`True` for instruments 0. + prints :py:attr:`serial_number` for instruments 'Dev1'. .. code:: python - session.instruments[0, 2].channel_enabled = True + print(session.instruments['Dev1', 'Dev2', '3rdDevice'].serial_number) - sets :py:attr:`channel_enabled` to :python:`True` for instruments 0, 2. + prints :py:attr:`serial_number` for instruments 'Dev1', 'Dev2', '3rdDevice' or errors if the value is not the same for all. diff --git a/src/niscope/metadata/config_addon.py b/src/niscope/metadata/config_addon.py index a8908b97e7..011f252777 100644 --- a/src/niscope/metadata/config_addon.py +++ b/src/niscope/metadata/config_addon.py @@ -15,5 +15,19 @@ 'file_name': 'measurement_stats', 'python_name': 'MeasurementStats' } - ] + ], + 'repeated_capabilities': [ + { + 'prefix': '', + 'python_name': 'channels' + }, + { + 'attr_for_docs_example': 'serial_number', + 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], + 'prefix': '', + 'python_name': 'instruments', + 'value_for_docs_example': None, + } + ], } From 76fede833765cbb913184e2356dd475e297034a9 Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Tue, 11 Jul 2023 13:14:58 -0500 Subject: [PATCH 12/18] generate correct rep_cap documentation for niswitch --- docs/niswitch/rep_caps.rst | 8 ++++---- src/niswitch/metadata/config_addon.py | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/niswitch/rep_caps.rst b/docs/niswitch/rep_caps.rst index 8cf95a4896..5c1304f132 100644 --- a/docs/niswitch/rep_caps.rst +++ b/docs/niswitch/rep_caps.rst @@ -32,14 +32,14 @@ channels .. code:: python - session.channels[0].channel_enabled = True + session.channels[0].is_source_channel = True - sets :py:attr:`channel_enabled` to :python:`True` for channels 0. + sets :py:attr:`is_source_channel` to :python:`True` for channels 0. .. code:: python - session.channels[0, 2].channel_enabled = True + session.channels[0, 2].is_source_channel = True - sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 2. + sets :py:attr:`is_source_channel` to :python:`True` for channels 0, 2. diff --git a/src/niswitch/metadata/config_addon.py b/src/niswitch/metadata/config_addon.py index 4c5df38f2d..5d87d2f3be 100644 --- a/src/niswitch/metadata/config_addon.py +++ b/src/niswitch/metadata/config_addon.py @@ -3,4 +3,12 @@ 'module_version': '1.4.6.dev0', 'latest_runtime_version_tested_against': '2023 Q1', 'initial_release_year': '2017', + 'repeated_capabilities': [ + { + 'attr_for_docs_example': 'is_source_channel', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'channels' + } + ], } From fb8c3a0f95cb24bead280ac1afd3c4abf7d2d06c Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Tue, 11 Jul 2023 13:48:01 -0500 Subject: [PATCH 13/18] parameterize the new tests --- build/unit_tests/test_documentation_helper.py | 322 ++++++++++-------- 1 file changed, 176 insertions(+), 146 deletions(-) diff --git a/build/unit_tests/test_documentation_helper.py b/build/unit_tests/test_documentation_helper.py index 12a177ae0b..62a340b957 100644 --- a/build/unit_tests/test_documentation_helper.py +++ b/build/unit_tests/test_documentation_helper.py @@ -1,3 +1,5 @@ +import pytest + from build.helper.documentation_helper import * @@ -728,150 +730,178 @@ def test_add_notes_re_links(): assert enum_note_text in local_config['functions']['MakeAFoo']['parameters'][1]['documentation']['note'] -def test_get_repeated_capability_single_index_python_example(): - basic_rep_cap = {'prefix': '', 'python_name': 'channels'} - basic_snippet = 'session.channels[0].channel_enabled = True' - basic_explanation = 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0.' - assert (basic_snippet, basic_explanation) == get_repeated_capability_single_index_python_example(basic_rep_cap) - - property_with_string_val_rep_cap = { - 'attr_for_docs_example': 'exported_pattern_opcode_event_output_terminal', - 'attr_type_for_docs_example': 'property', - 'prefix': 'patternOpcodeEvent', - 'python_name': 'pattern_opcode_events', - 'value_for_docs_example': '/Dev1/PXI_Trig0', - } - property_with_string_val_snippet = "session.pattern_opcode_events[0].exported_pattern_opcode_event_output_terminal = '/Dev1/PXI_Trig0'" - property_with_string_val_explanation = "sets :py:attr:`exported_pattern_opcode_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for pattern_opcode_events 0." - assert (property_with_string_val_snippet, property_with_string_val_explanation) == get_repeated_capability_single_index_python_example(property_with_string_val_rep_cap) - - custom_indices_rep_cap = { - 'indices_for_docs_example': [0, 1], - 'prefix': '', - 'python_name': 'channels', - } - custom_indices_snippet = 'session.channels[0].channel_enabled = True' - custom_indices_explanation = 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0.' - assert (custom_indices_snippet, custom_indices_explanation) == get_repeated_capability_single_index_python_example(custom_indices_rep_cap) - - string_indices_with_numerical_val_rep_cap = { - 'attr_for_docs_example': 'vil', - 'attr_type_for_docs_example': 'property', - 'indices_for_docs_example': ["PinA", "PinB", "CPin"], - 'prefix': '', - 'python_name': 'pins', - 'value_for_docs_example': 2, - } - string_indices_with_numerical_val_snippet = "session.pins['PinA'].vil = 2" - string_indices_with_numerical_val_explanation = "sets :py:attr:`vil` to :python:`2` for pins 'PinA'." - assert (string_indices_with_numerical_val_snippet, string_indices_with_numerical_val_explanation) == get_repeated_capability_single_index_python_example(string_indices_with_numerical_val_rep_cap) - - method_no_val_rep_cap = { - 'attr_for_docs_example': 'disable_sites', - 'attr_type_for_docs_example': 'method', - 'prefix': 'site', - 'python_name': 'sites', - 'value_for_docs_example': None, - } - method_no_val_snippet = "session.sites[0].disable_sites()" - method_no_val_explanation = "calls :py:meth:`disable_sites` for sites 0." - assert (method_no_val_snippet, method_no_val_explanation) == get_repeated_capability_single_index_python_example(method_no_val_rep_cap) - - property_no_val_rep_cap = { - 'attr_for_docs_example': 'serial_number', - 'attr_type_for_docs_example': 'property', - 'indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], - 'prefix': '', - 'python_name': 'instruments', - 'value_for_docs_example': None, - } - property_no_val_snippet = "print(session.instruments['Dev1'].serial_number)" - property_no_val_explanation = "prints :py:attr:`serial_number` for instruments 'Dev1'." - assert (property_no_val_snippet, property_no_val_explanation) == get_repeated_capability_single_index_python_example(property_no_val_rep_cap) - - enum_val_rep_cap = { - 'attr_for_docs_example': 'conditional_jump_trigger_type', - 'attr_type_for_docs_example': 'property', - 'prefix': 'conditionalJumpTrigger', - 'python_name': 'conditional_jump_triggers', - 'value_for_docs_example': 'nidigital.TriggerType.DIGITAL_EDGE', - 'value_type_for_docs_example': 'enum', - } - enum_val_snippet = "session.conditional_jump_triggers[0].conditional_jump_trigger_type = nidigital.TriggerType.DIGITAL_EDGE" - enum_val_explanation = "sets :py:attr:`conditional_jump_trigger_type` to :py:data:`~nidigital.TriggerType.DIGITAL_EDGE` for conditional_jump_triggers 0." - assert (enum_val_snippet, enum_val_explanation) == get_repeated_capability_single_index_python_example(enum_val_rep_cap) - - -def test_get_repeated_capability_tuple_index_python_example(): - basic_rep_cap = {'prefix': '', 'python_name': 'channels'} - basic_snippet = 'session.channels[0, 2].channel_enabled = True' - basic_explanation = 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 2.' - assert (basic_snippet, basic_explanation) == get_repeated_capability_tuple_index_python_example(basic_rep_cap) - - property_with_string_val_rep_cap = { - 'attr_for_docs_example': 'exported_pattern_opcode_event_output_terminal', - 'attr_type_for_docs_example': 'property', - 'prefix': 'patternOpcodeEvent', - 'python_name': 'pattern_opcode_events', - 'value_for_docs_example': '/Dev1/PXI_Trig0', - } - property_with_string_val_snippet = "session.pattern_opcode_events[0, 2].exported_pattern_opcode_event_output_terminal = '/Dev1/PXI_Trig0'" - property_with_string_val_explanation = "sets :py:attr:`exported_pattern_opcode_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for pattern_opcode_events 0, 2." - assert (property_with_string_val_snippet, property_with_string_val_explanation) == get_repeated_capability_tuple_index_python_example(property_with_string_val_rep_cap) - - custom_indices_rep_cap = { - 'indices_for_docs_example': [0, 1], - 'prefix': '', - 'python_name': 'channels', - } - custom_indices_snippet = 'session.channels[0, 1].channel_enabled = True' - custom_indices_explanation = 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1.' - assert (custom_indices_snippet, custom_indices_explanation) == get_repeated_capability_tuple_index_python_example(custom_indices_rep_cap) - - string_indices_with_numerical_val_rep_cap = { - 'attr_for_docs_example': 'vil', - 'attr_type_for_docs_example': 'property', - 'indices_for_docs_example': ["PinA", "PinB", "CPin"], - 'prefix': '', - 'python_name': 'pins', - 'value_for_docs_example': 2, - } - string_indices_with_numerical_val_snippet = "session.pins['PinA', 'PinB', 'CPin'].vil = 2" - string_indices_with_numerical_val_explanation = "sets :py:attr:`vil` to :python:`2` for pins 'PinA', 'PinB', 'CPin'." - assert (string_indices_with_numerical_val_snippet, string_indices_with_numerical_val_explanation) == get_repeated_capability_tuple_index_python_example(string_indices_with_numerical_val_rep_cap) - - method_no_val_rep_cap = { - 'attr_for_docs_example': 'disable_sites', - 'attr_type_for_docs_example': 'method', - 'prefix': 'site', - 'python_name': 'sites', - 'value_for_docs_example': None, - } - method_no_val_snippet = "session.sites[0, 2].disable_sites()" - method_no_val_explanation = "calls :py:meth:`disable_sites` for sites 0, 2." - assert (method_no_val_snippet, method_no_val_explanation) == get_repeated_capability_tuple_index_python_example(method_no_val_rep_cap) - - property_no_val_rep_cap = { - 'attr_for_docs_example': 'serial_number', - 'attr_type_for_docs_example': 'property', - 'indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], - 'prefix': '', - 'python_name': 'instruments', - 'value_for_docs_example': None, - } - property_no_val_snippet = "print(session.instruments['Dev1', 'Dev2', '3rdDevice'].serial_number)" - property_no_val_explanation = "prints :py:attr:`serial_number` for instruments 'Dev1', 'Dev2', '3rdDevice' or errors if the value is not the same for all." - assert (property_no_val_snippet, property_no_val_explanation) == get_repeated_capability_tuple_index_python_example(property_no_val_rep_cap) - - enum_val_rep_cap = { - 'attr_for_docs_example': 'conditional_jump_trigger_type', - 'attr_type_for_docs_example': 'property', - 'prefix': 'conditionalJumpTrigger', - 'python_name': 'conditional_jump_triggers', - 'value_for_docs_example': 'nidigital.TriggerType.DIGITAL_EDGE', - 'value_type_for_docs_example': 'enum', - } - enum_val_snippet = "session.conditional_jump_triggers[0, 2].conditional_jump_trigger_type = nidigital.TriggerType.DIGITAL_EDGE" - enum_val_explanation = "sets :py:attr:`conditional_jump_trigger_type` to :py:data:`~nidigital.TriggerType.DIGITAL_EDGE` for conditional_jump_triggers 0, 2." - assert (enum_val_snippet, enum_val_explanation) == get_repeated_capability_tuple_index_python_example(enum_val_rep_cap) +@pytest.mark.parametrize( + "rep_cap,snippet,explanation", + [ + pytest.param( + {'prefix': '', 'python_name': 'channels'}, + 'session.channels[0].channel_enabled = True', + 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0.', + id="defaults", + ), + pytest.param( + { + 'attr_for_docs_example': 'exported_pattern_opcode_event_output_terminal', + 'attr_type_for_docs_example': 'property', + 'prefix': 'patternOpcodeEvent', + 'python_name': 'pattern_opcode_events', + 'value_for_docs_example': '/Dev1/PXI_Trig0', + }, + "session.pattern_opcode_events[0].exported_pattern_opcode_event_output_terminal = '/Dev1/PXI_Trig0'", + "sets :py:attr:`exported_pattern_opcode_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for pattern_opcode_events 0.", + id="property_with_string_val", + ), + pytest.param( + { + 'indices_for_docs_example': [0, 1], + 'prefix': '', + 'python_name': 'channels', + }, + 'session.channels[0].channel_enabled = True', + 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0.', + id="custom_indices", + ), + pytest.param( + { + 'attr_for_docs_example': 'vil', + 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["PinA", "PinB", "CPin"], + 'prefix': '', + 'python_name': 'pins', + 'value_for_docs_example': 2, + }, + "session.pins['PinA'].vil = 2", + "sets :py:attr:`vil` to :python:`2` for pins 'PinA'.", + id="string_indices_with_numerical_val", + ), + pytest.param( + { + 'attr_for_docs_example': 'disable_sites', + 'attr_type_for_docs_example': 'method', + 'prefix': 'site', + 'python_name': 'sites', + 'value_for_docs_example': None, + }, + "session.sites[0].disable_sites()", + "calls :py:meth:`disable_sites` for sites 0.", + id="method_no_val", + ), + pytest.param( + { + 'attr_for_docs_example': 'serial_number', + 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], + 'prefix': '', + 'python_name': 'instruments', + 'value_for_docs_example': None, + }, + "print(session.instruments['Dev1'].serial_number)", + "prints :py:attr:`serial_number` for instruments 'Dev1'.", + id="property_no_val", + ), + pytest.param( + { + 'attr_for_docs_example': 'conditional_jump_trigger_type', + 'attr_type_for_docs_example': 'property', + 'prefix': 'conditionalJumpTrigger', + 'python_name': 'conditional_jump_triggers', + 'value_for_docs_example': 'nidigital.TriggerType.DIGITAL_EDGE', + 'value_type_for_docs_example': 'enum', + }, + "session.conditional_jump_triggers[0].conditional_jump_trigger_type = nidigital.TriggerType.DIGITAL_EDGE", + "sets :py:attr:`conditional_jump_trigger_type` to :py:data:`~nidigital.TriggerType.DIGITAL_EDGE` for conditional_jump_triggers 0.", + id="enum_val", + ), + ], +) +def test_get_repeated_capability_single_index_python_example(rep_cap, snippet, explanation): + assert (snippet, explanation) == get_repeated_capability_single_index_python_example(rep_cap) + + +@pytest.mark.parametrize( + "rep_cap,snippet,explanation", + [ + pytest.param( + {'prefix': '', 'python_name': 'channels'}, + 'session.channels[0, 2].channel_enabled = True', + 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 2.', + id="defaults", + ), + pytest.param( + { + 'attr_for_docs_example': 'exported_pattern_opcode_event_output_terminal', + 'attr_type_for_docs_example': 'property', + 'prefix': 'patternOpcodeEvent', + 'python_name': 'pattern_opcode_events', + 'value_for_docs_example': '/Dev1/PXI_Trig0', + }, + "session.pattern_opcode_events[0, 2].exported_pattern_opcode_event_output_terminal = '/Dev1/PXI_Trig0'", + "sets :py:attr:`exported_pattern_opcode_event_output_terminal` to :python:`'/Dev1/PXI_Trig0'` for pattern_opcode_events 0, 2.", + id="property_with_string_val", + ), + pytest.param( + { + 'indices_for_docs_example': [0, 1], + 'prefix': '', + 'python_name': 'channels', + }, + 'session.channels[0, 1].channel_enabled = True', + 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1.', + id="custom_indices", + ), + pytest.param( + { + 'attr_for_docs_example': 'vil', + 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["PinA", "PinB", "CPin"], + 'prefix': '', + 'python_name': 'pins', + 'value_for_docs_example': 2, + }, + "session.pins['PinA', 'PinB', 'CPin'].vil = 2", + "sets :py:attr:`vil` to :python:`2` for pins 'PinA', 'PinB', 'CPin'.", + id="string_indices_with_numerical_val", + ), + pytest.param( + { + 'attr_for_docs_example': 'disable_sites', + 'attr_type_for_docs_example': 'method', + 'prefix': 'site', + 'python_name': 'sites', + 'value_for_docs_example': None, + }, + "session.sites[0, 2].disable_sites()", + "calls :py:meth:`disable_sites` for sites 0, 2.", + id="method_no_val", + ), + pytest.param( + { + 'attr_for_docs_example': 'serial_number', + 'attr_type_for_docs_example': 'property', + 'indices_for_docs_example': ["Dev1", "Dev2", "3rdDevice"], + 'prefix': '', + 'python_name': 'instruments', + 'value_for_docs_example': None, + }, + "print(session.instruments['Dev1', 'Dev2', '3rdDevice'].serial_number)", + "prints :py:attr:`serial_number` for instruments 'Dev1', 'Dev2', '3rdDevice' or errors if the value is not the same for all.", + id="property_no_val", + ), + pytest.param( + { + 'attr_for_docs_example': 'conditional_jump_trigger_type', + 'attr_type_for_docs_example': 'property', + 'prefix': 'conditionalJumpTrigger', + 'python_name': 'conditional_jump_triggers', + 'value_for_docs_example': 'nidigital.TriggerType.DIGITAL_EDGE', + 'value_type_for_docs_example': 'enum', + }, + "session.conditional_jump_triggers[0, 2].conditional_jump_trigger_type = nidigital.TriggerType.DIGITAL_EDGE", + "sets :py:attr:`conditional_jump_trigger_type` to :py:data:`~nidigital.TriggerType.DIGITAL_EDGE` for conditional_jump_triggers 0, 2.", + id="enum_val", + ), + ], +) +def test_get_repeated_capability_tuple_index_python_example(rep_cap, snippet, explanation): + assert (snippet, explanation) == get_repeated_capability_tuple_index_python_example(rep_cap) From ad59a969e00e251274241b9ce9dc81de426d5272 Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Tue, 11 Jul 2023 14:26:24 -0500 Subject: [PATCH 14/18] reduce code duplication in new helper functions --- build/helper/documentation_helper.py | 73 ++++++++++++++-------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/build/helper/documentation_helper.py b/build/helper/documentation_helper.py index f02b083163..f82857af22 100644 --- a/build/helper/documentation_helper.py +++ b/build/helper/documentation_helper.py @@ -56,17 +56,16 @@ def get_indented_docstring_snippet(d, indent=4): return ret_val -def get_repeated_capability_single_index_python_example(rep_cap_config): - '''Returns a python code snippet and explanation for example usage of a repeated capability.''' - rep_cap_name = rep_cap_config['python_name'] - +def _get_repeated_capability_example_info(rep_cap_config): + '''Returns values needed for building a rep cap doc snippet and explanation.''' # defaults attr_for_example = 'channel_enabled' attr_type_for_example = 'property' class_attr_ref = f':py:attr:`{attr_for_example}`' index = 0 + indices = ["0", "2"] # use strings so that we can call join value = True - value_type = bool + value_type = None # we only set this for enum values if 'attr_for_docs_example' in rep_cap_config and rep_cap_config['attr_for_docs_example']: attr_for_example = rep_cap_config['attr_for_docs_example'] @@ -81,6 +80,7 @@ def get_repeated_capability_single_index_python_example(rep_cap_config): index = rep_cap_config["indices_for_docs_example"][0] if isinstance(index, str): index = repr(index) + indices = [repr(index) for index in rep_cap_config["indices_for_docs_example"]] if 'value_for_docs_example' in rep_cap_config: value = rep_cap_config['value_for_docs_example'] @@ -94,6 +94,30 @@ def get_repeated_capability_single_index_python_example(rep_cap_config): if value_type == 'enum': explanation_value = f':py:data:`~{value}`' + ret_val = { + 'attr_for_example': attr_for_example, + 'attr_type_for_example': attr_type_for_example, + 'class_attr_ref': class_attr_ref, + 'explanation_value': explanation_value, + 'index': index, + 'indices': indices, + 'value': value, + } + return ret_val + + +def get_repeated_capability_single_index_python_example(rep_cap_config): + '''Returns a python code snippet and explanation for example usage of a repeated capability.''' + rep_cap_name = rep_cap_config['python_name'] + + rep_cap_info = _get_repeated_capability_example_info(rep_cap_config) + attr_for_example = rep_cap_info['attr_for_example'] + attr_type_for_example = rep_cap_info['attr_type_for_example'] + class_attr_ref = rep_cap_info['class_attr_ref'] + explanation_value = rep_cap_info['explanation_value'] + index = rep_cap_info['index'] + value = rep_cap_info['value'] + if attr_type_for_example == "property": if value is None: snippet = f'print(session.{rep_cap_name}[{index}].{attr_for_example})' @@ -117,38 +141,13 @@ def get_repeated_capability_tuple_index_python_example(rep_cap_config): '''Returns a python code snippet and explanation for example usage of a repeated capability.''' rep_cap_name = rep_cap_config['python_name'] - # defaults - attr_for_example = 'channel_enabled' - attr_type_for_example = 'property' - class_attr_ref = f':py:attr:`{attr_for_example}`' - indices = ["0", "2"] # use strings so that we can call join - value = True - value_type = bool - - # TODO(ni-jfitzger): reduce code duplication between this and other function - if 'attr_for_docs_example' in rep_cap_config and rep_cap_config['attr_for_docs_example']: - attr_for_example = rep_cap_config['attr_for_docs_example'] - if 'attr_type_for_docs_example' in rep_cap_config and rep_cap_config['attr_type_for_docs_example']: - attr_type_for_example = rep_cap_config['attr_type_for_docs_example'] - if attr_type_for_example == 'property': - class_attr_ref = f':py:attr:`{attr_for_example}`' - elif attr_type_for_example == 'method': - class_attr_ref = f':py:meth:`{attr_for_example}`' - - if 'indices_for_docs_example' in rep_cap_config: - indices = [repr(index) for index in rep_cap_config["indices_for_docs_example"]] - - if 'value_for_docs_example' in rep_cap_config: - value = rep_cap_config['value_for_docs_example'] - value_type = type(value) - if 'value_type_for_docs_example' in rep_cap_config: - value_type = rep_cap_config['value_type_for_docs_example'] - if not value_type == 'enum' and isinstance(value, str): - value = repr(value) - - explanation_value = f':python:`{value}`' - if value_type == 'enum': - explanation_value = f':py:data:`~{value}`' + rep_cap_info = _get_repeated_capability_example_info(rep_cap_config) + attr_for_example = rep_cap_info['attr_for_example'] + attr_type_for_example = rep_cap_info['attr_type_for_example'] + class_attr_ref = rep_cap_info['class_attr_ref'] + explanation_value = rep_cap_info['explanation_value'] + indices = rep_cap_info['indices'] + value = rep_cap_info['value'] if attr_type_for_example == "property": if value is None: From 30efefd6cf02c17ee374a9d04ef72718fd21dacb Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Tue, 11 Jul 2023 14:59:38 -0500 Subject: [PATCH 15/18] eliminate most rep cap example defaults --- build/helper/documentation_helper.py | 32 +++++++------------ build/unit_tests/test_documentation_helper.py | 22 +++++++++++-- src/niscope/metadata/config_addon.py | 5 ++- src/niswitch/metadata/config_addon.py | 3 +- 4 files changed, 38 insertions(+), 24 deletions(-) diff --git a/build/helper/documentation_helper.py b/build/helper/documentation_helper.py index f82857af22..3b7dfb92ea 100644 --- a/build/helper/documentation_helper.py +++ b/build/helper/documentation_helper.py @@ -58,23 +58,16 @@ def get_indented_docstring_snippet(d, indent=4): def _get_repeated_capability_example_info(rep_cap_config): '''Returns values needed for building a rep cap doc snippet and explanation.''' - # defaults - attr_for_example = 'channel_enabled' - attr_type_for_example = 'property' - class_attr_ref = f':py:attr:`{attr_for_example}`' index = 0 indices = ["0", "2"] # use strings so that we can call join - value = True value_type = None # we only set this for enum values - if 'attr_for_docs_example' in rep_cap_config and rep_cap_config['attr_for_docs_example']: - attr_for_example = rep_cap_config['attr_for_docs_example'] - if 'attr_type_for_docs_example' in rep_cap_config and rep_cap_config['attr_type_for_docs_example']: - attr_type_for_example = rep_cap_config['attr_type_for_docs_example'] - if attr_type_for_example == 'property': - class_attr_ref = f':py:attr:`{attr_for_example}`' - elif attr_type_for_example == 'method': - class_attr_ref = f':py:meth:`{attr_for_example}`' + attr_for_example = rep_cap_config['attr_for_docs_example'] + attr_type_for_example = rep_cap_config['attr_type_for_docs_example'] + if attr_type_for_example == 'property': + class_attr_ref = f':py:attr:`{attr_for_example}`' + elif attr_type_for_example == 'method': + class_attr_ref = f':py:meth:`{attr_for_example}`' if 'indices_for_docs_example' in rep_cap_config: index = rep_cap_config["indices_for_docs_example"][0] @@ -82,13 +75,12 @@ def _get_repeated_capability_example_info(rep_cap_config): index = repr(index) indices = [repr(index) for index in rep_cap_config["indices_for_docs_example"]] - if 'value_for_docs_example' in rep_cap_config: - value = rep_cap_config['value_for_docs_example'] - value_type = type(value) - if 'value_type_for_docs_example' in rep_cap_config: - value_type = rep_cap_config['value_type_for_docs_example'] - if not value_type == 'enum' and isinstance(value, str): - value = repr(value) + value = rep_cap_config['value_for_docs_example'] + value_type = type(value) + if 'value_type_for_docs_example' in rep_cap_config: + value_type = rep_cap_config['value_type_for_docs_example'] + if not value_type == 'enum' and isinstance(value, str): + value = repr(value) explanation_value = f':python:`{value}`' if value_type == 'enum': diff --git a/build/unit_tests/test_documentation_helper.py b/build/unit_tests/test_documentation_helper.py index 62a340b957..ad0ad2ce9d 100644 --- a/build/unit_tests/test_documentation_helper.py +++ b/build/unit_tests/test_documentation_helper.py @@ -734,7 +734,13 @@ def test_add_notes_re_links(): "rep_cap,snippet,explanation", [ pytest.param( - {'prefix': '', 'python_name': 'channels'}, + { + 'attr_for_docs_example': 'channel_enabled', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'channels', + 'value_for_docs_example': True, + }, 'session.channels[0].channel_enabled = True', 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0.', id="defaults", @@ -753,9 +759,12 @@ def test_add_notes_re_links(): ), pytest.param( { + 'attr_for_docs_example': 'channel_enabled', + 'attr_type_for_docs_example': 'property', 'indices_for_docs_example': [0, 1], 'prefix': '', 'python_name': 'channels', + 'value_for_docs_example': True, }, 'session.channels[0].channel_enabled = True', 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0.', @@ -822,7 +831,13 @@ def test_get_repeated_capability_single_index_python_example(rep_cap, snippet, e "rep_cap,snippet,explanation", [ pytest.param( - {'prefix': '', 'python_name': 'channels'}, + { + 'attr_for_docs_example': 'channel_enabled', + 'attr_type_for_docs_example': 'property', + 'prefix': '', + 'python_name': 'channels', + 'value_for_docs_example': True, + }, 'session.channels[0, 2].channel_enabled = True', 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 2.', id="defaults", @@ -841,9 +856,12 @@ def test_get_repeated_capability_single_index_python_example(rep_cap, snippet, e ), pytest.param( { + 'attr_for_docs_example': 'channel_enabled', + 'attr_type_for_docs_example': 'property', 'indices_for_docs_example': [0, 1], 'prefix': '', 'python_name': 'channels', + 'value_for_docs_example': True, }, 'session.channels[0, 1].channel_enabled = True', 'sets :py:attr:`channel_enabled` to :python:`True` for channels 0, 1.', diff --git a/src/niscope/metadata/config_addon.py b/src/niscope/metadata/config_addon.py index 011f252777..5b901b5b6f 100644 --- a/src/niscope/metadata/config_addon.py +++ b/src/niscope/metadata/config_addon.py @@ -18,8 +18,11 @@ ], 'repeated_capabilities': [ { + 'attr_for_docs_example': 'channel_enabled', + 'attr_type_for_docs_example': 'property', 'prefix': '', - 'python_name': 'channels' + 'python_name': 'channels', + 'value_for_docs_example': True, }, { 'attr_for_docs_example': 'serial_number', diff --git a/src/niswitch/metadata/config_addon.py b/src/niswitch/metadata/config_addon.py index 5d87d2f3be..b0786b5753 100644 --- a/src/niswitch/metadata/config_addon.py +++ b/src/niswitch/metadata/config_addon.py @@ -8,7 +8,8 @@ 'attr_for_docs_example': 'is_source_channel', 'attr_type_for_docs_example': 'property', 'prefix': '', - 'python_name': 'channels' + 'python_name': 'channels', + 'value_for_docs_example': True, } ], } From e461d65687c477e05dfea693636746f7d42e64f6 Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Sat, 15 Jul 2023 12:21:33 -0500 Subject: [PATCH 16/18] Omit examples of elements and iterables at the top. Specify element type in documentation for each capability. --- build/helper/__init__.py | 1 + build/helper/documentation_helper.py | 12 +++++++ build/templates/rep_caps.rst.mako | 7 ++-- build/unit_tests/test_documentation_helper.py | 33 +++++++++++++++++++ docs/nidcpower/rep_caps.rst | 9 +++-- docs/nidigital/rep_caps.rst | 21 ++++++++++-- docs/nifgen/rep_caps.rst | 13 ++++++-- docs/niscope/rep_caps.rst | 9 +++-- docs/niswitch/rep_caps.rst | 7 ++-- 9 files changed, 94 insertions(+), 18 deletions(-) diff --git a/build/helper/__init__.py b/build/helper/__init__.py index f0829cd9f3..9d278dfe95 100644 --- a/build/helper/__init__.py +++ b/build/helper/__init__.py @@ -23,6 +23,7 @@ from build.helper.documentation_helper import get_function_docstring # noqa: F401 from build.helper.documentation_helper import get_function_rst # noqa: F401 from build.helper.documentation_helper import get_indented_docstring_snippet # noqa: F401 +from build.helper.documentation_helper import get_repeated_capability_element_recommendation # noqa: F401 from build.helper.documentation_helper import get_repeated_capability_single_index_python_example # noqa: F401 from build.helper.documentation_helper import get_repeated_capability_tuple_index_python_example # noqa: F401 from build.helper.documentation_helper import get_rst_header_snippet # noqa: F401 diff --git a/build/helper/documentation_helper.py b/build/helper/documentation_helper.py index 3b7dfb92ea..9f81ca2baf 100644 --- a/build/helper/documentation_helper.py +++ b/build/helper/documentation_helper.py @@ -56,6 +56,18 @@ def get_indented_docstring_snippet(d, indent=4): return ret_val +def get_repeated_capability_element_recommendation(rep_cap_config): + '''Returns a string recommending a specific type be useed for the repeated capability.''' + rep_cap_prefix = rep_cap_config['prefix'] + rep_cap_name = rep_cap_config['python_name'] + if rep_cap_prefix or rep_cap_name == 'channels': + element_type = 'an integer' + else: + element_type = 'a string' + + return f'The basic element for indexing this repeated capability is {element_type}.' + + def _get_repeated_capability_example_info(rep_cap_config): '''Returns values needed for building a rep cap doc snippet and explanation.''' index = 0 diff --git a/build/templates/rep_caps.rst.mako b/build/templates/rep_caps.rst.mako index b98599f889..253dfbf31c 100644 --- a/build/templates/rep_caps.rst.mako +++ b/build/templates/rep_caps.rst.mako @@ -32,10 +32,9 @@ name = rep_cap['python_name'] Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` - for those that don't support integers. + A single element will access one repeated capability. - The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. + An iterable will access multiple repeated capabilites at once. % for rep_cap in config['repeated_capabilities']: <% @@ -49,6 +48,8 @@ ${helper.get_rst_header_snippet(name, '-')} .. py:attribute:: ${module_name}.Session.${name}[] + ${helper.get_repeated_capability_element_recommendation(rep_cap)} + .. code:: python ${single_index_snippet} diff --git a/build/unit_tests/test_documentation_helper.py b/build/unit_tests/test_documentation_helper.py index ad0ad2ce9d..72e0d05616 100644 --- a/build/unit_tests/test_documentation_helper.py +++ b/build/unit_tests/test_documentation_helper.py @@ -730,6 +730,39 @@ def test_add_notes_re_links(): assert enum_note_text in local_config['functions']['MakeAFoo']['parameters'][1]['documentation']['note'] +@pytest.mark.parametrize( + "rep_cap,recommendation", + [ + pytest.param( + { + 'prefix': '', + 'python_name': 'channels', + }, + 'The basic element for indexing this repeated capability is an integer.', + id="no_prefix-channels", + ), + pytest.param( + { + 'prefix': '', + 'python_name': 'non-channels_cap', + }, + 'The basic element for indexing this repeated capability is a string.', + id="no_prefix-other", + ), + pytest.param( + { + 'prefix': 'RepCap', + 'python_name': 'any_rep_cap', + }, + 'The basic element for indexing this repeated capability is an integer.', + id="prefix", + ), + ], +) +def test_get_repeated_capability_element_recommendation(rep_cap, recommendation): + assert recommendation == get_repeated_capability_element_recommendation(rep_cap) + + @pytest.mark.parametrize( "rep_cap,snippet,explanation", [ diff --git a/docs/nidcpower/rep_caps.rst b/docs/nidcpower/rep_caps.rst index d9520d1918..81a27acd7f 100644 --- a/docs/nidcpower/rep_caps.rst +++ b/docs/nidcpower/rep_caps.rst @@ -21,16 +21,17 @@ Repeated Capabilities Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` - for those that don't support integers. + A single element will access one repeated capability. - The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. + An iterable will access multiple repeated capabilites at once. channels -------- .. py:attribute:: nidcpower.Session.channels[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.channels[0].output_function = nidcpower.OutputFunction.DC_CURRENT @@ -48,6 +49,8 @@ instruments .. py:attribute:: nidcpower.Session.instruments[] + The basic element for indexing this repeated capability is a string. + .. code:: python print(session.instruments['Dev1'].serial_number) diff --git a/docs/nidigital/rep_caps.rst b/docs/nidigital/rep_caps.rst index f31b94baf8..04fb1f6ac1 100644 --- a/docs/nidigital/rep_caps.rst +++ b/docs/nidigital/rep_caps.rst @@ -27,16 +27,17 @@ Repeated Capabilities Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` - for those that don't support integers. + A single element will access one repeated capability. - The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. + An iterable will access multiple repeated capabilites at once. channels -------- .. py:attribute:: nidigital.Session.channels[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.channels[0].vil = 2 @@ -54,6 +55,8 @@ pins .. py:attribute:: nidigital.Session.pins[] + The basic element for indexing this repeated capability is a string. + .. code:: python session.pins['PinA'].vil = 2 @@ -71,6 +74,8 @@ instruments .. py:attribute:: nidigital.Session.instruments[] + The basic element for indexing this repeated capability is a string. + .. code:: python session.instruments['Dev1'].timing_absolute_delay = 5e-09 @@ -88,6 +93,8 @@ pattern_opcode_events .. py:attribute:: nidigital.Session.pattern_opcode_events[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.pattern_opcode_events[0].exported_pattern_opcode_event_output_terminal = '/Dev1/PXI_Trig0' @@ -105,6 +112,8 @@ conditional_jump_triggers .. py:attribute:: nidigital.Session.conditional_jump_triggers[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.conditional_jump_triggers[0].conditional_jump_trigger_type = nidigital.TriggerType.DIGITAL_EDGE @@ -122,6 +131,8 @@ sites .. py:attribute:: nidigital.Session.sites[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.sites[0].disable_sites() @@ -139,6 +150,8 @@ rio_events .. py:attribute:: nidigital.Session.rio_events[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.rio_events[0].exported_rio_event_output_terminal = '/Dev1/PXI_Trig0' @@ -156,6 +169,8 @@ rio_triggers .. py:attribute:: nidigital.Session.rio_triggers[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.rio_triggers[0].rio_trigger_type = nidigital.TriggerType.DIGITAL_EDGE diff --git a/docs/nifgen/rep_caps.rst b/docs/nifgen/rep_caps.rst index 8410374abe..64c44aae91 100644 --- a/docs/nifgen/rep_caps.rst +++ b/docs/nifgen/rep_caps.rst @@ -23,16 +23,17 @@ Repeated Capabilities Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` - for those that don't support integers. + A single element will access one repeated capability. - The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. + An iterable will access multiple repeated capabilites at once. channels -------- .. py:attribute:: nifgen.Session.channels[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.channels[0].func_amplitude = 0.5 @@ -50,6 +51,8 @@ script_triggers .. py:attribute:: nifgen.Session.script_triggers[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.script_triggers[0].exported_script_trigger_output_terminal = '/Dev1/PXI_Trig0' @@ -67,6 +70,8 @@ markers .. py:attribute:: nifgen.Session.markers[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.markers[0].marker_event_output_terminal = '/Dev1/PXI_Trig0' @@ -84,6 +89,8 @@ data_markers .. py:attribute:: nifgen.Session.data_markers[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.data_markers[0].data_marker_event_level_polarity = nifgen.DataMarkerEventLevelPolarity.LOW diff --git a/docs/niscope/rep_caps.rst b/docs/niscope/rep_caps.rst index 188390abc2..6af1615c7f 100644 --- a/docs/niscope/rep_caps.rst +++ b/docs/niscope/rep_caps.rst @@ -21,16 +21,17 @@ Repeated Capabilities Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` - for those that don't support integers. + A single element will access one repeated capability. - The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. + An iterable will access multiple repeated capabilites at once. channels -------- .. py:attribute:: niscope.Session.channels[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.channels[0].channel_enabled = True @@ -48,6 +49,8 @@ instruments .. py:attribute:: niscope.Session.instruments[] + The basic element for indexing this repeated capability is a string. + .. code:: python print(session.instruments['Dev1'].serial_number) diff --git a/docs/niswitch/rep_caps.rst b/docs/niswitch/rep_caps.rst index 5c1304f132..be24054726 100644 --- a/docs/niswitch/rep_caps.rst +++ b/docs/niswitch/rep_caps.rst @@ -20,16 +20,17 @@ Repeated Capabilities Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. - The recommended way of accessing a single repeated capability is with an integer :python:`[0]` for capabilities that support it and a string :python:`['Dev1']` - for those that don't support integers. + A single element will access one repeated capability. - The recommended way of accessing multiple repeated capabilites at once is with a tuple (:python:`[0, 1]` or :python:`['Dev1', 'Dev2']`) or slice :python:`[0:2]`. + An iterable will access multiple repeated capabilites at once. channels -------- .. py:attribute:: niswitch.Session.channels[] + The basic element for indexing this repeated capability is an integer. + .. code:: python session.channels[0].is_source_channel = True From 19b220847cf23942ed418068159c66beb4ebe574 Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Sat, 15 Jul 2023 12:36:36 -0500 Subject: [PATCH 17/18] Remove the "or errors if the value is not the same for all." statement --- build/helper/documentation_helper.py | 2 +- build/unit_tests/test_documentation_helper.py | 2 +- docs/nidcpower/rep_caps.rst | 2 +- docs/niscope/rep_caps.rst | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/helper/documentation_helper.py b/build/helper/documentation_helper.py index 9f81ca2baf..4f6933f408 100644 --- a/build/helper/documentation_helper.py +++ b/build/helper/documentation_helper.py @@ -156,7 +156,7 @@ def get_repeated_capability_tuple_index_python_example(rep_cap_config): if attr_type_for_example == "property": if value is None: snippet = f'print(session.{rep_cap_name}[{", ".join(indices)}].{attr_for_example})' - explanation = f"prints {class_attr_ref} for {rep_cap_name} {', '.join(indices)} or errors if the value is not the same for all." + explanation = f"prints {class_attr_ref} for {rep_cap_name} {', '.join(indices)}." else: snippet = f'session.{rep_cap_name}[{", ".join(indices)}].{attr_for_example} = {value}' explanation = f"sets {class_attr_ref} to {explanation_value} for {rep_cap_name} {', '.join(indices)}." diff --git a/build/unit_tests/test_documentation_helper.py b/build/unit_tests/test_documentation_helper.py index 72e0d05616..75d9006005 100644 --- a/build/unit_tests/test_documentation_helper.py +++ b/build/unit_tests/test_documentation_helper.py @@ -935,7 +935,7 @@ def test_get_repeated_capability_single_index_python_example(rep_cap, snippet, e 'value_for_docs_example': None, }, "print(session.instruments['Dev1', 'Dev2', '3rdDevice'].serial_number)", - "prints :py:attr:`serial_number` for instruments 'Dev1', 'Dev2', '3rdDevice' or errors if the value is not the same for all.", + "prints :py:attr:`serial_number` for instruments 'Dev1', 'Dev2', '3rdDevice'.", id="property_no_val", ), pytest.param( diff --git a/docs/nidcpower/rep_caps.rst b/docs/nidcpower/rep_caps.rst index 81a27acd7f..c9f8172e19 100644 --- a/docs/nidcpower/rep_caps.rst +++ b/docs/nidcpower/rep_caps.rst @@ -61,6 +61,6 @@ instruments print(session.instruments['Dev1', 'Dev2', '3rdDevice'].serial_number) - prints :py:attr:`serial_number` for instruments 'Dev1', 'Dev2', '3rdDevice' or errors if the value is not the same for all. + prints :py:attr:`serial_number` for instruments 'Dev1', 'Dev2', '3rdDevice'. diff --git a/docs/niscope/rep_caps.rst b/docs/niscope/rep_caps.rst index 6af1615c7f..cd9231a790 100644 --- a/docs/niscope/rep_caps.rst +++ b/docs/niscope/rep_caps.rst @@ -61,6 +61,6 @@ instruments print(session.instruments['Dev1', 'Dev2', '3rdDevice'].serial_number) - prints :py:attr:`serial_number` for instruments 'Dev1', 'Dev2', '3rdDevice' or errors if the value is not the same for all. + prints :py:attr:`serial_number` for instruments 'Dev1', 'Dev2', '3rdDevice'. From d2c61ae02e7ec3833c375b7e35af7750914593cc Mon Sep 17 00:00:00 2001 From: Jay Fitzgerald <34140133+ni-jfitzger@users.noreply.github.com> Date: Sat, 15 Jul 2023 12:51:25 -0500 Subject: [PATCH 18/18] like -> such as --- build/templates/rep_caps.rst.mako | 2 +- docs/nidcpower/rep_caps.rst | 2 +- docs/nidigital/rep_caps.rst | 2 +- docs/nifgen/rep_caps.rst | 2 +- docs/niscope/rep_caps.rst | 2 +- docs/niswitch/rep_caps.rst | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/templates/rep_caps.rst.mako b/build/templates/rep_caps.rst.mako index 253dfbf31c..64fbf46de3 100644 --- a/build/templates/rep_caps.rst.mako +++ b/build/templates/rep_caps.rst.mako @@ -30,7 +30,7 @@ name = rep_cap['python_name'] % endfor Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. + The parameter can be a single element or an iterable that implements sequence semantics, such as list, tuple, range and slice. A single element will access one repeated capability. diff --git a/docs/nidcpower/rep_caps.rst b/docs/nidcpower/rep_caps.rst index c9f8172e19..f7b13dc527 100644 --- a/docs/nidcpower/rep_caps.rst +++ b/docs/nidcpower/rep_caps.rst @@ -19,7 +19,7 @@ Repeated Capabilities #. instruments_ Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. + The parameter can be a single element or an iterable that implements sequence semantics, such as list, tuple, range and slice. A single element will access one repeated capability. diff --git a/docs/nidigital/rep_caps.rst b/docs/nidigital/rep_caps.rst index 04fb1f6ac1..2820ce2b35 100644 --- a/docs/nidigital/rep_caps.rst +++ b/docs/nidigital/rep_caps.rst @@ -25,7 +25,7 @@ Repeated Capabilities #. rio_triggers_ Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. + The parameter can be a single element or an iterable that implements sequence semantics, such as list, tuple, range and slice. A single element will access one repeated capability. diff --git a/docs/nifgen/rep_caps.rst b/docs/nifgen/rep_caps.rst index 64c44aae91..143aa716be 100644 --- a/docs/nifgen/rep_caps.rst +++ b/docs/nifgen/rep_caps.rst @@ -21,7 +21,7 @@ Repeated Capabilities #. data_markers_ Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. + The parameter can be a single element or an iterable that implements sequence semantics, such as list, tuple, range and slice. A single element will access one repeated capability. diff --git a/docs/niscope/rep_caps.rst b/docs/niscope/rep_caps.rst index cd9231a790..0d39d82f3c 100644 --- a/docs/niscope/rep_caps.rst +++ b/docs/niscope/rep_caps.rst @@ -19,7 +19,7 @@ Repeated Capabilities #. instruments_ Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. + The parameter can be a single element or an iterable that implements sequence semantics, such as list, tuple, range and slice. A single element will access one repeated capability. diff --git a/docs/niswitch/rep_caps.rst b/docs/niswitch/rep_caps.rst index be24054726..0864239c9c 100644 --- a/docs/niswitch/rep_caps.rst +++ b/docs/niswitch/rep_caps.rst @@ -18,7 +18,7 @@ Repeated Capabilities #. channels_ Use the indexing operator :python:`[]` to indicate which repeated capability instance you are trying to access. - The parameter can be a single element or an iterable that implements sequence semantics, like list, tuple, range and slice. + The parameter can be a single element or an iterable that implements sequence semantics, such as list, tuple, range and slice. A single element will access one repeated capability.