diff --git a/craft_cli/messages.py b/craft_cli/messages.py index 8ed2549..556c12e 100644 --- a/craft_cli/messages.py +++ b/craft_cli/messages.py @@ -546,6 +546,7 @@ def __init__(self): self._printer = None self._mode = None self._initiated = False + self._stopped = False self._log_filepath = None self._log_handler = None @@ -670,6 +671,9 @@ def open_stream(self, text: str): @_init_guard def ended_ok(self) -> None: """Finish the messaging system gracefully.""" + if self._stopped: + return + self._stopped = True self._printer.stop() # type: ignore def _report_error(self, error: errors.CraftError) -> None: @@ -706,6 +710,9 @@ def _report_error(self, error: errors.CraftError) -> None: @_init_guard def error(self, error: errors.CraftError) -> None: """Handle the system's indicated error and stop machinery.""" + if self._stopped: + return + self._stopped = True self._report_error(error) self._printer.stop() # type: ignore diff --git a/tests/unit/test_messages_emitter.py b/tests/unit/test_messages_emitter.py index 8d2e893..e3057ff 100644 --- a/tests/unit/test_messages_emitter.py +++ b/tests/unit/test_messages_emitter.py @@ -404,6 +404,26 @@ def test_ended_ok(get_initiated_emitter): assert emitter.printer_calls == [call().stop()] +def test_ended_double_after_ok(get_initiated_emitter): + """Support double ending.""" + emitter = get_initiated_emitter(EmitterMode.QUIET) + emitter.ended_ok() + emitter.printer_calls.clear() + + emitter.ended_ok() + assert emitter.printer_calls == [] + + +def test_ended_double_after_error(get_initiated_emitter): + """Support double ending.""" + emitter = get_initiated_emitter(EmitterMode.QUIET) + emitter.error(CraftError("test message")) + emitter.printer_calls.clear() + + emitter.ended_ok() + assert emitter.printer_calls == [] + + # -- tests for error reporting @@ -627,3 +647,23 @@ def test_reporterror_full_complete(get_initiated_emitter): call().show(sys.stderr, full_log_message, use_timestamp=True, end_line=True), call().stop(), ] + + +def test_reporterror_double_after_ok(get_initiated_emitter): + """Support error reporting after ending.""" + emitter = get_initiated_emitter(EmitterMode.TRACE) + emitter.ended_ok() + emitter.printer_calls.clear() + + emitter.error(CraftError("test message")) + assert emitter.printer_calls == [] + + +def test_reporterror_double_after_error(get_initiated_emitter): + """Support error reporting after ending.""" + emitter = get_initiated_emitter(EmitterMode.TRACE) + emitter.error(CraftError("test message")) + emitter.printer_calls.clear() + + emitter.error(CraftError("test message")) + assert emitter.printer_calls == []