Auto dedent -c arguments.

I have what I think is a fairly low impact quality of life improvement to suggest for the python CLI. When I'm not working in Python I tend to be working in bash. But often I want to break out and do something quick in Python. I find the `python -c ` CLI very useful for this. For one liners it's perfect. E.g. NEW_VAR=$(python -c "import pathlib; print(pathlib.Path('$MYVAR').parent.parent)") And even if I want to do something multi-line it's pretty easy NEW_VAR=$(python -c " import pathlib for _ in range(10): print('this is a demo, bear with me') ") But the problem is when I'm writing bash inside a function or some other nested code, I would like to have nice indentation in my bash file, but if I write something like this: mybashfunc(){ python -c " import pathlib for _ in range(10): print('this is a demo, bear with me') " } I get `IndentationError: unexpected indent`. This means I have to write the function ugly like this: mybashfunc(){ python -c " import pathlib for _ in range(10): print('this is a demo, bear with me') " } Or use a helper function like this: codeblock() { __doc__=' copy-pastable implementation Prevents indentation errors in bash ' echo "$1" | python -c "import sys; from textwrap import dedent; print(dedent(sys.stdin.read()).strip('\n'))" } mybashfunc(){ python -c $(codeblock " import pathlib for _ in range(10): print('this is a demo, bear with me') ") } Or more recently I found that this is a low-impact workaround: mybashfunc(){ python -c "if 1: import pathlib for _ in range(10): print('this is a demo, bear with me') " } But as a certain Python dev may say: "There must be a better way." Would there be any downside to the Python CLI automatically dedenting the input string given to -c? I can't think of any case off the top of my head where it would make a previously valid program invalid. Unless I'm missing something this would strictly make previously invalid strings valid. Thoughts? -- -Dr. Jon Crall (him)

On Tue, Apr 4, 2023 at 7:19 AM Jonathan Crall <erotemic@gmail.com> wrote:
Very strong +1 to this. That would be useful and it doesn't seem like there's a downside. I often make bash functions that pipe files or database queries to Python for post-processing. I also sometimes resort to Ruby because it's easy to write one-liners in Ruby and annoying to write one-liners in python/bash. I suppose there's some ambiguity in the contents of multi-line """strings""". Should indentation be stripped at all in that case? E.g. python -c " ''' some text '''' " But it seems simpler and easier to understand/document if you pre-process the input like using an algorithm like this: * If the first nonempty line has indentation, and all subsequent lines either start with the same indentation characters or are empty, then remove that prefix from those lines. I think that handles cases where editors strip trailing spaces or the first line is blank. So e.g.: python -c " some_code_here() " Then python receives something like "\n some_code_here\n" python -c " some_code here() if some_some_other_code(): still_more_code() " Then python receives something like "\n some_code_here\n\n if ..." This wouldn't handle cases where indentation is mixed and there is a first line, e.g.: python -c "first_thing() if second_thing(): third_thing() " That seems simple enough to avoid, and raising a syntax error is reasonable in that case. Best wishes, Lucas

On 04/04/2023 15:18, Jonathan Crall wrote:
You can solve this with a small module. I named mine run_dedent mkdir -p run_dedent echo pass >run_dedent/__init__.py cat <<EOF >run_dedent/__main__.py import sys import textwrap cmd = textwrap.dedent(sys.argv[1]) exec(cmd) EOF python3 -m run_dedent " import sys print(sys.version_info) " Barry

There's no question that there are lots of ways you can work around the issue (I think the `if 1:` method is the easiest and most portable, but it still is boilerplate which can be confusing if you don't know why it's there). The question is: would enough people benefit from this to add the feature to CPython? On Sun, Apr 9, 2023 at 4:09 PM Barry Scott <barry@barrys-emacs.org> wrote:
-- -Dr. Jon Crall (him)

I can't think of a case where the check for "\n" would result in a false negative. It likely makes sense to do that to keep python startup as lightweight as possible. I've made a PR that implements a proof-of-concept: https://github.com/python/cpython/pull/103998 It's currently done via the Python C-API, but in terms of keeping things lightweight, I might need some help on how to effectively use the wide c-string API to implement this. On Mon, Apr 10, 2023 at 4:46 AM Barry <barry@barrys-emacs.org> wrote:
-- -Dr. Jon Crall (him)

On Tue, Apr 4, 2023 at 7:19 AM Jonathan Crall <erotemic@gmail.com> wrote:
Very strong +1 to this. That would be useful and it doesn't seem like there's a downside. I often make bash functions that pipe files or database queries to Python for post-processing. I also sometimes resort to Ruby because it's easy to write one-liners in Ruby and annoying to write one-liners in python/bash. I suppose there's some ambiguity in the contents of multi-line """strings""". Should indentation be stripped at all in that case? E.g. python -c " ''' some text '''' " But it seems simpler and easier to understand/document if you pre-process the input like using an algorithm like this: * If the first nonempty line has indentation, and all subsequent lines either start with the same indentation characters or are empty, then remove that prefix from those lines. I think that handles cases where editors strip trailing spaces or the first line is blank. So e.g.: python -c " some_code_here() " Then python receives something like "\n some_code_here\n" python -c " some_code here() if some_some_other_code(): still_more_code() " Then python receives something like "\n some_code_here\n\n if ..." This wouldn't handle cases where indentation is mixed and there is a first line, e.g.: python -c "first_thing() if second_thing(): third_thing() " That seems simple enough to avoid, and raising a syntax error is reasonable in that case. Best wishes, Lucas

On 04/04/2023 15:18, Jonathan Crall wrote:
You can solve this with a small module. I named mine run_dedent mkdir -p run_dedent echo pass >run_dedent/__init__.py cat <<EOF >run_dedent/__main__.py import sys import textwrap cmd = textwrap.dedent(sys.argv[1]) exec(cmd) EOF python3 -m run_dedent " import sys print(sys.version_info) " Barry

There's no question that there are lots of ways you can work around the issue (I think the `if 1:` method is the easiest and most portable, but it still is boilerplate which can be confusing if you don't know why it's there). The question is: would enough people benefit from this to add the feature to CPython? On Sun, Apr 9, 2023 at 4:09 PM Barry Scott <barry@barrys-emacs.org> wrote:
-- -Dr. Jon Crall (him)

I can't think of a case where the check for "\n" would result in a false negative. It likely makes sense to do that to keep python startup as lightweight as possible. I've made a PR that implements a proof-of-concept: https://github.com/python/cpython/pull/103998 It's currently done via the Python C-API, but in terms of keeping things lightweight, I might need some help on how to effectively use the wide c-string API to implement this. On Mon, Apr 10, 2023 at 4:46 AM Barry <barry@barrys-emacs.org> wrote:
-- -Dr. Jon Crall (him)
participants (5)
-
Barry
-
Barry Scott
-
Cameron Simpson
-
Jonathan Crall
-
Lucas Wiman