fix(python): fan out only on JSON-array output, not any IEnumerable

The old code iterated every IEnumerable, so `output = "hello"` emitted one
item per character (a string is IEnumerable-of-char) and `output = {"a":1}`
emitted the keys as items. Now the script's output is serialized first and
the ValueKind decides: JSON array → per-element items; anything else →
single item. `output = None` remains an empty emission.

New tests cover string, dict, number, and None shapes.
This commit is contained in:
Claude
2026-08-31 11:21:55 +00:00
parent e4e55ea01a
commit 6615c5f7d0
2 changed files with 55 additions and 3 deletions

View File

@@ -59,12 +59,19 @@ public sealed class PythonTransformNode : IActionNode
string.IsNullOrEmpty(formatted) ? ex.Message : formatted);
}
if (!scope.TryGetVariable("output", out object? outputObj))
if (!scope.TryGetVariable("output", out object? outputObj) || outputObj is null)
return Task.FromResult<IReadOnlyList<IReadOnlyList<Item>>>(new[] { Array.Empty<Item>() });
// Fan out only when `output` serializes to a JSON array. A naive
// `IEnumerable` check would treat a bare string as an iterable of chars
// (`output = "hello"` → 5 items) and a bare dict as an iterable of keys.
// Serializing first and dispatching on ValueKind gives one predictable rule.
var element = JsonToPython.ToJson(outputObj);
var outItems = new List<Item>();
if (outputObj is System.Collections.IEnumerable ie)
foreach (var v in ie) outItems.Add(new Item(JsonToPython.ToJson(v)));
if (element.ValueKind == JsonValueKind.Array)
foreach (var el in element.EnumerateArray()) outItems.Add(new Item(el.Clone()));
else
outItems.Add(new Item(element));
return Task.FromResult<IReadOnlyList<IReadOnlyList<Item>>>(new[] { outItems });
}