Search code examples
pythonpippython-wheel

How do you build a wheel outside of a repo containing the package?


Question

Is there a way to build a wheel for a package while in a different repository such that the wheel has been built exactly as it would be if you built the wheel inside of the repository containing the package?

Example

Consider the following repo:

/repo-containing-your-package
      |___ your_module/
      |___ setup.py

Build method A

When I run python setup.py bdist_wheel from within repo-containing-your-package it builds the wheel as expected, including your_module. This means after I install pip install ./dist/your_module-#.#.#-py3-none-any.whl (which is successful), I can run python -m your_module.foo from the command line.

When the package is building, I get output that verifies that my module has been picked up by the wheel:

creating 'dist/your_module-#.#.#-py3-none-any.whl' and adding 'build/bar' to it
adding 'your_module/__init__.py'
etc...

Build method B

However, if I run python ../repo-containing-your-package/setup.py bdist_wheel from a repository that is a sibling to repo-containing-your-package, it does not build the wheel as expected, as it fails to include your_module. This means after I install pip install ./dist/your_module-#.#.#-py3-none-any.whl (which is successful), attempting python -m your_module.foo fails:

Error while finding module specification for 'your_module.foo' (ModuleNotFoundError: No module named 'your_module')

The fact that the module has not been properly installed with the package is confirmed by reviewing the build output, which does not include the adding 'your_module' output that method A includes.


Solution

  • Two solutions I know of:

    change working directory in setup.py

    If you can modify the setup script, you can change the working directory programmatically. Add an os.chdir call early enough in the setup script:

    import os
    from setuptools import setup
    
    os.chdir(os.path.dirname(__file__))
    
    setup(...)
    

    You can also change the working directory with other means without having to modify the setup script, e.g. in bash:

    $ pushd path/to/repo; python setup.py bdist_wheel; popd
    

    Use pip wheel

    pip has a subcommand wheel that builds a wheel from the given arg; this arg is usually the name of the package, but can be a directory containing the setup script. Pass -e in that case so the wheel has the correct name:

    $ pip wheel -e path/to/repo