Skip to content

Commit 48a8909

Browse files
authored
fix(python): legacy replicas conversion (#1908)
This PR fixes the logic for converting legacy replicas in `run_trees`. We were incorrectly expecting lists when legacy replica items were actually tuples
1 parent 5b27ad8 commit 48a8909

File tree

4 files changed

+39
-28
lines changed

4 files changed

+39
-28
lines changed

python/langsmith/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
# Avoid calling into importlib on every call to __version__
2323

24-
__version__ = "0.4.12"
24+
__version__ = "0.4.13"
2525
version = __version__ # for backwards compatibility
2626

2727

python/langsmith/run_trees.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,10 @@ def from_header(cls, header_value: Optional[str]) -> _Baggage:
927927
replicas_data = json.loads(urllib.parse.unquote(value))
928928
parsed_replicas: list[WriteReplica] = []
929929
for replica_item in replicas_data:
930-
if isinstance(replica_item, list) and len(replica_item) == 2:
930+
if (
931+
isinstance(replica_item, (tuple, list))
932+
and len(replica_item) == 2
933+
):
931934
# Convert legacy format to WriteReplica
932935
parsed_replicas.append(
933936
WriteReplica(
@@ -991,7 +994,7 @@ def to_header(self) -> str:
991994
def _parse_write_replicas_from_env_var(env_var: Optional[str]) -> list[WriteReplica]:
992995
"""Parse write replicas from LANGSMITH_RUNS_ENDPOINTS environment variable value.
993996
994-
Supports array format [{"api_url": "x", "api_key": "y"}] and object format
997+
Supports array format [{"api_url": "x", "api_key": "y"}] and object format
995998
{"url": "key"}.
996999
"""
9971000
if not env_var:

python/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "langsmith"
7-
version = "0.4.12"
7+
version = "0.4.13"
88
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
99
authors = [
1010
{name = "LangChain", email = "[email protected]"},

python/tests/unit_tests/test_replica_endpoints.py

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -345,11 +345,13 @@ class TestParseWriteReplicasFromEnvVar:
345345

346346
def test_parse_new_array_format(self):
347347
"""Test parsing new array format."""
348-
env_var = json.dumps([
349-
{"api_url": "https://api.example.com", "api_key": "key1"},
350-
{"api_url": "https://api.example.com", "api_key": "key2"},
351-
{"api_url": "https://api.example.com", "api_key": "key3"},
352-
])
348+
env_var = json.dumps(
349+
[
350+
{"api_url": "https://api.example.com", "api_key": "key1"},
351+
{"api_url": "https://api.example.com", "api_key": "key2"},
352+
{"api_url": "https://api.example.com", "api_key": "key3"},
353+
]
354+
)
353355

354356
with patch.dict(
355357
os.environ, {"LANGSMITH_ENDPOINT": "", "LANGCHAIN_ENDPOINT": ""}, clear=True
@@ -396,10 +398,12 @@ def test_parse_object_format(self):
396398
def test_parse_url_trailing_slash_removal(self):
397399
"""Test that trailing slashes are removed from URLs."""
398400
# Test with new array format
399-
env_var = json.dumps([
400-
{"api_url": "https://api.example.com/", "api_key": "key1"},
401-
{"api_url": "https://other.example.com/path/", "api_key": "key2"},
402-
])
401+
env_var = json.dumps(
402+
[
403+
{"api_url": "https://api.example.com/", "api_key": "key1"},
404+
{"api_url": "https://other.example.com/path/", "api_key": "key2"},
405+
]
406+
)
403407

404408
with patch.dict(
405409
os.environ, {"LANGSMITH_ENDPOINT": "", "LANGCHAIN_ENDPOINT": ""}, clear=True
@@ -416,9 +420,11 @@ def test_parse_url_trailing_slash_removal(self):
416420
assert "https://other.example.com/path/" not in urls
417421

418422
# Test with object format
419-
env_var2 = json.dumps({
420-
"https://object.example.com/": "object-key",
421-
})
423+
env_var2 = json.dumps(
424+
{
425+
"https://object.example.com/": "object-key",
426+
}
427+
)
422428

423429
with patch.dict(
424430
os.environ, {"LANGSMITH_ENDPOINT": "", "LANGCHAIN_ENDPOINT": ""}, clear=True
@@ -505,14 +511,16 @@ def test_parse_invalid_json(self):
505511

506512
def test_parse_new_array_format_invalid_items(self):
507513
"""Test parsing new array format with invalid items."""
508-
env_var = json.dumps([
509-
{"api_url": "https://valid.example.com", "api_key": "valid-key"},
510-
"invalid-string-item",
511-
{"api_url": "https://missing-key.example.com"}, # missing api_key
512-
{"api_key": "missing-url-key"}, # missing api_url
513-
{"api_url": 123, "api_key": "invalid-url-type"}, # invalid api_url type
514-
{"api_url": "https://invalid-key-type.example.com", "api_key": 456},
515-
])
514+
env_var = json.dumps(
515+
[
516+
{"api_url": "https://valid.example.com", "api_key": "valid-key"},
517+
"invalid-string-item",
518+
{"api_url": "https://missing-key.example.com"}, # missing api_key
519+
{"api_key": "missing-url-key"}, # missing api_url
520+
{"api_url": 123, "api_key": "invalid-url-type"}, # invalid api_url type
521+
{"api_url": "https://invalid-key-type.example.com", "api_key": 456},
522+
]
523+
)
516524

517525
with patch.dict(
518526
os.environ, {"LANGSMITH_ENDPOINT": "", "LANGCHAIN_ENDPOINT": ""}, clear=True
@@ -677,10 +685,10 @@ def test_baggage_parsing_tuple_format(self):
677685

678686
from langsmith.run_trees import _Baggage
679687

680-
# tuple format: [project_name, updates]
688+
# tuple format: (project_name, updates)
681689
tuple_replicas = [
682-
["replica-project-1", {"environment": "staging"}],
683-
["replica-project-2", None],
690+
("replica-project-1", {"environment": "staging"}),
691+
("replica-project-2", None),
684692
]
685693

686694
baggage_value = (
@@ -745,7 +753,7 @@ def test_baggage_parsing_mixed_format(self):
745753

746754
# Mixed format: both tuple and new
747755
mixed_replicas = [
748-
["tuple-project", {"tuple": "true"}], # tuple format
756+
("tuple-project", {"tuple": "true"}), # tuple format
749757
{
750758
"api_url": "https://new.example.com",
751759
"api_key": "new-key",

0 commit comments

Comments
 (0)