Skip to content

Commit eb80f9a

Browse files
chore: deprecate select child_run_ids in list_runs (#2066)
Soft deprecate `child_run_ids` value in `select` for: - TS: `listRuns` - Python: `Client.list_runs`, `AsyncClient.list_runs` This column will not be ported next major version of the API.
1 parent 389a701 commit eb80f9a

File tree

7 files changed

+141
-1
lines changed

7 files changed

+141
-1
lines changed

js/src/client.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ interface ListRunsParams {
227227
treeFilter?: string;
228228
/**
229229
* The values to include in the response.
230+
*
231+
* Note: The 'child_run_ids' value is deprecated and will be removed in a future version.
232+
* This field is no longer populated by the API.
230233
*/
231234
select?: string[];
232235
}
@@ -2141,6 +2144,12 @@ export class Client implements LangSmithTracingClientInterface {
21412144
order,
21422145
};
21432146

2147+
if (body.select.includes("child_run_ids")) {
2148+
warnOnce(
2149+
"Deprecated: 'child_run_ids' in the listRuns select parameter is deprecated and will be removed in a future version."
2150+
);
2151+
}
2152+
21442153
let runsYielded = 0;
21452154
for await (const runs of this._getCursorPaginatedList<Run>(
21462155
"/runs/query",

js/src/tests/client.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,4 +685,52 @@ describe("Client", () => {
685685
});
686686
});
687687
});
688+
689+
describe("listRuns", () => {
690+
it("should warn when child_run_ids is in select parameter", async () => {
691+
const consoleWarnSpy = jest
692+
.spyOn(console, "warn")
693+
.mockImplementation(() => {});
694+
695+
// Create mock fetch function
696+
const mockFetch = jest.fn().mockImplementation(async () => ({
697+
ok: true,
698+
status: 200,
699+
statusText: "OK",
700+
json: async () => ({ runs: [] }),
701+
}));
702+
703+
const client = new Client({
704+
apiKey: "org-scoped-key",
705+
fetchImplementation: mockFetch as any,
706+
});
707+
708+
// Test that warning is issued when child_run_ids is in select
709+
const runs = [];
710+
for await (const run of client.listRuns({
711+
projectId: "00000000-0000-0000-0000-000000000000",
712+
select: ["id", "name", "child_run_ids"],
713+
})) {
714+
runs.push(run);
715+
}
716+
717+
expect(consoleWarnSpy).toHaveBeenCalledWith(
718+
expect.stringMatching(
719+
"Deprecated: 'child_run_ids' in the listRuns select parameter is deprecated and will be removed in a future version."
720+
)
721+
);
722+
consoleWarnSpy.mockClear();
723+
724+
// Test that no warning is issued when child_run_ids is not in select
725+
for await (const run of client.listRuns({
726+
projectId: "00000000-0000-0000-0000-000000000000",
727+
select: ["id", "name"],
728+
})) {
729+
runs.push(run);
730+
}
731+
732+
expect(consoleWarnSpy).not.toHaveBeenCalled();
733+
consoleWarnSpy.mockRestore();
734+
});
735+
});
688736
});

python/langsmith/async_client.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import datetime
88
import json
99
import uuid
10+
import warnings
1011
from collections.abc import AsyncGenerator, AsyncIterator, Mapping, Sequence
1112
from typing import (
1213
Any,
@@ -412,6 +413,12 @@ async def list_runs(
412413
)
413414
project_ids.extend([project.id for project in projects])
414415

416+
if select and "child_run_ids" in select:
417+
warnings.warn(
418+
"The child_run_ids field is deprecated and will be removed in following versions",
419+
DeprecationWarning,
420+
)
421+
415422
body_query: dict[str, Any] = {
416423
"session": project_ids if project_ids else None,
417424
"run_type": run_type,

python/langsmith/client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2887,7 +2887,15 @@ def list_runs(
28872887
"total_tokens",
28882888
"trace_id",
28892889
]
2890+
28902891
select = select or default_select
2892+
2893+
if "child_run_ids" in select:
2894+
warnings.warn(
2895+
"The child_run_ids field is deprecated and will be removed in following versions",
2896+
DeprecationWarning,
2897+
)
2898+
28912899
body_query: dict[str, Any] = {
28922900
"session": project_ids if project_ids else None,
28932901
"run_type": run_type,

python/langsmith/schemas.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ class Run(RunBase):
424424
session_id: Optional[UUID] = None
425425
"""The project ID this run belongs to."""
426426
child_run_ids: Optional[list[UUID]] = None
427-
"""The child run IDs of this run."""
427+
"""Deprecated: The child run IDs of this run."""
428428
child_runs: Optional[list[Run]] = None
429429
"""The child runs of this run, if instructed to load using the client
430430
These are not populated by default, as it is a heavier query to make."""
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""Test the AsyncClient."""
2+
3+
import warnings
4+
from unittest import mock
5+
from uuid import uuid4
6+
7+
import pytest
8+
9+
from langsmith import AsyncClient
10+
11+
12+
@mock.patch("langsmith.async_client.httpx.AsyncClient")
13+
@pytest.mark.asyncio
14+
async def test_list_runs_child_run_ids_deprecation_warning(
15+
mock_client_cls: mock.Mock,
16+
) -> None:
17+
mock_httpx_client = mock.AsyncMock()
18+
mock_client_cls.return_value = mock_httpx_client
19+
20+
# Mock the response for list_runs
21+
mock_response = mock.Mock()
22+
mock_response.json.return_value = {"runs": []}
23+
mock_response.status_code = 200
24+
mock_response.raise_for_status = mock.Mock()
25+
mock_httpx_client.request.return_value = mock_response
26+
27+
client = AsyncClient()
28+
29+
# Test that deprecation warning is raised when child_run_ids is in select
30+
with pytest.warns(DeprecationWarning, match="child_run_ids field is deprecated"):
31+
async for _ in client.list_runs(
32+
project_id=uuid4(),
33+
select=["id", "name", "child_run_ids"],
34+
):
35+
pass
36+
37+
# Test that no warning is raised when child_run_ids is not in select
38+
with warnings.catch_warnings():
39+
warnings.simplefilter("error", DeprecationWarning)
40+
async for _ in client.list_runs(project_id=uuid4(), select=["id", "name"]):
41+
pass

python/tests/unit_tests/test_client.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4326,3 +4326,30 @@ def track_processing(runs):
43264326
file_obj.close()
43274327
except Exception:
43284328
pass
4329+
4330+
4331+
@mock.patch("langsmith.client.requests.Session")
4332+
def test_list_runs_child_run_ids_deprecation_warning(
4333+
mock_session_cls: mock.Mock,
4334+
) -> None:
4335+
"""Test that using child_run_ids in select parameter raises a deprecation warning."""
4336+
4337+
mock_session = mock.Mock()
4338+
mock_session_cls.return_value = mock_session
4339+
mock_session.request.return_value.json.return_value = {"runs": []}
4340+
4341+
client = Client()
4342+
4343+
# Test that deprecation warning is raised when child_run_ids is in select
4344+
with pytest.warns(DeprecationWarning, match="child_run_ids field is deprecated"):
4345+
list(
4346+
client.list_runs(
4347+
project_id=uuid.uuid4(),
4348+
select=["id", "name", "child_run_ids"],
4349+
)
4350+
)
4351+
4352+
# Test that no warning is raised when child_run_ids is not in select
4353+
with warnings.catch_warnings():
4354+
warnings.simplefilter("error", DeprecationWarning)
4355+
list(client.list_runs(project_id=uuid.uuid4(), select=["id", "name"]))

0 commit comments

Comments
 (0)