Troubleshooting Contributions

This goes over common issues which can occur when contributing to tm_devices and how to deal with them.


Creating New Troubleshooting Entries

This section demonstrates the format to use when adding new entries to troubleshooting guides.

The dashed line should be included to help provide a visual break between different entries.

______________________________________________________________________

## Example Issue Summary

This is an example issue to use for formatting new troubleshooting entries.

### Problem:

Explain the problem.

```
Use code if applicable.
```

### Solution:

Explain the solution.

```
Use code if applicable.
```

Unit tests have lots of VISA timeouts and failures in tests for areas that were not changed

Problem:

Running unit tests takes a really long time and there are lots of VISA failures/timeouts in tests for areas that did not have any changes.

Pytest will usually also emit failures and warnings that look like this:

>               raise AssertionError(message) from error_2
E               AssertionError: Unable to establish a VISA connection to TCPIP0::SS3706A-HOSTNAME::inst0::INSTR
E
E               This is the current ping output for the device at SS3706A-HOSTNAME:
E
E               Pinging SS3706A-HOSTNAME [xx.xxx.xxx.xxx] with 32 bytes of data:
E               Reply from xx.xxx.xxx.xxx: bytes=32 time=23ms TTL=56
E
E               Ping statistics for xx.xxx.xxx.xxx:
E                   Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
E               Approximate round trip times in milli-seconds:
E                   Minimum = 23ms, Maximum = 23ms, Average = 23ms
---------------------------- Captured stdout call -----------------------------
2023-04-10 08:50:21.664 - Creating Connection to SS 1 "SS-DEVICE"
------------------------------ Captured log call ------------------------------
WARNING  pyvisa:devices.py:143 No eom provided for InterfaceType.asrl, INSTR.Using LF.
WARNING  pyvisa:devices.py:143 No eom provided for InterfaceType.tcpip, INSTR.Using LF.
WARNING  pyvisa:devices.py:143 No eom provided for InterfaceType.tcpip, INSTR.Using LF.
WARNING  pyvisa:devices.py:143 No eom provided for InterfaceType.tcpip, INSTR.Using LF.
WARNING  pyvisa:devices.py:143 No eom provided for InterfaceType.tcpip, INSTR.Using LF.
WARNING  pyvisa:devices.py:143 No eom provided for InterfaceType.usb, INSTR.Using LF.
WARNING  pyvisa:devices.py:143 No eom provided for InterfaceType.tcpip, INSTR.Using LF.

Solution:

This is usually caused by invalid entries in the resources list in the tests/sim_devices/devices.yaml file.

Notice in this code example how the device key value does not match a valid item from the devices list in tests/sim_devices/psu/psu2281.yaml. The device key value must match a valid item (device) from the devices list in the yaml file which is specified by the filename key.

# tests/sim_devices/devices.yaml
resources:
  TCPIP::PSU2281-HOSTNAME::INSTR:
    device: psu2282
    filename: psu/psu2281.yaml
# tests/sim_devices/psu/psu2281.yaml
spec: '1.1'
devices:
  psu2281:
    dialogues:
      - q: '*IDN?'
        r: KEITHLEY INSTRUMENTS INC.,MODEL 2281S-20-6,01234567,01.00

Pyright is failing on unchanged code

Problem:

When running pre-commit, Pyright is showing errors on lines of code that were not touched by any recent changes.

pyright..................................................................Failed
- hook id: pyright
- exit code: 1
No configuration file found.
pyproject.toml file found at <file-path>.
Loading pyproject.toml file at <file-path>\pyproject.toml
No include entries specified; assuming <file-path>
Auto-excluding **/node_modules
Auto-excluding **/__pycache__
Auto-excluding **/.*
Searching for source files
Found 825 source files
pyright 1.1.305
<file-path>\docs\conf.py
  <file-path>\docs\conf.py:155:40 - error: Type of parameter "obj" is unknown (reportUnknownParameterType)
  <file-path>\docs\conf.py:190:50 - error: Type of "pathname" is unknown (reportUnknownMemberType)
  <file-path>\docs\conf.py:191:12 - error: Type of "pathname" is unknown (reportUnknownMemberType)
  <file-path>\docs\conf.py:191:12 - error: Type of "endswith" is unknown (reportUnknownMemberType)
<file-path>\tests\conftest.py
  <file-path>\tests\conftest.py:11:25 - error: Type of "mocker_server" is unknown (reportUnknownVariableType)
