Repository navigation
Merged
Conversation
…o dependencies
The transformer is rebuilt around a shell lexer and a small runtime instead of
string surgery on tokenized lines.
Bugs fixed
- A quote or backslash in an argument produced invalid or silently different
Python ('a\nb' became a newline, 'say "hi"' was a syntax error).
- Python strings containing "= $" or "($" were rewritten as commands.
- `a = $x | y` assigned a Popen object and leaked cmd1/fout variables; pipes
left processes and file handles open.
- `&&` raised NotImplementedError; operators needed surrounding spaces.
- `>` shell commands lost their quoting before reaching the shell.
- A trailing `# comment` was passed to the command as arguments.
- `python -m pybash` with no arguments crashed and never ran scripts as __main__.
New
- Operators: && || ; |& 2> 2>> &> &>> 2>&1 >&2, with or without spaces.
- `$(command)` capture, several captures per line, capture after return/+=.
- Backslash line continuation; one output line per input line.
- `{{ expr }}` accepts any expression and is str()-converted; `\{{` escapes it.
- Interpolation in `>` commands is quoted for its context; `{{! expr }}` opts out.
- PybashSyntaxError with filename/lineno/offset/text of the original line.
- `pybash` command with --show and -c; import hook without the ideas package.
- header()/runtime_source() so hosts can emit code with or without a pybash
runtime dependency.
Project
- Python 3.11-3.15, zero dependencies, typed (mypy strict), ruff.
- poetry/flake8/black/isort replaced by hatchling + uv; CI matrix and PyPI
trusted publishing.
- Version 0.4.0. See "Upgrading from 0.3" in the README for behavior changes.
Co-Authored-By: Claude Opus 5.5 <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
Rewrites the transformer around a real shell lexer and a small runtime helper, replacing the string surgery on tokenized lines. Adds full operator support, fixes a set of correctness bugs, and removes both dependencies. Motivated by cliffy, which generates CLIs from
$/>lines in YAML run blocks.Bugs fixed
'say "hi"'was a syntax error and'a\nb'became a real newline.= $or($(for example"total = $5") were rewritten as commands.a = $x | yassigned aPopenobject instead of the output, and pipes leakedcmd1/foutvariables, open files and unfinished processes.&&raisedNotImplementedError; operators only worked with spaces around them.>shell commands lost their quoting before the shell saw them.# commentwas passed to the command as arguments.python -m pybashcrashed with no arguments and never ran a script as__main__.New
$commands:||&&&||;<>>>2>2>>&>&>>2>&1>&2, with or without spaces. Background&, here-documents and other file descriptors raise a clear error that points to>shell mode.$(command)capture, several captures per line, and capture afterreturn/+=.{{ expr }}accepts any expression, is converted withstr()and is always exactly one argument;\{{and\f{write the markers literally.>shell lines are quoted for where they sit (bare, inside"...", inside'...'), so a value cannot become shell syntax.{{! expr }}opts out.PybashSyntaxError(aSyntaxError) withfilename,lineno,offsetandtextof the original line.pybashcommand with--showand-c; an import hook built onimportlib.pybash.header()/runtime_source(), so a host can emit code that imports the runtime helper or carries a pasted copy and needs no pybash at run time.Project
ideasandtoken-utilsare gone), typed (mypy --strict), ruff.Behaviour changes
All listed under "Upgrading from 0.3" in the README. The main ones:
$echo \\n...printing a newline) changes.>lines are quoted by default.$a > f1 > f2writes the output to both files; before, the second file received a copy of the first.["ls", "-la"]and the output no longer gains a trailing newline.Maintainer action
publish.yml, environmentpypi); the old token-based workflow is removed.How verified
ruff format --check,ruff checkandmypy --strictare clean.🤖 Generated with Claude Code