Skip to content

Commit 1d2aa19

Browse files
authored
docs: Fix bug that caused the word "Beta" to appear twice in doc-strings (langchain-ai#17704)
The current issue: Several beta descriptions in the API Reference are duplicated. For example: `[Beta] Get a context value.[Beta] Get a context value.` for the [ContextGet class](https://api.python.langchain.com/en/latest/core_api_reference.html#module-langchain_core.beta) description. NOTE: I've tested it only with a new ut! I cannot build API Reference locally :( This PR related to langchain-ai#17615
1 parent 73edf17 commit 1d2aa19

File tree

2 files changed

+80
-15
lines changed

2 files changed

+80
-15
lines changed

libs/core/langchain_core/_api/beta_decorator.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,10 +206,9 @@ def finalize( # type: ignore
206206

207207
old_doc = inspect.cleandoc(old_doc or "").strip("\n")
208208

209+
# old_doc can be None
209210
if not old_doc:
210-
new_doc = "[*Beta*]"
211-
else:
212-
new_doc = f"[*Beta*] {old_doc}"
211+
old_doc = ""
213212

214213
# Modify the docstring to include a beta notice.
215214
notes_header = "\nNotes\n-----"
@@ -218,7 +217,7 @@ def finalize( # type: ignore
218217
addendum,
219218
]
220219
details = " ".join([component.strip() for component in components if component])
221-
new_doc += (
220+
new_doc = (
222221
f"[*Beta*] {old_doc}\n"
223222
f"{notes_header if notes_header not in old_doc else ''}\n"
224223
f".. beta::\n"

libs/core/tests/unit_tests/_api/test_beta_decorator.py

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def test_beta_function() -> None:
112112

113113
doc = beta_function.__doc__
114114
assert isinstance(doc, str)
115-
assert doc.startswith("[*Beta*] original doc")
115+
assert doc.startswith("[*Beta*] original doc")
116116

117117
assert not inspect.iscoroutinefunction(beta_function)
118118

@@ -132,7 +132,7 @@ async def test_beta_async_function() -> None:
132132

133133
doc = beta_function.__doc__
134134
assert isinstance(doc, str)
135-
assert doc.startswith("[*Beta*] original doc")
135+
assert doc.startswith("[*Beta*] original doc")
136136

137137
assert inspect.iscoroutinefunction(beta_async_function)
138138

@@ -152,7 +152,7 @@ def test_beta_method() -> None:
152152

153153
doc = obj.beta_method.__doc__
154154
assert isinstance(doc, str)
155-
assert doc.startswith("[*Beta*] original doc")
155+
assert doc.startswith("[*Beta*] original doc")
156156

157157
assert not inspect.iscoroutinefunction(obj.beta_method)
158158

@@ -173,7 +173,7 @@ async def test_beta_async_method() -> None:
173173

174174
doc = obj.beta_method.__doc__
175175
assert isinstance(doc, str)
176-
assert doc.startswith("[*Beta*] original doc")
176+
assert doc.startswith("[*Beta*] original doc")
177177

178178
assert inspect.iscoroutinefunction(obj.beta_async_method)
179179

@@ -192,7 +192,7 @@ def test_beta_classmethod() -> None:
192192

193193
doc = ClassWithBetaMethods.beta_classmethod.__doc__
194194
assert isinstance(doc, str)
195-
assert doc.startswith("[*Beta*] original doc")
195+
assert doc.startswith("[*Beta*] original doc")
196196

197197

198198
def test_beta_staticmethod() -> None:
@@ -211,7 +211,7 @@ def test_beta_staticmethod() -> None:
211211
)
212212
doc = ClassWithBetaMethods.beta_staticmethod.__doc__
213213
assert isinstance(doc, str)
214-
assert doc.startswith("[*Beta*] original doc")
214+
assert doc.startswith("[*Beta*] original doc")
215215

216216

217217
def test_beta_property() -> None:
@@ -231,13 +231,12 @@ def test_beta_property() -> None:
231231
)
232232
doc = ClassWithBetaMethods.beta_property.__doc__
233233
assert isinstance(doc, str)
234-
assert doc.startswith("[*Beta*] original doc")
234+
assert doc.startswith("[*Beta*] original doc")
235235

236236

237-
def test_whole_class_deprecation() -> None:
238-
"""Test whole class deprecation."""
237+
def test_whole_class_beta() -> None:
238+
"""Test whole class beta status."""
239239

240-
# Test whole class deprecation
241240
@beta()
242241
class BetaClass:
243242
def __init__(self) -> None:
@@ -269,6 +268,73 @@ def beta_method(self) -> str:
269268
)
270269

271270

271+
def test_whole_class_inherited_beta() -> None:
272+
"""Test whole class beta status for inherited class.
273+
274+
The original version of beta decorator created duplicates with
275+
'[*Beta*]'.
276+
"""
277+
278+
# Test whole class beta status
279+
@beta()
280+
class BetaClass:
281+
@beta()
282+
def beta_method(self) -> str:
283+
"""original doc"""
284+
return "This is a beta method."
285+
286+
@beta()
287+
class InheritedBetaClass(BetaClass):
288+
@beta()
289+
def beta_method(self) -> str:
290+
"""original doc"""
291+
return "This is a beta method 2."
292+
293+
with warnings.catch_warnings(record=True) as warning_list:
294+
warnings.simplefilter("always")
295+
296+
obj = BetaClass()
297+
assert obj.beta_method() == "This is a beta method."
298+
299+
assert len(warning_list) == 2
300+
warning = warning_list[0].message
301+
assert str(warning) == (
302+
"The class `BetaClass` is in beta. It is actively being worked on, so the "
303+
"API may change."
304+
)
305+
306+
warning = warning_list[1].message
307+
assert str(warning) == (
308+
"The function `beta_method` is in beta. It is actively being worked on, so "
309+
"the API may change."
310+
)
311+
312+
with warnings.catch_warnings(record=True) as warning_list:
313+
warnings.simplefilter("always")
314+
315+
obj = InheritedBetaClass()
316+
assert obj.beta_method() == "This is a beta method 2."
317+
318+
assert len(warning_list) == 2
319+
warning = warning_list[0].message
320+
assert str(warning) == (
321+
"The class `InheritedBetaClass` is in beta. "
322+
"It is actively being worked on, so the "
323+
"API may change."
324+
)
325+
326+
warning = warning_list[1].message
327+
assert str(warning) == (
328+
"The function `beta_method` is in beta. "
329+
"It is actively being worked on, so "
330+
"the API may change."
331+
)
332+
333+
# if [*Beta*] was inserted only once:
334+
if obj.__doc__ is not None:
335+
assert obj.__doc__.count("[*Beta*]") == 1
336+
337+
272338
# Tests with pydantic models
273339
class MyModel(BaseModel):
274340
@beta()
@@ -292,4 +358,4 @@ def test_beta_method_pydantic() -> None:
292358

293359
doc = obj.beta_method.__doc__
294360
assert isinstance(doc, str)
295-
assert doc.startswith("[*Beta*] original doc")
361+
assert doc.startswith("[*Beta*] original doc")

0 commit comments

Comments
 (0)