fix: prevent sys.modules["langfuse"] import failures in langfuse unit tests

Three test failures caused by the real langfuse SDK import being triggered
at test time:

1. test_langfuse_prompt_management.py: Both tests create LangfusePromptManagement()
   which calls `import langfuse`. Since earlier TestLangfuseUsageDetails tests
   remove sys.modules["langfuse"] via patch.dict teardown, the real langfuse
   import runs and fails on Python 3.14 (pydantic v1 incompatibility).
   Fix: add setup_method/teardown_method to mock sys.modules["langfuse"].

2. test_langfuse.py::test_max_langfuse_clients_limit: Same root cause — creates
   LangFuseLogger() without mocking sys.modules["langfuse"].
   Fix: wrap test body with patch.dict("sys.modules", {"langfuse": mock}).

3. test_langfuse_otel.py::test_extract_langfuse_metadata_with_header_enrichment:
   Replaces sys.modules["litellm.integrations.langfuse.langfuse"] with a stub
   without restoring it, causing patch() in later tests to target the stub
   instead of the real module.
   Fix: use monkeypatch.setitem() which auto-restores after the test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Julio Quinteros Pro 2026-02-17 22:33:06 -03:00
parent 24fcc9da7c
commit 81827be215
3 changed files with 29 additions and 4 deletions

View file

@ -1,5 +1,5 @@
import os
from unittest.mock import patch
from unittest.mock import MagicMock, patch
from litellm.integrations.langfuse.langfuse_prompt_management import (
LangfusePromptManagement,
@ -7,6 +7,20 @@ from litellm.integrations.langfuse.langfuse_prompt_management import (
class TestLangfusePromptManagement:
def setup_method(self):
# Mock langfuse package to avoid triggering real import.
# The real langfuse import fails on Python 3.14 due to pydantic v1 incompatibility.
# This also prevents test-ordering issues when earlier tests remove sys.modules["langfuse"].
self._mock_langfuse = MagicMock()
self._mock_langfuse.version.__version__ = "3.0.0"
self._langfuse_patcher = patch.dict(
"sys.modules", {"langfuse": self._mock_langfuse}
)
self._langfuse_patcher.start()
def teardown_method(self):
self._langfuse_patcher.stop()
def test_get_prompt_from_id(self):
langfuse_prompt_management = LangfusePromptManagement()
with patch.object(

View file

@ -472,8 +472,15 @@ def test_max_langfuse_clients_limit():
"""
Test that the max langfuse clients limit is respected when initializing multiple clients
"""
# Mock langfuse package to avoid triggering real import.
# The real langfuse import fails on Python 3.14 due to pydantic v1 incompatibility,
# and sys.modules["langfuse"] may be absent after other tests in the suite clean up.
mock_langfuse = MagicMock()
mock_langfuse.version.__version__ = "3.0.0"
# Set max clients to 2 for testing
with patch.object(langfuse_module, "MAX_LANGFUSE_INITIALIZED_CLIENTS", 2):
with patch.dict("sys.modules", {"langfuse": mock_langfuse}), patch.object(
langfuse_module, "MAX_LANGFUSE_INITIALIZED_CLIENTS", 2
):
# Reset the counter
litellm.initialized_langfuse_clients = 0

View file

@ -157,8 +157,12 @@ class TestLangfuseOtelIntegration:
stub_module.LangFuseLogger = StubLFLogger # type: ignore
# Register stub in sys.modules so import inside method succeeds
sys.modules["litellm.integrations.langfuse.langfuse"] = stub_module # type: ignore
# Register stub in sys.modules so import inside method succeeds.
# Use monkeypatch so the real module is restored after the test runs,
# preventing sys.modules corruption that would break patch() targets in
# later tests (the patch would hit the stub while the real module's
# globals remain unpatched).
monkeypatch.setitem(sys.modules, "litellm.integrations.langfuse.langfuse", stub_module) # type: ignore
kwargs = {"litellm_params": {"metadata": {"foo": "bar"}}}
extracted = LangfuseOtelLogger._extract_langfuse_metadata(kwargs)