1

The problem I am facing is that setuptools overwrite the sub-package dependency requirements.

Example:

setup.py

import os
from setuptools import setup

setup(
    name="test",
    version="0.1",
    author="myself",
    author_email="info@example.com",
    description="How to manage dependencies?",
    license="MIT",
    classifiers=[
        "Development Status :: 3 - Alpha"
    ],
    zip_safe=False,
    install_requires=[
        'dependency-injector',
    ]
)

Installation successful via python setup.py install

Output:

(venv) alex@ws:~$ pip freeze
dependency-injector==3.14.12
six==1.12.0
test==0.1

If you use the following setup.py including six as dependency (because you need it in your package), then you hit problems, because dependency-injector also needs the dependency though they have defined a fixed version range.

import os
from setuptools import setup



setup(
    name="test",
    version="0.1",
    author="myself",
    author_email="info@example.com",
    description="How to manage dependencies?",
    license="MIT",
    classifiers=[
        "Development Status :: 3 - Alpha"
    ],
    zip_safe=False,
    install_requires=[
        'dependency-injector',
        'six'
    ]
)

Output:

error: six 1.13.0 is installed but six<=1.12.0,>=1.7.0 is required by {'dependency-injector'}
(venv) alex@ws:~$ pip freeze
dependency-injector==3.14.12
six==1.13.0
test==0.1

For sure a working solution is just to repeat the same six version range which dependency-injector uses (see the requirements.txt file in their repo), though I would really like to avoid this duplicate definition of dependencies, because e.g. dependency-injector might upgrade the six version dependency and thus I need to also update my package. So I will always try to mimic their requirements which is bad practice.

I think actually the only clean solution would be that setuptools builds up a dependency tree and and then uses the versions matching the requirements of all dependencies. Is this realistic? How can it be achieved or what is the recommended best-practice in such a case as described above?

Alex
  • 1,652
  • 11
  • 18
  • 1
    Which command wrote this error message? – sinoroc Nov 28 '19 at 17:08
  • `python setup.py install`. I just added it to the question. Good question. Thanks. – Alex Nov 29 '19 at 09:51
  • 2
    I managed to reproduce it. I thought somehow I would find related bugs on the _setuptools_ issue tracker, but couldn't find any. I would suggest using `pip install .` instead of `python3 setup.py install`. – sinoroc Nov 29 '19 at 15:03
  • Thanks for looking into it. Appreciate it. Indeed, `pip install .` solves the problem. I just verified. Funny. Because yesterday I also tried a requirements.txt file with both requirements and then a `pip install -r requirements.txt` and it fails due to the exact same reason. I know too little though about setuptools and pip to judge now if it is the same root cause and why `pip install .` works though. I would really like to at least report this bug so that it gets fixed at some point in time. – Alex Nov 29 '19 at 15:28

1 Answers1

1

The TL;DR answer is that pip currently does not have a dependency solver.

There is an ongoing issue on pip's issue tracker on just that topic: https://github.com/pypa/pip/issues/988 What they say is that currently pip's behavior is "first found wins", so your top-level six dependency is resolved before dependency-injector's six dependency, which is why you get the latest six version installed in the end.

On the python setup.py install vs. pip install . question, there seems to be a subtle difference between the two commands. They don't use the same tools internally, and the recommended command is pip install . generally

(sources: https://stackoverflow.com/a/15731459/9977650, https://github.com/pypa/setuptools/issues/960)

guampi
  • 306
  • 1
  • 8
  • 1
    True, I agree an almost everything except the premise... If I am not mistaken the original question doesn't use _pip install_ to begin with but only _setuptools_' `python setup.py install`. And actually using `pip install` seems to solve the issue, so _pip_'s dependency resolution seems to be good enough at least in this case. – sinoroc Dec 03 '19 at 14:25