6

In my tox.ini file, the dependencies are installed via the requirements.txt file which is also used by setup.py, as follows:

The requirements.txt file contains the acceptable range of django packages, depending on the python version installed, as follows:

Django>=1.11,<2 ; python_version == '2.7'
Django>=1.11,<3 ; python_version > '3'

For python3, I want to make sure the tests run on django 2.0 as well as the latest django 2.1+ that will be installed by default, obeying the version constraints specified in the requirements.txt file. To achieve that, I force the installation of the desired django version with commands, as follows:

[tox]
envlist = {py27,py3}-django111,py3-django{20,21}

[testenv]
deps =
    -r{toxinidir}/requirements.txt

commands =
    django111: pip install 'Django>=1.11,<1.12'
    py3-django20: pip install 'Django>=2.0,<2.1'
    py3-django21: pip install 'Django>=2.1'
    pytest

Ideally I could just add to the deps variable like so:

[testenv]
deps =
    -r{toxinidir}/requirements.txt
    django111: Django>=1.11,<1.12
    py3-django20: Django>=2.0,<2.1
    py3-django21: Django>=2.1

commands =
    pytest

But pip does not support double requirements and will throw an error even though there is no conflict in how the version constraints are specified.

The drawback of using commands to override the installation is that it needs to remove the django package version installed via requirements.txt to install the desired one. Is there a way to avoid that extra step?

singuliere
  • 767
  • 10
  • 19

1 Answers1

2

One trick is to move the requirement from requirements.txt into setup.py - where it's loosely pinned so that all your django versions are possible. For example

# setup.py
from setuptools import setup, find_packages

setup(
    ...
    install_requires=[
        "Django>=1.11,<2.1",
    ]
)

and then use your second suggestion in tox.ini

[testenv]
deps =
    -r{toxinidir}/requirements.txt
    django111: Django>=1.11,<1.12
    py3-django20: Django>=2.0,<2.1
    py3-django21: Django>=2.1

commands =
    pytest

... so long as the Django requirement isn't listed in requirements.txt.

This works because the pip install is split in two parts, the first from tox:deps where you specify the hard requirement, and the second from the equivalent of pip install -e . where the setup.py has the looser requirement.

danodonovan
  • 19,636
  • 10
  • 70
  • 78
  • What happens if you have more dependencies in requirements that need to be installed. Should they all go into install_requires? Or how do you split what ti list on install_requires and requirements? Check my Q for more context: https://stackoverflow.com/questions/69888445/how-to-use-tox-in-an-existing-python-package-with-requirements-and-setup – Gonzalo Nov 08 '21 at 22:37