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
4 changes: 4 additions & 0 deletions src/specify_cli/workflows/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,10 @@ def _evaluate_simple_expression(expr: str, namespace: dict[str, Any]) -> Any:
items = [
_evaluate_simple_expression(i.strip(), namespace)
for i in _split_top_level_commas(inner)
# Drop empty segments from trailing/leading/double commas ([1, 2,] ->
# [1, 2], not [1, 2, None]). An intentional empty-string element
# ('') strips to "''" (truthy), so ['', 'a'] is preserved.
if i.strip()
]
return items

Expand Down
11 changes: 11 additions & 0 deletions tests/test_workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,17 @@ def test_list_literal_preserves_quoted_commas(self):
assert evaluate_expression('{{ [["a", "b"], "c"] }}', ctx) == [["a", "b"], "c"]
assert evaluate_expression("{{ [[1, 2], [3, 4]] }}", ctx) == [[1, 2], [3, 4]]

def test_list_literal_ignores_trailing_and_empty_commas(self):
from specify_cli.workflows.expressions import evaluate_expression
from specify_cli.workflows.base import StepContext

ctx = StepContext()
# A trailing comma must not append a spurious None element.
assert evaluate_expression("{{ [1, 2,] }}", ctx) == [1, 2]
assert evaluate_expression("{{ [1,, 2] }}", ctx) == [1, 2]
# …but an intentional empty-string element is still preserved.
assert evaluate_expression("{{ ['', 'a'] }}", ctx) == ["", "a"]

def test_operator_splitting_is_quote_aware(self):
from specify_cli.workflows.expressions import (
evaluate_condition,
Expand Down