Piyush S. Wanare
Piyush S. Wanare

Reputation: 4943

Setuptools package discovery

I have below package tree for my project


└── src
|    ├── mypkg1
|    │   ├── module1.py
|    │   ├── module2.py
|    │   └── __init__.py
|    |   |-- setup.py
|    |   |__ requirements.py 
|    └── mypkg2
|        ├── module1.py
|        └── __init__.p
|
|---- base
|      |----- init.py
|      |----- module1.py      

Note - src and base are at same level.

How should I configure setup.py file, so that I can install base and mypkg1 packages only and exclude mypkg2.

I have tried mentioning ['base','mypkg1'] in packages but didn't worked also tried using find_packages() it will show up only mypkg1 and mypkg2.

Upvotes: 3

Views: 5432

Answers (1)

hoefling
hoefling

Reputation: 66581

There are multiple things to take care of due to the complex codebase layout. Also, I'm not sure why you are showing the setup script inside src/mypkg1 - invoking it from there will not find anything outside of src and thus you'll have no chance to include base. In the below example, I switched to the root directory containing both src and base dirs:

project_root
├── src/
├── base/
└── setup.py

Package discovery

Since base is under the project root, it will be discovered by plain find_packages invocation:

>>> from setuptools import find_packages
>>> find_packages()
['base']

To find packages under src, pass it via where argument:

>>> from setuptools import find_packages
>>> find_packages(where='src')
['mypkg1', 'mypkg2']

To exclude mypkg2, pass it via the list in exclude argument:

>>> from setuptools import find_packages
>>> find_packages(where='src', exclude=['mypkg2'])
['mypkg1']

Package structure mapping and file inclusion

Calling setuptools.setup() as is with the collected packages will only work for base, since mypkg1 is not on the root level. You have to map its location via package_dir:

setup(
    ...,
    package_dir={'': 'src'},
)

This, however, instructs setup() to look for files of all packages in src, which makes files under base not findable. You thus have to map it explicitly:

setup(
    ...,
    package_dir={'': 'src', 'base': 'base'},
)

Complete minimal setup script

from setuptools import setup, find_packages

setup(
    name='...',
    version='...',
    packages=find_packages() + find_packages(where='src', exclude=['mypkg2']),
    package_dir={'': 'src', 'base': 'base'},
)

Now when e.g. building a wheel, this will produce the following file layout:

  Length      Date    Time    Name
---------  ---------- -----   ----
        0  06-24-2022 21:55   base/__init__.py
        0  06-24-2022 21:55   base/module1.py
        0  06-24-2022 21:54   mypkg1/__init__.py
        0  06-24-2022 21:54   mypkg1/module1.py
        0  06-24-2022 21:54   mypkg1/module2.py

Upvotes: 6

Related Questions