* Add .pre-commit-config.yaml to the project and exclude tests (for now). This does not include the MyPy linting that pip does but does include everything else.
- Begin a refactor of `delegator.run` invocation to ensure we capture
and handle failures with our own exception wrappers
- Additoinally capture output and error logging and command information
when running in verbose mode (should avoid significant repitition in
the codebase)
- Refactor `which` and `system_which` to fallback to pythonfinder's
implementation
- Abstract `is_python_command` to identify whether we are looking for
python, this enables us to rely on `pythonfinder.Finder.find_all_python_versions()`
to ensure we aren't skipping python versions
- Fixes#2783
Signed-off-by: Dan Ryan <dan@danryan.co>
Carets introduce a difficult situation since they are essentially
"lossy" when parses. Consider this in cmd.exe:
> echo "foo^bar"
"foo^bar"
> echo foo^^bar
foo^bar
The two commands produce different results, but are both parsed by the
shell as `foo^bar`, and there's essentially no sensible way to tell what
was actually passed in. This implementation assumes the quoted variation
(the first) since it is easier to implement, and arguably the more common
case.
The command can be safely quoted in this case since non-quotable commands
(cmd built-in) do not have parentheses.
Note that this change only applies to the command, not arguments.
Parentheses in arguments can be correctly interpreted without quotes, and
the quotes, like spaces, will cause incorrect outputs for echo etc.
The API now requires a command argument from signature. Parsing errors
(no command from input) is thrown as a custom exception, and caught by
the outmost possible invocation to emit a message from click.
I chose to make Script.parse to always operate in POSIX mode so it is much
easier to write commands compatible on all platforms.
Script.cmdify is the important part on Windows. It ensures the argument
line is always escaped and joined properly on Windows, not just for the
subset that works both under POSIX and Windows (as is the case of
shlex.escape).