Skip to content

Commit 0fbebf2

Browse files
committed
fix(integrations): make langchain package optional for LangchainIntegration
1 parent 567a91a commit 0fbebf2

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

sentry_sdk/integrations/langchain.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030

3131
try:
32-
from langchain.agents import AgentExecutor
3332
from langchain_core.agents import AgentFinish
3433
from langchain_core.callbacks import (
3534
BaseCallbackHandler,
@@ -72,10 +71,13 @@ def __init__(self, include_prompts=True, max_spans=1024):
7271
def setup_once():
7372
# type: () -> None
7473
manager._configure = _wrap_configure(manager._configure)
74+
try:
75+
from langchain.agents import AgentExecutor
7576

76-
if AgentExecutor is not None:
7777
AgentExecutor.invoke = _wrap_agent_executor_invoke(AgentExecutor.invoke)
7878
AgentExecutor.stream = _wrap_agent_executor_stream(AgentExecutor.stream)
79+
except ImportError:
80+
pass
7981

8082

8183
class WatchedSpan:

tests/integrations/langchain/test_langchain.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import importlib
2+
import re
3+
import sys
14
from typing import List, Optional, Any, Iterator
25
from unittest import mock
36
from unittest.mock import Mock
@@ -382,6 +385,34 @@ def test_span_origin(sentry_init, capture_events):
382385
assert span["origin"] == "auto.ai.langchain"
383386

384387

388+
def test_langchain_module_is_optional(monkeypatch):
389+
"""
390+
Test that the LangchainIntegration can be imported and set up
391+
even if the langchain module is not installed.
392+
"""
393+
394+
lc_re = re.compile(r"^langchain(\..*)?$")
395+
396+
stripped_modules = {
397+
name: mod for name, mod in sys.modules.items() if not lc_re.match(name)
398+
}
399+
400+
class HideModuleImportHook(importlib.abc.MetaPathFinder):
401+
def find_spec(self, fullname, path, target=..., /):
402+
if lc_re.match(fullname):
403+
raise ModuleNotFoundError(f"No module named '{fullname}'")
404+
return None
405+
406+
with (
407+
mock.patch.dict(sys.modules, stripped_modules, clear=True),
408+
mock.patch.object(sys, "meta_path", [HideModuleImportHook(), *sys.meta_path]),
409+
mock.patch("sentry_sdk.integrations.langchain.manager"),
410+
):
411+
from sentry_sdk.integrations.langchain import LangchainIntegration
412+
413+
LangchainIntegration().setup_once()
414+
415+
385416
def test_manual_callback_no_duplication(sentry_init):
386417
"""
387418
Test that when a user manually provides a SentryLangchainCallback,

0 commit comments

Comments
 (0)