Skip to content

feat(exec): support interpreter on serial and parallel steps - #442

Merged
jahvon merged 1 commit into
feat/python-containerfrom
feat/step-interpreter
Aug 27, 2026
Merged

feat(exec): support interpreter on serial and parallel steps#442
jahvon merged 1 commit into
feat/python-containerfrom
feat/step-interpreter

Conversation

@jahvon

@jahvon jahvon commented Aug 27, 2026

Copy link
Copy Markdown
Member

Part 4/5. Stacked on #441.

Summary

Inline cmd steps in serial/parallel executables now take their own interpreter, so one workflow can mix shell and Python without splitting into separate executables.

serial:
  execs:
    - cmd: ./fetch-data.sh
    - cmd: |
        import json
        print(json.load(open("data.json"))["total"])
      interpreter: python

Notable Changes

  • Both step configs $ref the same ExecInterpreter definition the exec type uses, so there is one enum rather than three parallel ones. (Part 1 hoisted it to a top-level definition for exactly this.)
  • A step that omits interpreter runs under the shell as before; a ref step ignores the field — the referenced executable brings its own.
  • This lifts the interim restriction from feat(mcp): add run_python tool #440: --interpreter now applies to every --cmd in an invocation, in serial and parallel mode alike.
  • ExecutableForCmd takes the interpreter as a new parameter (5 call sites). Its unused int parameter is left alone to keep the diff to the one concern.

Testing

  • E2E: a serial executable mixing a shell step and a Python step, each running under its own interpreter; a step without an interpreter staying on the shell (asserted via echo, a shell builtin, so it only passes if the step really stayed there); and --interpreter applied across a multi-command batch.
  • The e2e case that previously asserted the multi-command rejection is replaced with one asserting it now works.
  • flow validate passes; generate produces no diff.

🤖 Generated with Claude Code

https://claude.ai/code/session_01R328pa3FUUfga4gYah1iQi

@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.30769% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
cmd/internal/exec.go 83.33% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@jahvon
jahvon force-pushed the feat/step-interpreter branch from 8b27964 to 69e5a4a Compare August 27, 2026 04:28
@jahvon
jahvon force-pushed the feat/step-interpreter branch from 69e5a4a to 91b3d5f Compare August 27, 2026 05:48
@jahvon
jahvon force-pushed the feat/step-interpreter branch from 91b3d5f to eace042 Compare August 27, 2026 06:24
@jahvon
jahvon force-pushed the feat/step-interpreter branch from eace042 to 7b6876c Compare August 27, 2026 06:44
Inline `cmd` steps in serial/parallel executables now take their own
`interpreter`, so one workflow can mix shell and Python without splitting into
separate executables. A step that omits it runs under the shell as before, and
a `ref` step ignores it — the referenced executable brings its own.

Both step configs $ref the same ExecInterpreter definition the exec type uses,
so there is one enum rather than three parallel ones.

This also lifts the restriction added with the --interpreter flag: the flag now
applies to every --cmd in an invocation, in serial and parallel mode alike.

ExecutableForCmd takes the interpreter as a new parameter; its unused int
parameter is left alone to keep this diff to the one concern.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R328pa3FUUfga4gYah1iQi
@jahvon
jahvon force-pushed the feat/step-interpreter branch from 7b6876c to 366fea8 Compare August 27, 2026 06:50
@jahvon
jahvon merged commit 09890bb into main Aug 27, 2026
23 checks passed
@jahvon
jahvon deleted the feat/step-interpreter branch August 27, 2026 13:52
jahvon added a commit that referenced this pull request Aug 27, 2026
**Part 5/5.** Stacked on #442.

# Summary

Adds `.py` to the script types `imports:` can turn into executables, so
a repo's Python scripts become named, discoverable flow executables
alongside its shell ones.

```yaml
imports:
  - "scripts/analyze.py"
```

```python
#!/usr/bin/env python3
# f:name=metrics f:verb=analyze
# f:description="Analyze project metrics"
# f:tag=reporting
```

→ `flow analyze metrics`

**Notable Changes**

- Python uses `#` line comments, so the existing `f:name=` / `f:verb=`
metadata syntax and its parser work unchanged — the new parser is the
shell one with a different extension.
- The generated executable leaves `interpreter` unset: the `.py`
extension already routes it (Part 1), and setting the field would add
noise to every generated definition.
- Docs updated in both `executables.md` (import table + a Python tab in
the metadata examples) and `generated-config.md` (supported types,
comment-prefix note, and Python tabs in the params/args examples).

# Testing

- Parser tests mirroring the ps1 set (simple / complex / params), plus
two cases the others do not have: metadata following a shebang line —
idiomatic in Python scripts, and it must not shadow the comments beneath
it — and that the generated executable leaves `interpreter` unset while
still resolving to Python via its extension.
- An import-dispatch test alongside the existing `.sh`/`.bat`/`.ps1`
ones.
- Verified end-to-end outside the test suite: a scratch workspace
importing a `.py`, synced, then run — metadata, tags, and description
all landed, and `flow analyze metrics` executed it under Python.
- `flow validate` passes; `generate` produces no diff.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01R328pa3FUUfga4gYah1iQi

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant