fix(context): preserve leading underscores in _snake_to_camel key conversion (#2414)

This commit is contained in:
Bartok
2026-07-02 09:50:10 +08:00
committed by GitHub
parent bcf78d19aa
commit 0cf9fa3ece
2 changed files with 32 additions and 3 deletions
+14 -3
View File
@@ -76,9 +76,20 @@ See https://docs.getwren.ai/oss/engine/get_started/installation for full setup.
def _snake_to_camel(name: str) -> str:
"""Convert snake_case to camelCase."""
parts = name.split("_")
return parts[0] + "".join(w.capitalize() for w in parts[1:])
"""Convert snake_case to camelCase, preserving any leading underscores.
Keys like ``_instructions`` are sentinel carriers consumed downstream
under that exact name. The naive ``"_instructions".split("_")`` yields
``["", "instructions"]`` → ``"Instructions"`` — the leading underscore is
lost and the first real word is capitalized, mangling the key. Strip and
re-attach the leading underscore run so it round-trips.
"""
stripped = name.lstrip("_")
prefix = name[: len(name) - len(stripped)]
parts = stripped.split("_")
if not stripped:
return name
return prefix + parts[0] + "".join(w.capitalize() for w in parts[1:])
def _convert_keys(obj: Any) -> Any:
+18
View File
@@ -43,6 +43,24 @@ def test_snake_to_camel():
assert _snake_to_camel("name") == "name"
def test_snake_to_camel_preserves_leading_underscore():
# Sentinel keys like `_instructions` must keep their leading underscore
# and not capitalize the first real word (the naive split mangled this
# into "Instructions").
assert _snake_to_camel("_instructions") == "_instructions"
assert _snake_to_camel("_dbt_tests") == "_dbtTests"
assert _snake_to_camel("__double") == "__double"
def test_convert_keys_does_not_mangle_nested_instructions():
# A nested `_instructions` carrier must survive the camelCase pass intact;
# the top-level pop workarounds elsewhere don't protect nested ones.
obj = {"models": [{"name": "m", "_instructions": "do x"}]}
result = _convert_keys(obj)
assert result["models"][0]["_instructions"] == "do x"
assert "Instructions" not in result["models"][0]
def test_convert_keys_nested():
obj = {
"table_reference": {"catalog": "c", "schema_name": "s"},