feat(workflows): add from_json expression filter#2961
Conversation
Step outputs captured as strings could never become typed values in templates - the filter set was default/join/map/contains only, so e.g. a fan-out items: could never consume a step's JSON stdout. Add an arg-less from_json pipe filter with parse-or-raise semantics: invalid JSON or non-string input raises a clear ValueError rather than passing through silently. Fixes github#2960
|
@mnriem when you have a moment, would appreciate a review — happy to adjust anything. |
There was a problem hiding this comment.
Pull request overview
Adds a new from_json pipe filter to the workflow expression evaluator so step outputs (typically strings like stdout) can be converted into typed Python values (dict/list/scalar) inside templates, enabling patterns like feeding fan-out.items from a runtime-emitted JSON string.
Changes:
- Implement
from_jsonfilter in the sandboxed expression evaluator (json.loadswith strict ValueError semantics on misuse). - Extend filter documentation in the evaluator docstring to include
from_json. - Add unit tests validating successful parsing and failure modes (invalid JSON, non-string input).
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/workflows/expressions.py |
Adds the from_json filter and wires it into filter dispatch. |
tests/test_workflows.py |
Adds 3 tests covering from_json success + error cases. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 2
|
Please address Copilot feedback |
Address review (github#2961): from_json('x') and from_json() previously fell through to a silent passthrough of the unparsed value. Reject any parenthesized form with a clear error so mis-wired templates fail loudly. Rename test to ...parses_object (JSON under test is an object) and add coverage for the strict no-arguments behavior. Co-Authored-By: Claude Fable 5 <[email protected]>
|
@mnriem Thanks for the review — addressed the Copilot feedback:
Full suite green; |
Address review (github#2961): from_json('x') and from_json() previously fell through to a silent passthrough of the unparsed value. Reject any parenthesized form with a clear error so mis-wired templates fail loudly. Rename test to ...parses_object (JSON under test is an object) and add coverage for the strict no-arguments behavior. Co-Authored-By: Claude Fable 5 <[email protected]>
b8bbc8a to
3751f5f
Compare
| - Comparisons: ``==``, ``!=``, ``>``, ``<``, ``>=``, ``<=`` | ||
| - Boolean operators: ``and``, ``or``, ``not`` | ||
| - ``in``, ``not in`` | ||
| - Pipe filters: ``| default('...')``, ``| join(', ')``, ``| contains('...')``, ``| map('...')`` | ||
| - Pipe filters: ``| default('...')``, ``| join(', ')``, ``| contains('...')``, ``| from_json``, ``| map('...')`` | ||
| - String and numeric literals | ||
| """ |
mnriem
left a comment
There was a problem hiding this comment.
Please address Copilot feedback
Description
Fixes #2960.
Adds one arg-less pipe filter to the sandboxed expression evaluator:
_filter_from_jsonparses a JSON string into its typed value (list/dict/scalar). Semantics are parse-or-raise: invalid JSON or non-string input raises a clearValueError— never a silent passthrough, since a parse failure means the pipeline wiring is wrong and silence would hide it. The module docstring's filter list is updated; no other filter or evaluator behavior is touched.This is the smallest unblock for feeding
fan-outitems:(or any condition/arg) from a step that computes a collection at runtime. It composes with — and doesn't preclude — a future declared-outputs:mechanism, which I'm proposing separately.Testing
uv sync && uv run pytest—tests/test_workflows.py210 passedTestExpressions(valid JSON → typed value; invalid JSON raises; non-string raises) — all three are red against currentmain, green with the filter (verified both directions)uvx ruff check src/— cleanuv run specify --help| from_json)AI Disclosure
Code, tests, and this description were authored with AI assistance (Claude); verified by running the repo's test suite and ruff locally in both red and green directions.