Search code examples
python-3.xmakefilezsh

Unable to activate venv from python makefile


I have the following python makefile.

.ONESHELL:

TEST_DIR = ./tests
DIR_NAME = $(shell date "+%Y-%m-%d_%T")

.PHONY: clean test backup env

env:
    . .venv/bin/activate

test: env clean
    pytest --cache-clear --cov -p no:logging --html=report.html --self-contained-html -n 8 --maxprocesses=8 $(TEST_DIR)

backup: 
    mkdir -p ./backup_test_results
    cd ./backup_test_results
    mkdir $(DIR_NAME) && cd $(DIR_NAME)
    find . -name htmlcov -type d -exec cp -r '{}' ./ \;
    find . \( -name "error.log" -o -name "download.log" -o -name ".coverage*" -o -name "report.html" \) -type f -exec cp '{}' ./ \;
    cd ../../

clean: backup
    find . -path ./.venv -prune -o \( -name __pycache__ -o -name .pytest_cache  -o -name htmlcov \) -type d -exec rm -rf '{}' \;
    find . \( -name "error.log" -o -name "download.log" -o -name ".coverage*" -o -name "report.html" \) -type f -delete

The directories are created as expected by using the .ONESHELL command. But the virtual env is not getting activated.

On running the make file, there is an error which says that pytest is not found. Hence, I am assuming that virtual env was not activated.

What am I doing wrong?


Solution

  • .ONESHELL doesn't mean that make starts one shell for the entire run of make and somehow passes all the commands from all the recipes to that one shell (that is not possible, because make needs to know the exit code from each recipe to know whether the rule succeeded or not).

    .ONESHELL means that all the lines in each individual recipe are passed to a single shell: by default each individual line in each individual recipe is passed to a separate shell.

    So, you can't share shell environment settings between different recipes ever, even using .ONESHELL. You could do something like this instead:

    .ONESHELL:
    
    SETVENV = . .venv/bin/activate
    
    test: clean
            $(SETVENV)
            pytest --cache-clear --cov -p no:logging --html=report.html --self-contained-html -n 8 --maxprocesses=8 $(TEST_DIR)
    

    (e.g., add the $(SETVENV) variable to each recipe.)