0

I want to make a distributable package. And my package depends on some OS package

Here what I want to install:

def install_libmagic():
    if sys.platform == 'darwin':
        subprocess.run(['brew', 'install', 'libmagic'])
    elif sys.platform == 'linux':
        subprocess.run(['apt-get', 'update'])
        subprocess.run(['apt-get', 'install', '-y', 'libmagic1'])
    else:
        raise Exception(f'Unknown system: {sys.platform}, can not install libmagic')

I want this code to be executed only when smb call: pip install mypacakge

I don't want it to be executed when I run: python setup.py bdist_wheel

How can I achieve this?

I tried this:

setup(
    ...
    install_requires=install_libmagic(),
)

Also tried to override install command:

from setuptools.command.install import install

class MyInstall(install):
    def run(self):
        install_libmagic()
        install.run(self)
setup(
    ...
    cmdclass={'install': MyInstall}
)

But the function was executed on python setup.py bdist_wheel, which is not what I am trying to achieve.

Snobby
  • 1,067
  • 3
  • 18
  • 38
  • 2
    `setup.py` usually isn't run as root. – Charles Duffy Sep 28 '20 at 15:17
  • 2
    ...if you want to install OS packages, have you considered making a OS package _for your Python module_? Then someone installing _your_ package with `apt` will get the others as dependencies. – Charles Duffy Sep 28 '20 at 15:18
  • 1
    (Mind, folks using [Nix](https://nixos.org/) can have cross-language dependency chains without trouble, but that's very much its own thing). – Charles Duffy Sep 28 '20 at 15:20
  • `usually isn't run as root` well, that's the point, didn't thought about it. My package is for local index only (for company purposes), so I know that it's basically is launched by root. – Snobby Sep 28 '20 at 15:21
  • `apt` package is an interesting option, haven't tried it before, maybe I should now:) – Snobby Sep 28 '20 at 15:21
  • See [`Python/LibraryStyleGuide`](https://wiki.debian.org/Python/LibraryStyleGuide?action=show&redirect=Python%2FPackaging) or the Debian wiki for guidance on making dpkg packages you can install with apt (unless you're using apt4rpm or similar, in which case you need to build a spec file -- which is arguably easier). – Charles Duffy Sep 28 '20 at 15:23
  • I hope there are still options to do this with `python setup.py bdist_wheell` and `pip install`, I just haven't digged enough to find the answer:) – Snobby Sep 28 '20 at 15:24
  • 2
    Gotcha. If you're guaranteed your `pip install` will happen is root, I'm quite certain there are options, but it's not a usage mode I'm willing to support -- even if I write up an answer for you to use internally, someone else is going to try to use it for a package they're publishing to the public. – Charles Duffy Sep 28 '20 at 15:25
  • oh, you really know the answer?) The answer can be written with a disclaimer "Do not do this for public package" or just be written in comments. I spent hours googling for it:) – Snobby Sep 28 '20 at 15:30
  • 1
    See https://github.com/mschwager/0wned – Charles Duffy Sep 28 '20 at 15:48
  • thanks man, I realised that it's possible through installation of the source code (because setup.py is launched) but it's not possible through wheel installation – Snobby Sep 28 '20 at 17:03

1 Answers1

1

I think you're mixing up the behaviors of built distributions (wheels) and source distributions.

If your goal is run some subprocesses at install time, then you can't do this with a built distribution. A built distribution executes no Python code at install time. It only executes setup.py at build time, which is why you're seeing your functions executed when you call python setup.py bdist_wheel.

On the other hand, a source distribution (python setup.py sdist) does execute the setup.py file at both build time and install time (roughly the same as python setup.py install) and would give you the behavior you're looking for.

However, as the comments have already mentioned, this is going to be very fragile and not very user-friendly or portable. What you're describing is really a distro/OS package that contains some Python module, and you'd probably be better off with that instead.

Dustin Ingram
  • 20,502
  • 7
  • 59
  • 82
  • Thanks man. I realised that it is not possible through python wheels, but is possible through installation of the source code. – Snobby Sep 28 '20 at 17:02
  • Marking question as resolved. If you want to achieve what I wanted, just override install command`cmdclass={'install': PostInstallCommand}` upload your code to the repository, and install it with smth like `git+https://github.com//.git@` – Snobby Sep 28 '20 at 17:07