Search code examples
pythonsetuptools

Setup.py install requires local package


I am looking to install a package my-package using setuptools. my-package has a local dependency, utils. My file structure is as follows:

parent/
    my-package/
        my-package/
        setup.py
    utils/
        utils/
        setup.py

I am looking to install the local dependency using the following:

from setuptools import setup
import os

setup(
    name='my-package',
    version='1.0',
    packages=['my-package'],
    install_requires=[
        # location to your my-package project directory
        "file:\\" + os.path.join(os.path.dirname(os.getcwd()), 'utils#egg=utils-1.0')
    ]
)

Unfortunately this errors out with the following:

    ERROR: Command errored out with exit status 1:
     command: /path/to/python/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/home/my-package/setup.py'"'"'; __file__='"'"'/home/my-package/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info
         cwd: /home/my-package/
    Complete output (1 lines):
    error in my-package setup command: 'install_requires' must be a string or list of strings containing valid project/version requirement specifiers; Invalid requirement, parse error at "'://home/'"
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

I have tried the solutions here with no luck. Any help is greatly appreciated.


Solution

  • dependency_links is deprecated. This is a ugly hack, a very bad practice. I do not recommend you do this.

    This hack is meant to be installed as python setup.py install, which is nowadays also deprecated. If you install with pip, then most likely this won't work.

    In general, relative path dependencies are always a bad idea in Python packaging, I would recommend you solve it a different way.

    With that said, something like this could work, or at least could have worked at some point in the past:

    .
    ├── One
    │   ├── one
    │   │   └── __init__.py
    │   └── setup.py
    └── Two
        ├── setup.py
        └── two
            └── __init__.py
    

    One/setup.py

    #!/usr/bin/env python3
    
    import setuptools
    import pathlib
    
    TWO_PATH = pathlib.Path(__file__).resolve().parent.parent.joinpath('Two')
    
    setuptools.setup(
        name='One',
        version='1.2.3',
        packages=['one'],
        install_requires=['Two'],
        dependency_links=[
            'file://{}#egg=Two-1.2.3'.format(TWO_PATH),
        ],
    )