Repository: QCoDeS/Qcodes (python)

Issue:
print_readable_snapshot() of instrument modules without parameters broken.
### `print_readable_snapshot()` of instrument modules without parameters fails.

### Steps to reproduce
```python
from qcodes import instrument
bar = instrument.Instrument('bar')
foo = instrument.InstrumentModule(bar, 'foo')
bar.add_submodule('foo', foo)
```
Calling `print_readable_snapshot()` on either the submodule or the parent instrument fails:
```python
>>> bar.print_readable_snapshot()
  File ~\Documents\Qcodes\src\qcodes\instrument\instrument_base.py:406 in print_readable_snapshot
    par_field_len = min(max(par_lengths) + 1, 50)

ValueError: max() arg is an empty sequence
```
This should be resolved by catching the empty sequence here:
https://github.com/QCoDeS/Qcodes/blob/7f114bfc2c8cbb759d0a7266da26945fd66dac43/src/qcodes/instrument/instrument_base.py#L398-L402

Branch: main @ https://github.com/QCoDeS/Qcodes/commit/42c74833d227a85ee45d7812e1ac0f66b8d948b0

Pull request description:
Fix print_readable_snapshot for empty InstrumentModule
Closes #5519


Patch:
diff --git a/src/qcodes/instrument/instrument_base.py b/src/qcodes/instrument/instrument_base.py
index fe94dda74..02a5f962f 100644
--- a/src/qcodes/instrument/instrument_base.py
+++ b/src/qcodes/instrument/instrument_base.py
@@ -396,6 +396,8 @@ class InstrumentBase(MetadatableWithName, DelegateAttributes):
         snapshot = self.snapshot(update=update)
 
         par_lengths = [len(p) for p in snapshot["parameters"]]
+        # handle the case of no parameters
+        par_lengths = par_lengths or [0]
 
         # Min of 50 is to prevent a super long parameter name to break this
         # function


Test patch:
diff --git a/tests/test_instrument.py b/tests/test_instrument.py
index 0d15c2d16..d91ace758 100644
--- a/tests/test_instrument.py
+++ b/tests/test_instrument.py
@@ -14,7 +14,12 @@ from weakref import WeakValueDictionary
 import pytest
 from pytest import FixtureRequest
 
-from qcodes.instrument import Instrument, InstrumentBase, find_or_create_instrument
+from qcodes.instrument import (
+    Instrument,
+    InstrumentBase,
+    InstrumentModule,
+    find_or_create_instrument,
+)
 from qcodes.instrument_drivers.mock_instruments import (
     DummyChannelInstrument,
     DummyFailingInstrument,
@@ -53,6 +58,16 @@ def _dummy_parabola() -> Iterator[MockParabola]:
         instrument.close()
 
 
+@pytest.fixture(name="empty_instrument_with_empty_submodule", scope="function")
+def _empty_instrument_with_empty_submodule() -> Iterator[Instrument]:
+    instrument = Instrument("EmptyInstrument")
+    instrument.add_submodule("A", InstrumentModule(instrument, "B"))
+    try:
+        yield instrument
+    finally:
+        instrument.close()
+
+
 @pytest.fixture(name='close_before_and_after', scope='function')
 def _close_before_and_after():
     Instrument.close_all()
@@ -320,6 +335,10 @@ def test_meta_instrument(parabola) -> None:
     assert re.search(r"gain[ \t]+:[ \t]+2", readable_snap) is not None
 
 
+def test_empty_instrument(empty_instrument_with_empty_submodule: Instrument) -> None:
+    empty_instrument_with_empty_submodule.print_readable_snapshot()
+
+
 def test_find(testdummy) -> None:
     """Test finding an existing instrument"""