@@ -152,6 +152,8 @@ def test_device_loading(core: pmn.CMMCore) -> None:
152152
153153
154154# have to use capfd to capture stderr, capsys won't work
155+ # Flaky on macOS CI: capfd occasionally returns partial/null-filled reads
156+ @pytest .mark .flaky (reruns = 2 )
155157def test_core_logging (capfd : pytest .CaptureFixture , tmp_path : Path ) -> None :
156158 mmc = pmn .CMMCore ()
157159 # no file logging at start
@@ -211,6 +213,47 @@ def test_core(demo_core: pmn.CMMCore) -> None:
211213 assert isinstance (cfg , pmn .Configuration )
212214
213215
216+ def test_per_device_timeout (demo_core : pmn .CMMCore ) -> None :
217+ global_timeout = demo_core .getTimeoutMs ()
218+
219+ # No override is set initially; effective timeout equals global timeout.
220+ assert not demo_core .hasDeviceTimeout ("Camera" )
221+ assert demo_core .getDeviceTimeoutMs ("Camera" ) == global_timeout
222+
223+ demo_core .setDeviceTimeoutMs ("Camera" , global_timeout + 1234 )
224+ assert demo_core .hasDeviceTimeout ("Camera" )
225+ assert demo_core .getDeviceTimeoutMs ("Camera" ) == global_timeout + 1234
226+ # Global timeout is unaffected by the per-device override.
227+ assert demo_core .getTimeoutMs () == global_timeout
228+
229+ demo_core .unsetDeviceTimeout ("Camera" )
230+ assert not demo_core .hasDeviceTimeout ("Camera" )
231+ assert demo_core .getDeviceTimeoutMs ("Camera" ) == global_timeout
232+
233+ # The Core device cannot have a per-device override.
234+ assert not demo_core .hasDeviceTimeout ("Core" )
235+ assert demo_core .getDeviceTimeoutMs ("Core" ) == global_timeout
236+ with pytest .raises (pmn .CMMError , match = "Core device" ):
237+ demo_core .setDeviceTimeoutMs ("Core" , 1000 )
238+
239+ with pytest .raises (pmn .CMMError , match = "must be positive" ):
240+ demo_core .setDeviceTimeoutMs ("Camera" , 0 )
241+ with pytest .raises (pmn .CMMError , match = r'No device with label "Bogus"' ):
242+ demo_core .setDeviceTimeoutMs ("Bogus" , 1000 )
243+
244+
245+ def test_sequence_acquisition_unused_kwarg (demo_core : pmn .CMMCore ) -> None :
246+ # Upstream renamed the always-ignored `intervalMs` parameter to `unused`;
247+ # confirm the new keyword name is accepted by all three overloads.
248+ demo_core .startSequenceAcquisition (2 , unused = 0 , stopOnOverflow = False )
249+ _wait_until (lambda : not demo_core .isSequenceRunning ())
250+ demo_core .startSequenceAcquisition ("Camera" , 2 , unused = 0 , stopOnOverflow = False )
251+ _wait_until (lambda : not demo_core .isSequenceRunning ())
252+ demo_core .startContinuousSequenceAcquisition (unused = 0 )
253+ _wait_until (lambda : demo_core .isSequenceRunning ())
254+ demo_core .stopSequenceAcquisition ()
255+
256+
214257def test_camera_snap (demo_core : pmn .CMMCore ) -> None :
215258 assert demo_core .getCameraDevice () == "Camera"
216259 # change image dimensions to make it non-square
0 commit comments