fix(core): make removal optional in warn_deprecated (#37056)

Drop the `NotImplementedError` branch in `warn_deprecated` so callers
can pass `pending=False` without specifying a `removal` version. The
previous behavior contradicted the docstring (which claimed an empty
default would auto-compute a removal version) — no such computation
existed; the function just raised a placeholder "Need to determine which
default deprecation schedule to use" error.
This commit is contained in:
Mason Daugherty
2026-04-28 11:05:31 -04:00
committed by GitHub
parent 5790244b95
commit 37be34be82
2 changed files with 15 additions and 18 deletions

View File

@@ -136,9 +136,8 @@ def deprecated(
addendum: Additional text appended directly to the final message.
removal: 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.
With the default (an empty string), no removal version is shown in the
warning message.
Cannot be used together with pending.
package: The package of the deprecated object.
@@ -472,21 +471,13 @@ def warn_deprecated(
addendum: Additional text appended directly to the final message.
removal: 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.
With the default (an empty string), no removal version is shown in the
warning message.
Cannot be used together with pending.
package: The package of the deprecated object.
"""
if not pending:
if not removal:
removal = f"in {removal}" if removal else "within ?? minor releases"
msg = (
f"Need to determine which default deprecation schedule to use. "
f"{removal}"
)
raise NotImplementedError(msg)
if not pending and removal:
removal = f"in {removal}"
if not message:

View File

@@ -71,10 +71,16 @@ def test_warn_deprecated(kwargs: dict[str, Any], expected_message: str) -> None:
assert str(warning) == expected_message
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)
def test_warn_deprecated_without_removal() -> None:
"""`removal` is optional; warning omits the removal phrase when not provided."""
with warnings.catch_warnings(record=True) as warning_list:
warnings.simplefilter("always")
warn_deprecated("1.0.0", name="SomeFunction", pending=False)
assert len(warning_list) == 1
message = str(warning_list[0].message)
assert message == "`SomeFunction` was deprecated in LangChain 1.0.0"
assert "will be removed" not in message
@deprecated(since="2.0.0", removal="3.0.0", pending=False)