Skip to content

Commit cef00a1

Browse files
jawwad-aliclaude
andauthored
fix(workflows): list-literal expression ignores trailing/empty commas (#3631)
A workflow list-literal expression with a trailing (or leading/double) comma — '{{ [1, 2,] }}' — evaluated to [1, 2, None]: _split_top_level_commas returns a trailing empty segment, which _evaluate_simple_expression resolves as an empty dot-path to None. That silently widens membership tests and renders a stray None in joins. Python and Jinja2 both tolerate trailing commas. Drop whitespace-empty segments from the comprehension. An intentional empty-string element ('') survives because its segment strips to "''" (truthy), so ['', 'a'] is preserved. Completes the quoted-comma handling from #3134. Test: [1, 2,] and [1,, 2] -> [1, 2]; ['', 'a'] -> ['', 'a'] (fails before: trailing None). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 03f9013 commit cef00a1

2 files changed

Lines changed: 15 additions & 0 deletions

File tree

src/specify_cli/workflows/expressions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,10 @@ def _evaluate_simple_expression(expr: str, namespace: dict[str, Any]) -> Any:
535535
items = [
536536
_evaluate_simple_expression(i.strip(), namespace)
537537
for i in _split_top_level_commas(inner)
538+
# Drop empty segments from trailing/leading/double commas ([1, 2,] ->
539+
# [1, 2], not [1, 2, None]). An intentional empty-string element
540+
# ('') strips to "''" (truthy), so ['', 'a'] is preserved.
541+
if i.strip()
538542
]
539543
return items
540544

tests/test_workflows.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,17 @@ def test_list_literal_preserves_quoted_commas(self):
404404
assert evaluate_expression('{{ [["a", "b"], "c"] }}', ctx) == [["a", "b"], "c"]
405405
assert evaluate_expression("{{ [[1, 2], [3, 4]] }}", ctx) == [[1, 2], [3, 4]]
406406

407+
def test_list_literal_ignores_trailing_and_empty_commas(self):
408+
from specify_cli.workflows.expressions import evaluate_expression
409+
from specify_cli.workflows.base import StepContext
410+
411+
ctx = StepContext()
412+
# A trailing comma must not append a spurious None element.
413+
assert evaluate_expression("{{ [1, 2,] }}", ctx) == [1, 2]
414+
assert evaluate_expression("{{ [1,, 2] }}", ctx) == [1, 2]
415+
# …but an intentional empty-string element is still preserved.
416+
assert evaluate_expression("{{ ['', 'a'] }}", ctx) == ["", "a"]
417+
407418
def test_operator_splitting_is_quote_aware(self):
408419
from specify_cli.workflows.expressions import (
409420
evaluate_condition,

0 commit comments

Comments
 (0)