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
29 changes: 29 additions & 0 deletions tests/tool_parsers/test_gemma4_tool_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,26 @@ def test_empty_value_after_other_keys_partial_withheld(self):
result = _parse_gemma4_args('name:<|"|>test<|"|>,flag:', partial=True)
assert result == {"name": "test"}

def test_trailing_dot_float_partial_withheld(self):
"""Bare float ending with '.' is withheld in partial mode.

Regression test for #42047: float("108.") → 108.0 causes
streaming diff corruption (108.0 → 108.2 becomes 108.02).
"""
# Single key with trailing dot — withheld entirely
result = _parse_gemma4_args("left:108.,right:22.8", partial=True)
assert result == {}

# Stable key before trailing-dot key — stable key is kept
result = _parse_gemma4_args(
'name:<|"|>test<|"|>,score:3.,count:1', partial=True
)
assert result == {"name": "test"}

# Non-partial mode parses trailing dot normally
result = _parse_gemma4_args("left:108.,right:22.8", partial=False)
assert result == {"left": 108.0, "right": 22.8}

@pytest.mark.timeout(5)
def test_malformed_partial_array(self):
result = _parse_gemma4_args(":[t:[]")
Expand Down Expand Up @@ -164,6 +184,15 @@ def test_stray_closing_bracket(self):
result = _parse_gemma4_array("42,]trailing")
assert result == [42]

def test_trailing_dot_float_partial_withheld(self):
"""Array elements with trailing dot withheld in partial mode."""
result = _parse_gemma4_array("108.,22.8", partial=True)
assert result == []

# Stable elements before trailing-dot element are kept
result = _parse_gemma4_array("42,108.,3", partial=True)
assert result == [42]


# ---------------------------------------------------------------------------
# Non-streaming extraction tests
Expand Down
12 changes: 12 additions & 0 deletions vllm/tool_parsers/gemma4_tool_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,14 @@ def _parse_gemma4_args(args_str: str, *, partial: bool = False) -> dict:
i,
)
break
if partial:
raw_val = args_str[val_start:i].strip()
if raw_val.endswith("."):
# Trailing dot means decimal digits may still arrive
# (e.g. "108." may become "108.2"). Parsing now would
# yield float("108.") == 108.0, whose json repr "108.0"
# corrupts the streaming diff when the true digit lands.
break
result[key] = _parse_gemma4_value(args_str[val_start:i])

return result
Expand Down Expand Up @@ -294,6 +302,10 @@ def _parse_gemma4_array(arr_str: str, *, partial: bool = False) -> list:
i,
)
break
if partial:
raw_val = arr_str[val_start:i].strip()
if raw_val.endswith("."):
break
items.append(_parse_gemma4_value(arr_str[val_start:i]))

return items
Expand Down
Loading