Search code examples
pythontox

how to substitute tox environment dependencies with considering the Python version?


Suppose that we have two tox environment collections {py37,py38}-develop and {py37,py38}-test. The develop environments dependencies include the corresponding test environment dependencies (for simplicity, additional dependencies and configurations of each environment collection is not shown):

[tox]
envlist = {py37,py38}-{test,develop}

[testenv:{py37,py38}-test]
deps = pytest
commands = pytest tests

[testenv:{py37,py38}-develop]
deps = {[testenv:py?-test]deps}  # How to describe python version here?

The current solution is:

[tox]
envlist = {py37,py38}-{test,develop}

[testenv:{py37,py38}-test]
deps = pytest
commands = pytest tests

[testenv:{py37,py38}-develop]
deps = 
    py37: {[testenv:py37-test]deps}
    py38: {[testenv:py38-test]deps}

Also, I know that by using the {envname} variable we can use the whole environment name, but I cannot extract the py* part for using inside dependencies variable substitution.

How to describe this dependency without duplication in the develop environment dependencies section? I also prefer the tox configuration to be complete itself and not enforcing the user to pass additional arguments when running tox.


Solution

  • With the help of the @sinoroc answer, I found that the factor conditions are evaluated on the actual executing environment (not the environment that contains it).

    For example:

    [tox]
    envlist = {py37,py38}-{test,develop}
    
    [testenv:{py37,py38}-test]
    deps = 
        py37: dep1
        py38: dep2
    
    [testenv:{py37,py38}-develop]
    deps = {[testenv:py37-test]deps}  # The py37 here is not important.
    

    Works successfully independent of py* factor specified in substitution line. Actually, the substitution mechanism copies the whole deps variable including the factors. So, the factors are evaluated on the actual running environment (not the included one).

    Finally, in order to clear up the ambiguity of the py37 factor used in the develop environment, I added pyauto factor in the test environment (which is not included in the envlist, so, the user cannot run it):

    [tox]
    envlist = {py37,py38}-{test,develop}
    
    [testenv:{py37,py38,pyauto}-test]
    deps = 
        py37: dep1
        py38: dep2
    
    [testenv:{py37,py38}-develop]
    deps = {[testenv:pyauto-test]deps}
    

    The solution is similar to @sinoroc solution, but:

    1. It does not append an additional section.
    2. In the case of many dependency inclusions, it's more simple and does not need many sections that use common* naming pattern.

    As a side note, you can also include pyauto factor in the envlist in order to allow the user to run the pyauto-... environments directly which means that it selects the Python version automatically. But if there is any factor condition like py38: ..., the tox evaluates its condition to false even if the automatically selected Python version is 3.8 (actually, the tox considers the factor in the conditions, not the python version). In this case, you can use PEP-508 dependency specification instead of factor conditions (that tox supports it).