diff --git a/libs/langchain/langchain/__init__.py b/libs/langchain/langchain/__init__.py index c22d789cae..feef1a7ee8 100644 --- a/libs/langchain/langchain/__init__.py +++ b/libs/langchain/langchain/__init__.py @@ -4,6 +4,8 @@ import warnings from importlib import metadata from typing import TYPE_CHECKING, Any, Optional +from langchain._api.deprecation import surface_langchain_deprecation_warnings + if TYPE_CHECKING: from langchain.schema import BaseCache @@ -40,6 +42,10 @@ def _warn_on_import(name: str) -> None: ) +# Surfaces Deprecation and Pending Deprecation warnings from langchain. +surface_langchain_deprecation_warnings() + + def __getattr__(name: str) -> Any: if name == "MRKLChain": from langchain.agents import MRKLChain diff --git a/libs/langchain/langchain/_api/__init__.py b/libs/langchain/langchain/_api/__init__.py index 168a99bcfd..e013a72129 100644 --- a/libs/langchain/langchain/_api/__init__.py +++ b/libs/langchain/langchain/_api/__init__.py @@ -13,10 +13,14 @@ from .deprecation import ( LangChainDeprecationWarning, deprecated, suppress_langchain_deprecation_warning, + surface_langchain_deprecation_warnings, + warn_deprecated, ) __all__ = [ "deprecated", "LangChainDeprecationWarning", "suppress_langchain_deprecation_warning", + "surface_langchain_deprecation_warnings", + "warn_deprecated", ] diff --git a/libs/langchain/langchain/_api/deprecation.py b/libs/langchain/langchain/_api/deprecation.py index ccc8e39716..6919504351 100644 --- a/libs/langchain/langchain/_api/deprecation.py +++ b/libs/langchain/langchain/_api/deprecation.py @@ -21,84 +21,8 @@ class LangChainDeprecationWarning(DeprecationWarning): """A class for issuing deprecation warnings for LangChain users.""" -def _warn_deprecated( - since: str, - *, - message: str = "", - name: str = "", - alternative: str = "", - pending: bool = False, - obj_type: str = "", - addendum: str = "", - removal: str = "", -) -> None: - """Display a standardized deprecation. - - Arguments: - since : str - The release at which this API became deprecated. - message : str, optional - Override the default deprecation message. The %(since)s, - %(name)s, %(alternative)s, %(obj_type)s, %(addendum)s, - and %(removal)s format specifiers will be replaced by the - values of the respective arguments passed to this function. - name : str, optional - The name of the deprecated object. - alternative : str, optional - An alternative API that the user may use in place of the - deprecated API. The deprecation warning will tell the user - about this alternative if provided. - pending : bool, optional - If True, uses a PendingDeprecationWarning instead of a - DeprecationWarning. Cannot be used together with removal. - obj_type : str, optional - The object type being deprecated. - addendum : str, optional - Additional text appended directly to the final message. - removal : str, optional - The expected removal version. With the default (an empty - string), a removal version is automatically computed from - since. Set to other Falsy values to not schedule a removal - date. Cannot be used together with pending. - """ - if pending and removal: - raise ValueError("A pending deprecation cannot have a scheduled removal") - - if not pending: - if not removal: - removal = f"in {removal}" if removal else "within ?? minor releases" - raise NotImplementedError( - f"Need to determine which default deprecation schedule to use. " - f"{removal}" - ) - else: - removal = f"in {removal}" - - if not message: - message = "" - - if obj_type: - message += f"The {obj_type} `{name}`" - else: - message += f"`{name}`" - - if pending: - message += " will be deprecated in a future version" - else: - message += f" was deprecated in LangChain {since}" - - if removal: - message += f" and will be removed {removal}" - - if alternative: - message += f". Use {alternative} instead." - - if addendum: - message += f" {addendum}" - - warning_cls = PendingDeprecationWarning if pending else LangChainDeprecationWarning - warning = warning_cls(message) - warnings.warn(warning, category=LangChainDeprecationWarning, stacklevel=2) +class LangChainPendingDeprecationWarning(PendingDeprecationWarning): + """A class for issuing deprecation warnings for LangChain users.""" # PUBLIC API @@ -262,7 +186,7 @@ def deprecated( def emit_warning() -> None: """Emit the warning.""" - _warn_deprecated( + warn_deprecated( since, message=_message, name=_name, @@ -318,4 +242,100 @@ def suppress_langchain_deprecation_warning() -> Generator[None, None, None]: """Context manager to suppress LangChainDeprecationWarning.""" with warnings.catch_warnings(): warnings.simplefilter("ignore", LangChainDeprecationWarning) + warnings.simplefilter("ignore", LangChainPendingDeprecationWarning) yield + + +def warn_deprecated( + since: str, + *, + message: str = "", + name: str = "", + alternative: str = "", + pending: bool = False, + obj_type: str = "", + addendum: str = "", + removal: str = "", +) -> None: + """Display a standardized deprecation. + + Arguments: + since : str + The release at which this API became deprecated. + message : str, optional + Override the default deprecation message. The %(since)s, + %(name)s, %(alternative)s, %(obj_type)s, %(addendum)s, + and %(removal)s format specifiers will be replaced by the + values of the respective arguments passed to this function. + name : str, optional + The name of the deprecated object. + alternative : str, optional + An alternative API that the user may use in place of the + deprecated API. The deprecation warning will tell the user + about this alternative if provided. + pending : bool, optional + If True, uses a PendingDeprecationWarning instead of a + DeprecationWarning. Cannot be used together with removal. + obj_type : str, optional + The object type being deprecated. + addendum : str, optional + Additional text appended directly to the final message. + removal : str, optional + The expected removal version. With the default (an empty + string), a removal version is automatically computed from + since. Set to other Falsy values to not schedule a removal + date. Cannot be used together with pending. + """ + if pending and removal: + raise ValueError("A pending deprecation cannot have a scheduled removal") + + if not pending: + if not removal: + removal = f"in {removal}" if removal else "within ?? minor releases" + raise NotImplementedError( + f"Need to determine which default deprecation schedule to use. " + f"{removal}" + ) + else: + removal = f"in {removal}" + + if not message: + message = "" + + if obj_type: + message += f"The {obj_type} `{name}`" + else: + message += f"`{name}`" + + if pending: + message += " will be deprecated in a future version" + else: + message += f" was deprecated in LangChain {since}" + + if removal: + message += f" and will be removed {removal}" + + if alternative: + message += f". Use {alternative} instead." + + if addendum: + message += f" {addendum}" + + warning_cls = ( + LangChainPendingDeprecationWarning if pending else LangChainDeprecationWarning + ) + warning = warning_cls(message) + warnings.warn(warning, category=LangChainDeprecationWarning, stacklevel=2) + + +def surface_langchain_deprecation_warnings() -> None: + """Unmute LangChain deprecation warnings.""" + warnings.filterwarnings( + "default", + category=LangChainPendingDeprecationWarning, + ) + + warnings.filterwarnings( + "default", + category=LangChainDeprecationWarning, + ) diff --git a/libs/langchain/langchain/chains/llm_symbolic_math/__init__.py b/libs/langchain/langchain/chains/llm_symbolic_math/__init__.py index d6cde9105a..6ba7b01959 100644 --- a/libs/langchain/langchain/chains/llm_symbolic_math/__init__.py +++ b/libs/langchain/langchain/chains/llm_symbolic_math/__init__.py @@ -2,3 +2,13 @@ Heavily borrowed from llm_math, wrapper for SymPy """ +from langchain._api import warn_deprecated + +warn_deprecated( + since="0.0.304", + message=( + "On 2023-10-06 this module will be moved to langchain-experimental as " + "it relies on sympy https://github.com/sympy/sympy/issues/10805" + ), + pending=True, +) diff --git a/libs/langchain/tests/unit_tests/_api/test_deprecation.py b/libs/langchain/tests/unit_tests/_api/test_deprecation.py index 7b6b359cbf..cecb034d4d 100644 --- a/libs/langchain/tests/unit_tests/_api/test_deprecation.py +++ b/libs/langchain/tests/unit_tests/_api/test_deprecation.py @@ -3,7 +3,7 @@ from typing import Any, Dict import pytest -from langchain._api.deprecation import _warn_deprecated, deprecated +from langchain._api.deprecation import deprecated, warn_deprecated from langchain.pydantic_v1 import BaseModel @@ -55,7 +55,7 @@ def test_warn_deprecated(kwargs: Dict[str, Any], expected_message: str) -> None: with warnings.catch_warnings(record=True) as warning_list: warnings.simplefilter("always") - _warn_deprecated(**kwargs) + warn_deprecated(**kwargs) assert len(warning_list) == 1 warning = warning_list[0].message @@ -65,7 +65,7 @@ def test_warn_deprecated(kwargs: Dict[str, Any], expected_message: str) -> None: def test_undefined_deprecation_schedule() -> None: """This test is expected to fail until we defined a deprecation schedule.""" with pytest.raises(NotImplementedError): - _warn_deprecated("1.0.0", pending=False) + warn_deprecated("1.0.0", pending=False) @deprecated(since="2.0.0", removal="3.0.0", pending=False)