InstrumentModule keeps appending to name_parts when Instrument is a Mock
haroldmeerwaldt opened this issue · comments
Hi there,
I am encountering the following:
InstrumentModule keeps appending to name_parts at each call when Instrument is a Mock.
This does not happen when an actual Instrument is passed as parent (set use_mock=False).
Steps to reproduce
from unittest.mock import Mock
from qcodes import Instrument
from qcodes.instrument import InstrumentModule
use_mock = True
if use_mock:
inst = Mock()
inst.name_parts = ["inst"]
else:
inst = Instrument("inst")
im0 = InstrumentModule(inst, "im0")
im1 = InstrumentModule(inst, "im1")
for _ in range(3):
print(f"{im0.name_parts=}")
for _ in range(3):
print(f"{im1.name_parts=}")
for _ in range(3):
print(f"{inst.name_parts=}")
for _ in range(3):
print(f"{inst.name=}")
for _ in range(3):
print(f"{im0.name=}")
for _ in range(3):
print(f"{im1.name=}")
Expected behaviour
I expected the name of the InstrumentModules to be "inst_im0" and "inst_im0"
Actual behaviour
What happens is that the "_im0" gets appended to the name each time name_parts
of the InstrumentModule is called:
im0.name_parts=['inst', 'im0']
im0.name_parts=['inst', 'im0', 'im0']
im0.name_parts=['inst', 'im0', 'im0', 'im0']
im1.name_parts=['inst', 'im0', 'im0', 'im0', 'im1']
im1.name_parts=['inst', 'im0', 'im0', 'im0', 'im1', 'im1']
im1.name_parts=['inst', 'im0', 'im0', 'im0', 'im1', 'im1', 'im1']
inst.name_parts=['inst', 'im0', 'im0', 'im0', 'im1', 'im1', 'im1']
inst.name_parts=['inst', 'im0', 'im0', 'im0', 'im1', 'im1', 'im1']
inst.name_parts=['inst', 'im0', 'im0', 'im0', 'im1', 'im1', 'im1']
inst.name=<Mock name='mock.name' id='2081958499568'>
inst.name=<Mock name='mock.name' id='2081958499568'>
inst.name=<Mock name='mock.name' id='2081958499568'>
im0.name='inst_im0_im0_im0_im1_im1_im1_im0'
im0.name='inst_im0_im0_im0_im1_im1_im1_im0_im0'
im0.name='inst_im0_im0_im0_im1_im1_im1_im0_im0_im0'
im1.name='inst_im0_im0_im0_im1_im1_im1_im0_im0_im0_im1'
im1.name='inst_im0_im0_im0_im1_im1_im1_im0_im0_im0_im1_im1'
im1.name='inst_im0_im0_im0_im1_im1_im1_im0_im0_im0_im1_im1_im1'
The .name_parts
property of InstrumentModule is:
@property
def name_parts(self) -> List[str]:
name_parts = self._parent.name_parts
name_parts.append(self.short_name)
return name_parts
I think this is okay when self._parent.name_parts
is a property and name_parts
becomes a copy. If you put in an instrument whose .name_parts
is not a property, name_parts
becomes a reference and self.short_name
is appended to the instrument's .name_parts
at each call.
I propose to replace this function by:
@property
def name_parts(self) -> list[str]:
return self._parent.name_parts + [self.short_name]
System
Windows 10
qcodes 0.33.0
@haroldmeerwaldt thank you for describing and reporting! sounds fair! would you be willing to open a PR with this change?
we could also trick a bit and don't depends on _parent.name_parts
being a list by doing:
@property
def name_parts(self) -> list[str]:
return list(self._parent.name_parts) + [self.short_name]
The extra list
sounds good, no need to depend on the static typing. I'll work on a PR.
@astafan8 do you also want a test to prevent this behaviour from re-occurring? Or is this such a special case, and you don't want to unit test properties? (If yes, it goes here?: https://github.com/QCoDeS/Qcodes/blob/master/qcodes/tests/test_channels.py#L72)
No worries. I will go ahead and mark this as closed by #4257 then