diff --git a/build/helper/metadata_add_all.py b/build/helper/metadata_add_all.py index 69132a934f..235ee44f10 100644 --- a/build/helper/metadata_add_all.py +++ b/build/helper/metadata_add_all.py @@ -729,6 +729,38 @@ def add_all_config_metadata(config): ''' config = merge_helper(config, 'config', config, use_re=False) + for repeated_capability in config['repeated_capabilities']: + documentation = repeated_capability.setdefault('documentation', {}) + prefix = repeated_capability['prefix'] + name = repeated_capability['python_name'] + + if prefix: + documentation.setdefault( + 'description', + ( + 'If no prefix is added to the items in the parameter, the correct prefix will be added when\n' + 'the driver function call is made.\n\n' + ".. code:: python\n\n session.{}['0-2'].channel_enabled = True\n\n" + "passes a string of :python:`'{}0, {}1, {}2'` to the set attribute function.\n\n" + 'If an invalid repeated capability is passed to the driver, the driver will return an error.\n\n' + 'You can also explicitly use the prefix as part of the parameter, but it must be the correct prefix\n' + 'for the specific repeated capability.' + ).format(name, prefix, prefix, prefix) + ) + else: + documentation.setdefault('description', '') + + documentation.setdefault( + 'examples', + [ + ( + "session.{}['{}0-{}2'].channel_enabled = True\n\n" + "passes a string of :python:`'{}0, {}1, {}2'` to the set attribute function." + ).format(name, prefix, prefix, prefix, prefix, prefix) + ] + ) + documentation.setdefault('valid_identifiers', []) + if 'use_locking' not in config: config['use_locking'] = True diff --git a/build/templates/rep_caps.rst.mako b/build/templates/rep_caps.rst.mako index 179d56e1fc..1571d9c3b4 100644 --- a/build/templates/rep_caps.rst.mako +++ b/build/templates/rep_caps.rst.mako @@ -33,34 +33,24 @@ ${helper.get_rst_header_snippet('Repeated Capabilities', '=')} % for rep_cap in config['repeated_capabilities']: <% name = rep_cap['python_name'] -prefix = rep_cap['prefix'] +rep_cap_doc = rep_cap['documentation'] %>\ ${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 rep_cap_doc['description']: + ${rep_cap_doc['description'].replace('\n', '\n ')} - .. 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. +% endif +% if rep_cap_doc['valid_identifiers']: + Valid identifiers: :python:`'${", ".join(rep_cap_doc["valid_identifiers"])}'`. % endif +% for example in rep_cap_doc['examples']: .. 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. - + ${example.replace('\n', '\n ')} % endfor - +% endfor diff --git a/build/unit_tests/test_rep_caps_template.py b/build/unit_tests/test_rep_caps_template.py new file mode 100644 index 0000000000..347297c485 --- /dev/null +++ b/build/unit_tests/test_rep_caps_template.py @@ -0,0 +1,87 @@ +from pathlib import Path +from types import SimpleNamespace + +from mako.template import Template +from build.helper.metadata_add_all import add_all_config_metadata + + +def _render_rep_caps(config): + repo_root = Path(__file__).resolve().parents[2] + template_path = repo_root / 'build' / 'templates' / 'rep_caps.rst.mako' + template = Template(filename=str(template_path)) + metadata = SimpleNamespace(config=add_all_config_metadata(config)) + return template.render(template_parameters={'metadata': metadata}) + + +def test_rep_caps_template_uses_custom_documentation_overrides(): + config = { + 'module_name': 'nifake', + 'c_function_prefix': 'niFake_', + 'repeated_capabilities': [ + { + 'prefix': 'res', + 'python_name': 'resources', + 'documentation': { + 'description': 'Resource repeated capabilities use fully-qualified identifiers.', + 'valid_identifiers': ['dev0/res0', 'dev0/res1'], + 'examples': [ + "session.resources['dev0/res0'].channel_enabled = True", + "session.resources['dev0/res1'].channel_enabled = True", + ], + }, + } + ], + } + + rendered = _render_rep_caps(config) + + assert 'Resource repeated capabilities use fully-qualified identifiers.' in rendered + assert "Valid identifiers: :python:`'dev0/res0, dev0/res1'`." in rendered + assert "session.resources['dev0/res0'].channel_enabled = True" in rendered + assert "session.resources['dev0/res1'].channel_enabled = True" in rendered + + # Generic auto-prefix guidance should be suppressed when override disables it. + assert 'If no prefix is added to the items in the parameter' not in rendered + assert "session.resources['0-2'].channel_enabled = True" not in rendered + assert "'res0, res1, res2'" not in rendered + + +def test_rep_caps_template_preserves_default_prefixed_behavior(): + config = { + 'module_name': 'nifake', + 'c_function_prefix': 'niFake_', + 'repeated_capabilities': [ + { + 'prefix': 'channel', + 'python_name': 'channels', + } + ], + } + + rendered = _render_rep_caps(config) + + assert 'If no prefix is added to the items in the parameter' in rendered + assert "session.channels['0-2'].channel_enabled = True" in rendered + assert "'channel0, channel1, channel2'" in rendered + + +def test_rep_caps_template_expands_default_documentation_fields(): + config = { + 'module_name': 'nifake', + 'c_function_prefix': 'niFake_', + 'repeated_capabilities': [ + { + 'prefix': 'channel', + 'python_name': 'channels', + 'documentation': { + 'description': 'Custom channel documentation.', + }, + } + ], + } + + rendered = _render_rep_caps(config) + + assert 'Custom channel documentation.' in rendered + assert "session.channels['channel0-channel2'].channel_enabled = True" in rendered + assert "'channel0, channel1, channel2'" in rendered diff --git a/docs/nidcpower/rep_caps.rst b/docs/nidcpower/rep_caps.rst index 6078e4deab..76fa29a033 100644 --- a/docs/nidcpower/rep_caps.rst +++ b/docs/nidcpower/rep_caps.rst @@ -31,9 +31,8 @@ channels .. code:: python session.channels['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. instruments ----------- @@ -43,8 +42,6 @@ instruments .. code:: python session.instruments['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. diff --git a/docs/nidigital/rep_caps.rst b/docs/nidigital/rep_caps.rst index 32550fc4f8..01eb7e6efb 100644 --- a/docs/nidigital/rep_caps.rst +++ b/docs/nidigital/rep_caps.rst @@ -31,9 +31,8 @@ channels .. code:: python session.channels['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. pins ---- @@ -43,9 +42,8 @@ pins .. code:: python session.pins['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. instruments ----------- @@ -55,138 +53,131 @@ instruments .. code:: python session.instruments['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. 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 + 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. - + + passes a string of :python:`'patternOpcodeEvent0, patternOpcodeEvent1, patternOpcodeEvent2'` to the set attribute function. 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 + 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. - + + passes a string of :python:`'conditionalJumpTrigger0, conditionalJumpTrigger1, conditionalJumpTrigger2'` to the set attribute function. sites ----- .. py:attribute:: nidigital.Session.sites[] - If no prefix is added to the items in the parameter, the correct prefix will be added when + 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. - + + passes a string of :python:`'site0, site1, site2'` to the set attribute function. 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 + 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. - + + passes a string of :python:`'RIOEvent0, RIOEvent1, RIOEvent2'` to the set attribute function. 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 + 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. - - + + passes a string of :python:`'RIOTrigger0, RIOTrigger1, RIOTrigger2'` to the set attribute function. diff --git a/docs/nifgen/rep_caps.rst b/docs/nifgen/rep_caps.rst index 5890a432ea..7ff8a720a2 100644 --- a/docs/nifgen/rep_caps.rst +++ b/docs/nifgen/rep_caps.rst @@ -31,86 +31,81 @@ channels .. code:: python session.channels['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. 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 + 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. - + + passes a string of :python:`'ScriptTrigger0, ScriptTrigger1, ScriptTrigger2'` to the set attribute function. markers ------- .. py:attribute:: nifgen.Session.markers[] - If no prefix is added to the items in the parameter, the correct prefix will be added when + 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. - + + passes a string of :python:`'Marker0, Marker1, Marker2'` to the set attribute function. 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 + 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. - - + + passes a string of :python:`'DataMarker0, DataMarker1, DataMarker2'` to the set attribute function. diff --git a/docs/nirfsg/rep_caps.rst b/docs/nirfsg/rep_caps.rst index 4b13100dfa..f14b8924ee 100644 --- a/docs/nirfsg/rep_caps.rst +++ b/docs/nirfsg/rep_caps.rst @@ -28,78 +28,75 @@ markers .. py:attribute:: nirfsg.Session.markers[] - If no prefix is added to the items in the parameter, the correct prefix will be added when + 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. - + + passes a string of :python:`'marker0, marker1, marker2'` to the set attribute function. script_triggers --------------- .. py:attribute:: nirfsg.Session.script_triggers[] - If no prefix is added to the items in the parameter, the correct prefix will be added when + 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. - + + passes a string of :python:`'scripttrigger0, scripttrigger1, scripttrigger2'` to the set attribute function. waveforms --------- .. py:attribute:: nirfsg.Session.waveforms[] - If no prefix is added to the items in the parameter, the correct prefix will be added when + 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.waveforms['0-2'].channel_enabled = True - + passes a string of :python:`'waveform::0, waveform::1, waveform::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.waveforms['waveform::0-waveform::2'].channel_enabled = True - - passes a string of :python:`'waveform::0, waveform::1, waveform::2'` to the set attribute function. - + + passes a string of :python:`'waveform::0, waveform::1, waveform::2'` to the set attribute function. ports ----- @@ -109,35 +106,33 @@ ports .. code:: python session.ports['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. los --- .. py:attribute:: nirfsg.Session.los[] - If no prefix is added to the items in the parameter, the correct prefix will be added when + 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.los['0-2'].channel_enabled = True - + passes a string of :python:`'LO0, LO1, LO2'` 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.los['LO0-LO2'].channel_enabled = True - - passes a string of :python:`'LO0, LO1, LO2'` to the set attribute function. - + + passes a string of :python:`'LO0, LO1, LO2'` to the set attribute function. device_temperatures ------------------- @@ -147,9 +142,8 @@ device_temperatures .. code:: python session.device_temperatures['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. channels -------- @@ -159,8 +153,6 @@ channels .. code:: python session.channels['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. diff --git a/docs/niscope/rep_caps.rst b/docs/niscope/rep_caps.rst index 19169bc085..49086e35df 100644 --- a/docs/niscope/rep_caps.rst +++ b/docs/niscope/rep_caps.rst @@ -31,9 +31,8 @@ channels .. code:: python session.channels['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. instruments ----------- @@ -43,8 +42,6 @@ instruments .. code:: python session.instruments['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. diff --git a/docs/niswitch/rep_caps.rst b/docs/niswitch/rep_caps.rst index 7f141fa26b..9b1bad4f86 100644 --- a/docs/niswitch/rep_caps.rst +++ b/docs/niswitch/rep_caps.rst @@ -31,8 +31,6 @@ channels .. code:: python session.channels['0-2'].channel_enabled = True - - passes a string of :python:`'0, 1, 2'` to the set attribute function. - - + + passes a string of :python:`'0, 1, 2'` to the set attribute function. diff --git a/src/nifake/metadata/config.py b/src/nifake/metadata/config.py index ea09207158..183e6f3496 100644 --- a/src/nifake/metadata/config.py +++ b/src/nifake/metadata/config.py @@ -64,6 +64,14 @@ 'python_name': 'channels' }, { + 'documentation': { + 'description': 'Sites are identified by the ``site`` prefix followed by a zero-based index.', + 'valid_identifiers': ['site0', 'site1'], + 'examples': [ + "session.sites['site0'].function_with_repeated_capability_type()", + "session.sites['site0', 'site1'].function_with_repeated_capability_type()", + ], + }, 'prefix': 'site', 'python_name': 'sites' },