<file-path>\tests\mock_server.py
  <file-path>\tests\mock_server.py:29:1 - error: Type of "mocker_server" is unknown (reportUnknownVariableType)
  <file-path>\tests\mock_server.py:33:2 - error: Type of "route" is unknown (reportUnknownMemberType)
  <file-path>\tests\mock_server.py:33:2 - error: Untyped function decorator obscures type of function; ignoring decorator (reportUntypedFunctionDecorator)
  <file-path>\tests\mock_server.py:43:2 - error: Type of "route" is unknown (reportUnknownMemberType)
  <file-path>\tests\mock_server.py:43:2 - error: Untyped function decorator obscures type of function; ignoring decorator (reportUntypedFunctionDecorator)
  <file-path>\tests\mock_server.py:53:2 - error: Type of "route" is unknown (reportUnknownMemberType)
  <file-path>\tests\mock_server.py:53:2 - error: Untyped function decorator obscures type of function; ignoring decorator (reportUntypedFunctionDecorator)
  <file-path>\tests\mock_server.py:63:2 - error: Type of "route" is unknown (reportUnknownMemberType)
  <file-path>\tests\mock_server.py:63:2 - error: Untyped function decorator obscures type of function; ignoring decorator (reportUntypedFunctionDecorator)
  <file-path>\tests\mock_server.py:73:2 - error: Type of "route" is unknown (reportUnknownMemberType)
  <file-path>\tests\mock_server.py:73:2 - error: Untyped function decorator obscures type of function; ignoring decorator (reportUntypedFunctionDecorator)
  <file-path>\tests\mock_server.py:83:2 - error: Type of "route" is unknown (reportUnknownMemberType)
  <file-path>\tests\mock_server.py:83:2 - error: Untyped function decorator obscures type of function; ignoring decorator (reportUntypedFunctionDecorator)
18 errors, 0 warnings, 0 informations
Completed in 58.189sec

Solution:

This is caused by running pre-commit in a Python environment that does not have the proper development dependencies installed.

See the contributing guide for details on how to properly set up and test changes using a virtual environment.


Executable not found during pre-commit

Pre-commit is failing with “Executable not found” errors.

Problem:

When running pre-commit, in either an Integrated Development Environment (IDE) or through the command line, the virtual environment must be used so that all necessary executables can be found.

tm_devices uses a few local pre-commit hooks, so if the environment is not correctly enabled, those hooks will fail.

pre-commit run --all
check yaml...............................................................Passed
check toml...............................................................Passed
check json...............................................................Passed
fix requirements.txt.....................................................Passed
trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
check for case conflicts.................................................Passed
check for merge conflicts................................................Passed
check for added large files..............................................Passed
forbid new submodules................................(no files to check)Skipped
pretty format json.......................................................Passed
Tabs remover.............................................................Passed
No-tabs checker..........................................................Passed
Validate ReadTheDocs Config..............................................Passed
Validate Dependabot Config (v2)..........................................Passed
Validate GitHub Actions..............................(no files to check)Skipped
Validate GitHub Workflows................................................Passed
blacken-docs.............................................................Passed
yamlfix..................................................................Passed
mdformat.................................................................Passed
Poetry check.............................................................Failed
- hook id: check-poetry
- exit code: 1

Executable `poetry` not found

toml-sort................................................................Failed
- hook id: toml-sort
- exit code: 1

Executable `toml-sort` not found

pylint...................................................................Failed
- hook id: pylint
- exit code: 1

Executable `pylint` not found

pyright..................................................................Failed
- hook id: pyright
- exit code: 1

Executable `pyright` not found

pyright-verifytypes......................................................Failed
- hook id: pyright-verifytypes
- exit code: 1

Executable `pyright` not found

pyroma...................................................................Failed
- hook id: pyroma
- exit code: 1

Executable `pyroma` not found

ruff.....................................................................Passed
black....................................................................Passed
docformatter.............................................................Passed

Solution:

In order to fix this issue, first activate the virtual environment (or set your IDE to use the correct Python interpreter for pre-commit hooks), then update the installed dependencies, then retry the command.

# Linux
source .venv/bin/activate

# Windows
.venv\Scripts\activate.bat

# Update installed dependencies
python scripts/update_development_dependencies.py

# Re-run original, failing command

FileNotFoundError when running tests

Problem:

When running tests with a specified html output file, sometimes an internal error can be raised causing the test run to crash.

> pytest -k "test_docs" --self-contained-html --html=.results_doctests/results.html

