pyinvoke / invoke

Pythonic task management & command execution.
http://pyinvoke.org
BSD 2-Clause "Simplified" License
4.31k stars 365 forks source link

QOL: Context run command accepts either str or list #987

Open achekery opened 3 months ago

achekery commented 3 months ago

Description

  1. Changed Context.run() and Context.sudo() to define command with the new type Union[str, List[str]] and handle the value with shlex.join if it is a list.

  2. Updated run() and sudo() functions to use this new type.

  3. Updated Context_.methods_exposed.run and Context_.methods_exposed.sudo classes to test this new type.

Demo

Created tasks.py for demo:

# pylint: disable-next=E0401:import-error
from invoke import task  # type: ignore

@task
def demo(ctx):
    import shlex  # pylint: disable=C0415:import-outside-toplevel

    ctx.config.run.echo = True
    command_list = ["git", "status", "--porcelain"]
    for command in [
        command_list,
        shlex.join(command_list),
    ]:
        try:
            print(f"** Demo: run {command=}")
            res = ctx.run(command)
        except TypeError as exc:
            print(f"** Error: {exc=}")
        else:
            print(f"** Success!: {res=}")

Results with invoke main

PS > pipx uninstall invoke
PS > pipx install 'git+https://github.com/pyinvoke/invoke@main'
  injected package invoke into venv invoke
done! ✨ 🌟 ✨
PS > invoke demo
** Demo: run command=['git', 'status', '--porcelain']
** Error: exc=TypeError('sequence item 0: expected str instance, list found')
** Demo: run command='git status --porcelain'
git status --porcelain
 M projects/bce-patch-builder/tasks.py
** Success!: res=<Result cmd='git status --porcelain' exited=0>

Results with invoke fork

PS > pipx uninstall invoke
PS > pipx install 'git+https://github.com/achekery/invoke@qol-commandlist'
  injected package invoke into venv invoke
done! ✨ 🌟 ✨
PS > invoke demo
** Demo: run command=['git', 'status', '--porcelain']
git status --porcelain
 M projects/bce-patch-builder/tasks.py
** Success!: res=<Result cmd='git status --porcelain' exited=0>
** Demo: run command='git status --porcelain'
git status --porcelain
 M projects/bce-patch-builder/tasks.py
** Success!: res=<Result cmd='git status --porcelain' exited=0>