From 0938968a201f7c2334f5ae221f95cc24c4c414de Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 12 Jun 2025 00:37:20 +0000 Subject: [PATCH] Fix Python 3.11 validation test failures: Remove global logger state and improve error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove global _litellm_logger variable that could interfere with exception propagation - Add proper error handling around logger.setLevel() operations - Update tests to reflect removal of global caching - Ensure context manager is fully isolated and doesn't affect validation methods Co-Authored-By: João --- src/crewai/llm.py | 17 ++++++++-------- tests/test_sys_stream_hijacking.py | 32 ++++++++++++------------------ 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/crewai/llm.py b/src/crewai/llm.py index 7a7ee4950..daaa60ee5 100644 --- a/src/crewai/llm.py +++ b/src/crewai/llm.py @@ -201,16 +201,11 @@ def suppress_warnings(): yield -_litellm_logger = None - @contextmanager def suppress_litellm_output(): """Contextually suppress litellm-related logging output during LLM calls.""" - global _litellm_logger - if _litellm_logger is None: - _litellm_logger = logging.getLogger("litellm") - - original_level = _litellm_logger.level + litellm_logger = logging.getLogger("litellm") + original_level = litellm_logger.level warning_patterns = [ ".*give feedback.*", @@ -224,14 +219,18 @@ def suppress_litellm_output(): for pattern in warning_patterns: warnings.filterwarnings("ignore", message=pattern) - _litellm_logger.setLevel(logging.WARNING) + try: + litellm_logger.setLevel(logging.WARNING) + except Exception as e: + logging.debug(f"Error setting logger level: {e}") + yield except Exception as e: logging.debug(f"Error in litellm output suppression: {e}") raise finally: try: - _litellm_logger.setLevel(original_level) + litellm_logger.setLevel(original_level) except Exception as e: logging.debug(f"Error restoring logger level: {e}") diff --git a/tests/test_sys_stream_hijacking.py b/tests/test_sys_stream_hijacking.py index 7a352dc5c..fdf99e7df 100644 --- a/tests/test_sys_stream_hijacking.py +++ b/tests/test_sys_stream_hijacking.py @@ -136,28 +136,22 @@ def test_concurrent_llm_calls(): assert all("test response" in result for result in results) -def test_logger_caching_performance(): - """Test that logger instance is cached for performance.""" +def test_logger_performance(): + """Test that logger operations work correctly without global caching.""" from crewai.llm import suppress_litellm_output - import crewai.llm - original_logger = crewai.llm._litellm_logger - crewai.llm._litellm_logger = None - - try: - with patch('logging.getLogger') as mock_get_logger: - mock_logger = MagicMock() - mock_get_logger.return_value = mock_logger + with patch('logging.getLogger') as mock_get_logger: + mock_logger = MagicMock() + mock_get_logger.return_value = mock_logger + + with suppress_litellm_output(): + pass + + with suppress_litellm_output(): + pass - with suppress_litellm_output(): - pass - - with suppress_litellm_output(): - pass - - mock_get_logger.assert_called_once_with("litellm") - finally: - crewai.llm._litellm_logger = original_logger + assert mock_get_logger.call_count == 2 + mock_get_logger.assert_called_with("litellm") def test_suppression_error_handling():