platform win32 -- Python 3.11.4, pytest-7.4.1, pluggy-1.3.0 -- .env\Scripts\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.11.4', 'Platform': 'Windows-10-10.0.19045-SP0', 'Packages': {'pytest': '7.4.1', 'pluggy': '1.3.0'}, 'Plugins': {'cov': '4.1.0', 'html': '4.0.0', 'metadata': '3.0.0', 'order': '1.1.0', 'profiling': '1.7.0'}}
configfile: pyproject.toml
plugins: cov-4.1.0, html-4.0.0, metadata-3.0.0, order-1.1.0, profiling-1.7.0
collected 177 items / 174 deselected / 3 selected

tests/test_docs.py::TestDocs::test_docs_linkcheck                                                                                                                                                                                                   [ 33%]
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File ".env\Lib\site-packages\_pytest\main.py", line 270, in wrap_session
INTERNALERROR>     session.exitstatus = doit(config, session) or 0
INTERNALERROR>                          ^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\_pytest\main.py", line 324, in _main
INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_hooks.py", line 493, in __call__
INTERNALERROR>     return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
INTERNALERROR>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_manager.py", line 115, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
INTERNALERROR>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_callers.py", line 152, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>            ^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_result.py", line 114, in get_result
INTERNALERROR>     raise exc.with_traceback(exc.__traceback__)
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_callers.py", line 77, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>           ^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\_pytest\main.py", line 349, in pytest_runtestloop
INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_hooks.py", line 493, in __call__
INTERNALERROR>     return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
INTERNALERROR>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_manager.py", line 115, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
INTERNALERROR>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_callers.py", line 152, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>            ^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_result.py", line 114, in get_result
INTERNALERROR>     raise exc.with_traceback(exc.__traceback__)
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_callers.py", line 77, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>           ^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\_pytest\runner.py", line 114, in pytest_runtest_protocol
INTERNALERROR>     runtestprotocol(item, nextitem=nextitem)
INTERNALERROR>   File ".env\Lib\site-packages\_pytest\runner.py", line 133, in runtestprotocol
INTERNALERROR>     reports.append(call_and_report(item, "call", log))
INTERNALERROR>                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\_pytest\runner.py", line 226, in call_and_report
INTERNALERROR>     hook.pytest_runtest_logreport(report=report)
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_hooks.py", line 493, in __call__
INTERNALERROR>     return self._hookexec(self.name, self._hookimpls, kwargs, firstresult)
INTERNALERROR>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_manager.py", line 115, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
INTERNALERROR>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_callers.py", line 113, in _multicall
INTERNALERROR>     raise exception.with_traceback(exception.__traceback__)
INTERNALERROR>   File ".env\Lib\site-packages\pluggy\_callers.py", line 77, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>           ^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File ".env\Lib\site-packages\pytest_html\basereport.py", line 251, in pytest_runtest_logreport
INTERNALERROR>     self._generate_report()
INTERNALERROR>   File ".env\Lib\site-packages\pytest_html\selfcontained_report.py", line 39, in _generate_report
INTERNALERROR>     super()._generate_report(self_contained=True)
INTERNALERROR>   File ".env\Lib\site-packages\pytest_html\basereport.py", line 65, in _generate_report
INTERNALERROR>     self._write_report(rendered_report)
INTERNALERROR>   File ".env\Lib\site-packages\pytest_html\basereport.py", line 134, in _write_report
INTERNALERROR>     with self._report_path.open("w", encoding="utf-8") as f:
INTERNALERROR>          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR>   File "C:\Python311_64bit\Lib\pathlib.py", line 1044, in open
INTERNALERROR>     return io.open(self, mode, buffering, encoding, errors, newline)
INTERNALERROR>            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
INTERNALERROR> FileNotFoundError: [Errno 2] No such file or directory: '.results_doctests\\results.html'

Solution:

This is caused by passing in a relative path to the html output file via the --html flag. Some versions of pytest-html don’t convert the path to an absolute path, so if a test changes the current working directory the html reporter plugin will raise a FileNotFoundError.

In order to prevent this issue from occurring, simply pass in the full path to the html output file when running pytest.

# Linux
source .venv/bin/activate
pytest -k "test_docs" --self-contained-html --html=$(pwd)/.results_doctests/results.html

# Windows
.venv\Scripts\activate.bat
pytest -k "test_docs" --self-contained-html --html=%CD%\.results_doctests\results.html