fix(workflows): evaluate 'in'/'not in' safely on a non-iterable right operand (#3447)#3468
Open
Noor-ul-ain001 wants to merge 1 commit into
Open
Conversation
… operand (github#3447) The `in` / `not in` operators in `_evaluate_simple_expression` only guarded `right is not None`, but `left in right` also raises `TypeError` for any other non-iterable right operand (int, bool, float). So a workflow condition like `{{ inputs.tag in inputs.count }}` where `count` is a number leaked a raw `TypeError: argument of type 'int' is not iterable` and crashed the whole run, instead of evaluating like the None case beside it. This was asymmetric with `_safe_compare`, which already swallows `TypeError` and returns False for the ordering operators. Add a `_safe_contains` helper (mirroring `_safe_compare`) that treats both a None and a non-container right operand as "nothing is contained": `in` -> False, `not in` -> True. Add a regression test covering int/bool/float/None right operands and asserting genuine containment against iterables still works. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #3447. The
in/not inoperators in_evaluate_simple_expression(src/specify_cli/workflows/expressions.py) only guardedright is not None:But
left in rightalso raisesTypeErrorfor any other non-iterable right operand (int, bool, float). So a workflow condition like{{ inputs.tag in inputs.count }}wherecountis a number leaked a rawTypeError: argument of type 'int' is not iterableand crashed the whole run, instead of evaluating like the None case right beside it.This is asymmetric with
_safe_compare, which already swallowsTypeErrorand returnsFalsefor the ordering operators (<,>, etc.).Before:
After: evaluates to
False(nothing is contained in a non-container), same as theright is Nonebranch.Changes
_safe_contains(left, right)helper mirroring_safe_compare: aNoneor non-containerrightmeans "nothing is contained", soin→Falseandnot in→Truerather than a rawTypeError.not innegates the result), so the two operators can't drift.Testing
test_in_operator_non_iterable_right_operand: assertsin/not inagainst int/bool/float/None right operands don't crash and return the None-branch result, and that genuine containment against iterables still works.TypeErrorpropagates).pytest tests/test_workflows.py→ 395 passed, 1 skipped. (The 11TestWorkflow*SymlinkGuardfailures are pre-existing on Windows without elevation and unrelated to this change.)🤖 Generated with Claude Code