Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions libs/langchain/langchain/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
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

Expand All @@ -26,6 +28,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
Expand Down
4 changes: 4 additions & 0 deletions libs/langchain/langchain/_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@
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",
]
178 changes: 99 additions & 79 deletions libs/langchain/langchain/_api/deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -262,7 +186,7 @@ def finalize( # type: ignore

def emit_warning() -> None:
"""Emit the warning."""
_warn_deprecated(
warn_deprecated(
since,
message=_message,
name=_name,
Expand Down Expand Up @@ -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,
)
10 changes: 10 additions & 0 deletions libs/langchain/langchain/chains/llm_symbolic_math/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
)
6 changes: 3 additions & 3 deletions libs/langchain/tests/unit_tests/_api/test_deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pytest

from langchain._api.deprecation import _warn_deprecated, deprecated
from langchain._api.deprecation import deprecated, warn_deprecated
from langchain.pydantic_v1 import BaseModel


Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down