Update stiching to differentiate bwtween stitchers that use a thread and those that block

This commit is contained in:
Julian Stirling 2025-08-06 17:47:33 +01:00
parent 5f092835ac
commit cd311f08bf
3 changed files with 11 additions and 18 deletions

View file

@ -44,7 +44,12 @@ def validate_command(cmd: list[str]):
class BaseStitcher:
"""A base stitching class for all stitchers. Don't initialise this directly."""
"""A base stitching class for all stitchers. Don't initialise this directly.
The base class has no way to run the command. Child classes should either implement
a ``start``, ``running``, and ``wait`` methods if they stitch in a thread, or ``run``
if they stitch in this thread and return once complete.
"""
def __init__(self, images_dir: str, *, overlap: float, correlation_resize: float):
"""Initialise a stitcher.
@ -104,15 +109,6 @@ class BaseStitcher:
"Invalid directory path: Contains unsafe characters."
)
def start(self) -> None:
"""Start stitching a stitching process.
This should be overridden by any child class.
"""
raise NotImplementedError(
"Child stitchers should implement their own ``start`` method."
)
class PreviewStitcher(BaseStitcher):
"""A stitcher for stitching an ongoing scan in preview mode.
@ -262,7 +258,7 @@ class FinalStitcher(BaseStitcher):
)
return overlap, correlation_resize
def start(
def run(
self,
cancel: lt.deps.CancelHook,
) -> None:

View file

@ -715,7 +715,7 @@ class SmartScanThing(lt.Thing):
)
try:
# start the final stitch, providing the cancel hook to allow aborting
final_stitcher.start(cancel)
final_stitcher.run(cancel)
except lt.exceptions.InvocationCancelledError:
# Sleep for 1 second just to allow invocation logs to pass to user.
time.sleep(1)

View file

@ -54,9 +54,6 @@ def test_base_stitcher():
]
stitcher = BaseStitcher(FAKE_DIR, overlap=overlap, correlation_resize=0.5)
assert stitcher.command == expected_command
# check that a BaseStitcher can't start
with pytest.raises(NotImplementedError):
stitcher.start()
def test_preview_stitcher_command():
@ -227,7 +224,7 @@ def test_final_stitching_command(caplog, mocker):
FAKE_DIR, logger=LOGGER, overlap=0.1, correlation_resize=0.5
)
# For the final stitcher it will always complete before returning.
stitcher.start(cancel=lt.deps.CancelHook(id=uuid.uuid4()))
stitcher.run(cancel=lt.deps.CancelHook(id=uuid.uuid4()))
# The mock command logs the inputs (but not the initial command) and the
# stitcher logs # "Stitching complete" when it ends.
assert len(caplog.records) == len(FINAL_EXPECTED_COMMAND)
@ -250,7 +247,7 @@ def test_final_stitching_command_cancelled(caplog, mocker):
cancel_hook = lt.deps.CancelHook(id=uuid.uuid4())
# Start stitching in a thread.
thread = threading.Thread(target=stitcher.start, kwargs={"cancel": cancel_hook})
thread = threading.Thread(target=stitcher.run, kwargs={"cancel": cancel_hook})
thread.start()
# Sleep long enough for at least 1 log.
sleep(0.5)
@ -273,4 +270,4 @@ def test_final_stitching_command_error(caplog, mocker):
# than echo.
stitcher._extra_args = ["ERROR"]
with pytest.raises(ChildProcessError):
stitcher.start(cancel=lt.deps.CancelHook(id=uuid.uuid4()))
stitcher.run(cancel=lt.deps.CancelHook(id=uuid.uuid4()))