9

In my project, I have a single setup.py file that builds multiple modules using the following namespace pattern:

from setuptools import setup

setup(name="testmoduleserver",
      packages=["testmodule.server","testmodule.shared"],
      namespace_packages=["testmodule"])

setup(name="testmoduleclient",
      packages=["testmodule.client","testmodule.shared"],
      namespace_packages=["testmodule"])

I am trying to build wheel files for both packages. However, when I do:

python -m pip wheel .

It only ever builds the package for one of the definitions.

Why does only one package get built?

Greg Fuller
  • 93
  • 1
  • 4
  • 2
    **This is not how you're supposed to use `setuptools.setup()`**. Can you give a more complete example of what your `setup.py` looks like? – Nils Werner Jul 12 '18 at 07:02

1 Answers1

18

You cannot call setuptools.setup() more than once in your setup.py, even if you want to create several packages out of one codebase.

Instead you need to separate everything out into separate namespace packages, and have one setup.py for each (they all can reside in one Git repository!):

testmodule/
    testmodule-client/
        setup.py
        testmodule/
            client/
                __init__.py
    testmodule-server/
        setup.py
        testmodule/
            server/
                __init__.py
    testmodule-shared/
        setup.py
        testmodule/
            shared/
                __init__.py

And each setup.py contains something along the lines

from setuptools import setup

setup(
    name='testmodule-client',
    packages=['testmodule.client'],
    install_requires=['testmodule-shared'],
    ...
)

and

from setuptools import setup

setup(
    name='testmodule-server',
    packages=['testmodule.server'],
    install_requires=['testmodule-shared'],
    ...
)

and

from setuptools import setup

setup(
    name='testmodule-shared',
    packages=['testmodule.shared'],
    ...
)

To build all three wheels you then run

pip wheel testmodule-client
pip wheel testmodule-server
pip wheel testmodule-shared
Nils Werner
  • 34,832
  • 7
  • 76
  • 98
  • Thanks! This is absolutely the right way to do it, and I've verified that it will work. I ended up fixing it the hacky way instead by using this answer: https://stackoverflow.com/a/50468000/10067085 which your answer helped me find. – Greg Fuller Jul 12 '18 at 15:18
  • I just came across this and those `pip wheel` commands didn't quite work for me. I needed to add a trailing `/`, and to specify `--no-deps` (at least for the two with `install_requires`. So e.g. I had `pip wheel --no-deps testmodule-client/` – gimboland Nov 14 '21 at 12:42
  • If I want to do something similar, but without the namespace package, do I still have to put each package I want to wheel into a subdirectory? – David Ghandehari Apr 03 '22 at 04:44
  • Yes, that would be the way to go – Nils Werner Apr 03 '22 at 08:28
  • I'd like to note that the part about sharing the namespace and building the packages works, but the concept of reusing testmodule.shared does not. For example, the testmodule.server cannot import anything from testmodule.shared - you end up with `ModuleNotFoundError: No module named testmodule.shared`. – alephzarro Jan 14 '23 at 10:48