wbolster / emacs-python-pytest

run pytest inside emacs
BSD 3-Clause "New" or "Revised" License
147 stars 25 forks source link

Add option to use a different shell for executing the tests #51

Closed Vynlar closed 2 years ago

Vynlar commented 2 years ago

I needed to be able to run my tests via zsh instead of the default sh and I also needed to run the shell in interactive mode in order for some of my tooling to work. I've added some additional configuration paramaters to enable this behavior :)

wbolster commented 2 years ago

what underlying problem are you trying to solve? because i am not convinced custom shells are the answer.

in fact, execution via a shell is purely an implementation detail and not strictly necessary. (it makes command line editing easier to implement, which is why it's used under the hood.)

Vynlar commented 2 years ago

For some context: I work on a large project for which I do not control the tooling. The project's tests (and other commands) are accessed through a collection of zsh files. Specifically, these files define functions in zshfor running the commands.

I tried using the python-pytest-executable config like this: (setq python-pytest-executable "zsh -ic 'my-run-tests-script'") but the issue this causes is when python-pytest appends the list of test files, the resulting command is incorrect:

zsh -ic 'my-run-test-script' test-file-1.py test-file-2.py

Which does not result in the test files being executed since the args are passed to zsh instead of my-run-test-script. I would need the command to look like this instead:

zsh -ic 'my-run-test-script test-file-1.py test-file-2.py'

Do you see a way to get around this issue?

wbolster commented 2 years ago

python-pytest.el needs an executable that behaves like pytest when it comes to flags etc. if that's not pytest itself, it can be a wrapper script that exposes the pytest interface.

i guess something like this should work?

#!/bin/sh
zsh -ic "my-run-test-script $*"

(note the $*, which is not the same as $@)

save it in a file, e.g. pytest-wrapper.sh, and chmod +x it.

Vynlar commented 2 years ago

That worked!

I'll have to look up the difference between $@ and $* because I had tried $@ before and it didn't work for me.

Appreciate the help :)

wbolster commented 2 years ago

alternatively, you may do it without a wrapper script by using a similar trick in a custom python-pytest-executable directly in emacs.

you wrote that this does not work because it does not pass arguments correctly:

(setq python-pytest-executable "zsh -ic 'my-run-tests-script'")

results in

zsh -ic 'my-run-test-script' test-file-1.py test-file-2.py

the trick to make it work would be to inject the arguments:

(setq python-pytest-executable "zsh -ic 'my-run-tests-script "$0" "$@"'")

...which results in:

zsh -ic 'my-run-test-script "$0" "$@"' test-file-1.py test-file-2.py

here's a plain shell command that shows how it works, and that behaves correctly wrt word splitting (whitespace handling):

$ sh -ic 'ls "$0" "$@"' t1.py t2.py 't3 with a space.py'
ls: cannot access 't1.py': No such file or directory
ls: cannot access 't2.py': No such file or directory
ls: cannot access 't3 with a space.py': No such file or directory
Vynlar commented 2 years ago

Wow! That's a lot nicer for sure. I didn't realize you could inject arguments while calling the shell with -c like that. I tried it out and it works great! :)

Thanks for going above and beyond for me