You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit a324625
Browse filesBrowse the repository at this point in the historyBrowse files
fix(workflows): chain comparisons like Python in expressions
A chained comparison such as 0 <= inputs.n <= 10 grouped left to right,
comparing a boolean with the next operand, so the range check answered
True for n = 50 and an if/while step silently took the wrong branch.
Evaluate comparisons as Python and Jinja2 do: a OP b OP c is a OP b and
b OP c, with the shared operand evaluated once and evaluation stopping
at the first false pair, so a later operand is only reached when every
pair before it held (the same guard behavior as and). Explicit
parentheses still end a chain: (0 <= n) <= 10 compares the grouped
boolean, exactly as in Python. The grammar is unchanged; cmp nodes
flatten into one chain node the way and/or and filter chains already
do, a parenthesized comparison stays one grouped operand, and
validation still walks every operand.
Fixes#5071
Assisted-by: Claude Code (model: Claude Fable 5, supervised)
Copy file name to clipboardExpand all lines: docs/workflows/expressions.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -64,7 +64,7 @@ Notes on the newer filters:
64
64
65
65
`and` and `or` return `true` or `false` and evaluate their right side only when the left side does not decide the result: `and` skips it when the left side is false, and `or` skips it when the left side is true. A condition can therefore guard a filter that would fail on an empty value. `{{ inputs.payload != '' and (inputs.payload | from_json | length) }}` is false for an empty optional `payload` instead of failing the run on invalid JSON. When the right side is evaluated, its errors still fail the run.
66
66
67
-
Operators bind from loosest to tightest as `or`, `and`, `not`, then the comparisons. All comparisons (`==`, `!=`, `>`, `<`, `>=`, `<=`, `in`, `not in`) share one level and are evaluated left to right; none has priority over another. `{{ a == b > 0 }}` therefore means `{{ (a == b) > 0 }}`. To combine comparisons, use parentheses or `and`/`or`.
67
+
Operators bind from loosest to tightest as `or`, `and`, `not`, then the comparisons. All comparisons (`==`, `!=`, `>`, `<`, `>=`, `<=`, `in`, `not in`) share one level and chain as in Python and Jinja2: `{{ 0 <= inputs.n <= 10 }}`means `{{ 0 <= inputs.n and inputs.n <= 10 }}`, with the shared operand evaluated once and evaluation stopping at the first false pair — a later operand is evaluated only when every pair before it held, with the same guard behavior as `and`. Explicit parentheses end a chain: `{{ (0 <= inputs.n) <= 10 }}` compares the grouped `true`/`false` result with `10`, exactly as in Python.
68
68
69
69
The body of every `{{ }}` block must be a valid expression. Text that is not one, such as prose (`{{ some text }}`), a key with characters other than letters, digits, `_` and `-` (`{{ inputs.weird:key }}`), or arithmetic (`{{ count + 1 }}`), raises a `ValueError` naming the offending token. Numbers may be written as `5`, `-5`, `+5`, `1_000`, `0.5`, `.5`, `5.`, or `1.5e3`.
0 commit comments