Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make setup.py install multiple top-level packages?

I have a python package that I would like to organize like so:

root/
    setup.py
    package1/
        __init__.py
        package2/
            __init__.py
        package3/
            __init__.py

I would like setup.py to install package1, package2, and package3 into the correct site-packages/ directory as top level packages, so that I could execute

import package1
import package2
import package3

without a problem. Perhaps this needs multiple setup.py files?

But most importantly, I'd like to ultimately be able to install all three packages by executing pip install root. How do I do this? Preferably a distutils-only solution, though setuptools is ok as well.

like image 943
Uri Laserson Avatar asked Oct 25 '25 00:10

Uri Laserson


2 Answers

You can try

packages=['package1', 'package2', 'package3'],
package_dir={
    'package2': 'package1',
    'package3': 'package1',
},

to tell distutils that packages 2 and 3 are located inside package1.

A full working setup.py could look like this:

#!/usr/bin/env python

from distutils.core import setup

setup(name='root',
      version='1.0',
      description='Root package',
      author='Me',
      author_email='[email protected]',
      url='https://example.org/root',
      packages=['package1', 'package2', 'package3'],
      package_dir={
          'package2': 'package1',
          'package3': 'package1',
      },
)

python -m pip install ./root installs the packages into the structure you look for, such that

import package1
import package2
import package3

work.

As a proof, this is how ls package* looks like in the site-packages dir:

package1:
__init__.py __pycache__

package2:
__init__.py __pycache__

package3:
__init__.py __pycache__

And this is the root-1.0.dist-info/RECORD file:

package1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
package1/__pycache__/__init__.cpython-37.pyc,,
package2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
package2/__pycache__/__init__.cpython-37.pyc,,
package3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
package3/__pycache__/__init__.cpython-37.pyc,,
root-1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
root-1.0.dist-info/METADATA,sha256=Z1crlNNrRhJwO6O2ujtNsCo9rURrPoZGE0--ZhuBZsU,190
root-1.0.dist-info/RECORD,,
root-1.0.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
root-1.0.dist-info/top_level.txt,sha256=svjaZCiNfClr21KxGb71MTR7bWON1-VZRPiPgM0FjV4,27
like image 57
Sebastian Höffner Avatar answered Oct 26 '25 14:10

Sebastian Höffner


I feel it is cleaner to have your development file/folder structure more closely represent the deployment structure.

What this means is, I'd place all three packages at the same level instead of nesting them.

If you subsequently want to be able to import all three via one of them, you can set up a dependency in your single setup.py file.

like image 44
JosefAssad Avatar answered Oct 26 '25 14:10

JosefAssad