File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -640,7 +640,15 @@ def dispose_engine(self) -> None:
640640 """
641641 if self .engine :
642642 self .engine .dispose ()
643- logger .info ("Engine disposed successfully." )
643+ # During interpreter shutdown, logging handler streams may already be closed,
644+ # causing the framework to print "Logging error" to stderr (GH-1520).
645+ # Temporarily suppress logging errors for this teardown message.
646+ previous_raise = logging .raiseExceptions
647+ logging .raiseExceptions = False
648+ try :
649+ logger .info ("Engine disposed successfully." )
650+ finally :
651+ logging .raiseExceptions = previous_raise
644652
645653 def get_all_embeddings (self ) -> Sequence [EmbeddingDataEntry ]:
646654 """
Original file line number Diff line number Diff line change @@ -364,7 +364,15 @@ def dispose_engine(self) -> None:
364364 """
365365 if self .engine :
366366 self .engine .dispose ()
367- logger .info ("Engine disposed and all connections closed." )
367+ # During interpreter shutdown, logging handler streams may already be closed,
368+ # causing the framework to print "Logging error" to stderr (GH-1520).
369+ # Temporarily suppress logging errors for this teardown message.
370+ previous_raise = logging .raiseExceptions
371+ logging .raiseExceptions = False
372+ try :
373+ logger .info ("Engine disposed and all connections closed." )
374+ finally :
375+ logging .raiseExceptions = previous_raise
368376
369377 def export_conversations (
370378 self ,
Original file line number Diff line number Diff line change 11# Copyright (c) Microsoft Corporation.
22# Licensed under the MIT license.
33
4+ import io
5+ import logging
46import os
57import uuid
68from collections .abc import Sequence
@@ -670,6 +672,28 @@ def test_get_conversation_stats_batches_multiple_conversations(sqlite_instance):
670672 assert result [conv_ids [2 ]].message_count == 3
671673
672674
675+ def test_dispose_engine_tolerates_closed_log_stream (sqlite_instance , capsys ):
676+ """Verify dispose_engine does not raise or emit 'Logging error' when streams are closed (GH-1520)."""
677+ pyrit_logger = logging .getLogger ("pyrit" )
678+ prev_level = pyrit_logger .level
679+ pyrit_logger .setLevel (logging .INFO )
680+
681+ stream = io .StringIO ()
682+ handler = logging .StreamHandler (stream )
683+ root = logging .getLogger ()
684+ root .addHandler (handler )
685+
686+ try :
687+ stream .close ()
688+ sqlite_instance .dispose_engine ()
689+ finally :
690+ root .removeHandler (handler )
691+ pyrit_logger .setLevel (prev_level )
692+
693+ captured = capsys .readouterr ()
694+ assert "Logging error" not in captured .err
695+
696+
673697def test_create_engine_uses_static_pool_for_in_memory (sqlite_instance ):
674698 """In-memory databases must use StaticPool so all threads share one database."""
675699 from sqlalchemy .pool import StaticPool
You can’t perform that action at this time.
0 commit comments