Search code examples
pythonsetuptoolssetup.pyinstall-requires

setup.py: require a recent version of setuptools before trying to install


I'm creating a package that has 'typing;python_version<"3.5"' in it's install_requires. Apparently, this kind of dependency specification has only been implemented in recent versions of setuptools. If the setuptools on the user's machine is old they'll get:

'install_requires' must be a string or list of strings containing valid project/version requirement specifiers; Expected version spec in typing;python_version<"3.5" at ;python_version<"3.5"

The easy solution is to tell the users to pip install 'setuptools>=36.2.1' before pip install my-package. (Note that 36.2.1 is just a version that I know works, not necessarily the the absolute minimum requirement)

But is there any way to specify this requirement in setup.py so that it gets done automatically? Adding setuptools>=36.2.1 to install_requires and setup_requires did not work. It says Installed /tmp/pip-si2fqg-build/.eggs/setuptools-38.2.5-py3.3.egg and then gives the same error above.


Solution

  • You can't update setuptools and use its code in the setup script in one pass. I see two possible solutions: If you want to support old versions of setuptools, you can't use env markers. Implement the check yourself by using sys.version_info:

    import sys
    from setuptools import setup
    
    
    setup(
        name='spam',
        version='0.1',
        packages=[],
        install_requires=['typing'] if sys.version_info < (3, 5) else []
    )
    

    If you don't want to support old versions of setuptools, check its version and abort early, informing the user:

    import sys
    from distutils.version import StrictVersion
    from setuptools import setup, __version__
    
    
    if StrictVersion(__version__) < StrictVersion('20.2'):
        print('your setuptools version does not support PEP 508. Upgrade setuptools and repeat the installation.')
        sys.exit(1)
    
    
    setup(
        name='spam',
        version='0.1',
        packages=[],
        install_requires=['typing;python_version<"3.5"']
    )