1

for the sake of the question, let's assume that under one git repository, I'm developing 2 independent packages. Consider the following structure:

my_repo/

    package1/
        ...some modules

    package2/
        ...some modules

    setup.py

setup.py code is:

from setuptools import setup

setup(
    name='Cool_package',
    version=1.0,
    description='...',
    author='Myself',
    packages=['package1', 'package2'],
    install_requires=[
                      ...
                     ]
    )

I'm using this command to install the packages in desired manner (avoiding python setup.py install or develop):

pip install -e .

And both package1 and package2 are installed.

My question is there a way to install only one of the two (user decides which one), considering that mentioned above structure requires them to share one setup.py file?

Again, I'm aware of that structure is not ideal (ideally I would split the packages into 2 separated repos).

Many thanks in advance!

NI6
  • 2,477
  • 5
  • 17
  • 28
  • 1
    i can see 2 options here: passing some [parameter into `setup.py`](https://stackoverflow.com/questions/677577/distutils-how-to-pass-a-user-defined-parameter-to-setup-py) (had never tried, may be too difficult) or write `setup.py` for each of packages and call them separately – Azat Ibrakov Jul 31 '18 at 09:35
  • And where would you locate those 2 setup.py files? under each package main dir (package1, package2)? – NI6 Jul 31 '18 at 09:50
  • make current package directories subdirectories (like `package1` in directory `package1`) and place each of `setup.py` scripts in super-directories, example of hierarchy: `my_repo/package1/ setup.py package1/...some modules` and `my_repo/package2/ setup.py package2/...some modules` – Azat Ibrakov Jul 31 '18 at 09:56
  • @NI6 By the way, in the question you mention that *"under one git repository, I'm developing 2 independent packages"*. However according to the `setup.py` file you have *one* package (\wrt how a Python package is configured) which happens to install two packages (\wrt `import` statements). With respect to package distribution you only have one package though. If you want two different packages you need two different scripts. Also note that packages are identified by their names, not by what they actually package. Furthermore for `-e` mode it doesn't even matter since a symlink is used. – a_guest Jul 31 '18 at 16:03

1 Answers1

1

I suggest you to create one setup script for each package. You can share common information via a general setup.py script like so:

repo/
├── bar
├── foo
├── setup_bar.py
├── setup_foo.py
└── setup.py

2 directories, 3 files

Then the common setup.py file would contain the following code. It can also be used to install both packages at once:

from functools import partial
from setuptools import setup

setup = partial(
    setup,
    name='Cool_package',
    version=1.0,
    description='...',
    author='Myself',
    packages=['foo', 'bar']
)

if __name__ == '__main__':
    setup()

The separate setup_*.py scripts would reuse that information and only install a single package:

from setup import setup

setup(packages=['foo'])  # For `setup_foo.py`.
setup(packages=['bar'])  # For `setup_bar.py`.

This way the user can choose which package to install by using the corresponding setup script.

a_guest
  • 34,165
  • 12
  • 64
  • 118
  • And how would the user choose which package is needed in the CLI? pip install -e . foo? – NI6 Jul 31 '18 at 11:15
  • 1
    @NI6 You can install from a specific setup file via `python setup_*.py develop`. – a_guest Jul 31 '18 at 11:53
  • 1
    @NI6 If you want to use `pip` another option would be to rename `mv setup.py setup_all.py` (as well as the `import` statements accordingly: `from setup_all import setup`) and then create a symlink before installing with pip: `ln -s setup_foo.py setup.py && pip install -e .`. pip always installs from `setup.py`, this is (at least *was*) apparently [hard coded](https://stackoverflow.com/a/38957066/3767239). – a_guest Jul 31 '18 at 12:45
  • Can you think of a way without using setup.py develop? from what I've read it's not so good with dependencies – NI6 Jul 31 '18 at 13:35
  • @NI6 See my above comment about creating a symlink. `pip` will always attempt to install from `setup.py`. If you don't like that either then you have two other options: 1. Create one separate top-level directory for each package and have two separate `setup.py` scripts (one per package). You can still share data by tweaking `sys.path.append('..')`. This will however change the overall structure of your actual package such that the OP's `setup.py` cannot be retained. 2. Create your own fork of [`pip`](https://github.com/pypa/pip) and modify it such that it allows for setup file specification. – a_guest Jul 31 '18 at 15:42
  • 1
    NEVER use `python setup.py install` (or develop). It is a mess and makes you unable to automatically uninstall the package – Adrian Jan 16 '23 at 07:15