I need to add rjsmin to my dependencies via install_require in a setup.py.
rjsmin offers a way to disable the c-extension by using the --without-c-extensions switch like following
python setup.py install --without-c-extensions
I wonder, how to add this switch to the install_require string.
I solved my problem of installing dependencies with global-options by sub-classing setuptools.command.install class and overriding its run() method, like following code -
from setuptools import setup
from setuptools.command.install import install
from subprocess import call
class CustomInstall(install):
def run(self):
install.run(self)
call(['pip', 'install', 'pycurl', '--global-option=--with-nss'])
setup( ...
cmdclass={
'install': CustomInstall,
},
)
Here, I am installing pycurl with global option --with-nss
You need to provide an --install-option or --global-option along with the requirement text.
You can refer the doc here
Related
Is there a way to specify optional dependencies for a Python package that should be installed by default from pip but for which an install should not be considered a failure if they cannot be installed?
I know that I can specify install_requires so that the packages will be installed for the 90% of users using OSes that can easily install certain optional dependencies, and I also know I can specify extra_require to specify that users can declare they want a full install to get these features, but I haven't found a way to make a default pip install try to install the packages but not complain if they cannot be installed.
(The particular package I'd like to update the setuptools and setup.py for is called music21 for which 95% of the tools can be run without matplotlib, IPython, scipy, pygame, some obscure audio tools etc. but the package gains extra abilities and speed if these packages are installed, and I'd prefer to let people have these abilities by default but not report errors if they cannot be installed)
Not a perfect solution by any means, but you could setup a post-install script to try to install the packages, something like this:
from distutils.core import setup
from distutils import debug
from setuptools.command.install import install
class PostInstallExtrasInstaller(install):
extras_install_by_default = ['matplotlib', 'nothing']
#classmethod
def pip_main(cls, *args, **kwargs):
def pip_main(*args, **kwargs):
raise Exception('No pip module found')
try:
from pip import main as pip_main
except ImportError:
from pip._internal import main as pip_main
ret = pip_main(*args, **kwargs)
if ret:
raise Exception(f'Exitcode {ret}')
return ret
def run(self):
for extra in self.extras_install_by_default:
try:
self.pip_main(['install', extra])
except Exception as E:
print(f'Optional package {extra} not installed: {E}')
else:
print(f"Optional package {extra} installed")
return install.run(self)
setup(
name='python-package-ignore-extra-dep-failures',
version='0.1dev',
packages=['somewhat',],
license='Creative Commons Attribution-Noncommercial-Share Alike license',
install_requires=['requests',],
extras_require={
'extras': PostInstallExtrasInstaller.extras_install_by_default,
},
cmdclass={
'install': PostInstallExtrasInstaller,
},
)
The simplest way to do this is by adding a custom install command that simply shells out to pip to install the "optional" packages. In your setup.py:
import sys
import subprocess
from setuptools import setup
from setuptools.command.install import install
class MyInstall(install):
def run(self):
subprocess.call([sys.executable, "-m", "pip", "install", "whatever"])
install.run(self)
setup(
...
cmdclass={
'install': MyInstall,
},
)
Like hoefling said above, this will only work if you publish a source distribution (.tar.gz or .zip). It will not work if you publish your package as a built distribution (.whl).
This might be what you are looking for. It's appears to be a built in feature of setup tools that allows you to declare "optional dependencies".
https://setuptools.pypa.io/en/latest/userguide/dependency_management.html#optional-dependencies
Ex
setup(
name="Project-A",
...
extras_require={
'PDF': ["ReportLab>=1.2", "RXP"],
'reST': ["docutils>=0.3"],
}
)
# setup.py
from setuptools import setup
from setuptools.command.install import install
from subprocess import check_call
class CustomInstall(install):
def run(self):
check_call("./build.sh")
install.run(self)
setup(
name='customlib',
packages=['customlib'],
version='0.0.1',
...
cmdclass={'install': CustomInstall}
)
build.sh contains a make & make install step which takes more than 10 minutes to finish.
Is there a PyPi way to "package" the output of build.sh to speed up the pip install process?
Use wheel. A wheel is a great standard format for passing around Python packages, and it can contain C code compiled for various architectures. PyPI supports uploading wheels for your project, and pip will download them when available.
Very useful docs can be found here: https://packaging.python.org/tutorials/distributing-packages/#packaging-your-project
import os
from setuptools import setup
from distutils.command.install import install as _install
def _post_install(dir):
from subprocess import call
call([sys.executable, 'post_script.py'],
cwd=os.path.join(dir, 'script_folder'))
class install(_install):
def run(self):
_install.run(self)
self.execute(_post_install, (self.install_lib,),
msg="Running post install task")
VERSION = '123'
setup(name='XXXX',
description='hello',
url='http://giturl.com',
packages=['package_folder'],
cmdclass={'install': install},
package_data={
'package_folder': [
'*.py',
'se/*pp'
],
},
)
#
Basically the postscript should execute once I install the rpm that is being built.
Its not working.
Any other method as this is not working?
You can run python setup.py bdist_rpm --post-install=<script name>
This will create an rpm which will run the contents of the script you provide after the normal rpm installation is completed.
If you want to do it in your setup.py you can pass along
setup(
...
options={'bdist_rpm': {'post_install': '<post_install script name>'}},
...
)
This will only affect bdist_rpm, and thus only the rpm you create with python setup.py bdist_rpm
From resources online, I've learned that the following will add a "post-install" hook if included in setup.py:
from setuptools import setup
from setuptools.command.install import install as _install
class install(_install):
def run(self):
_install.run(self)
# Do something magical
setup(cmdclass={'install': install})
What I'd like to do, though, is create equivalent behavior after a setup.py clean is executed. Specifically, I'd like setup.py clean to remove the .egg-INFO directory created during the execution of setup.py egg_info.
I have used pip to install PIL. It requires two additional arguments while installation. So the command for installation looks something like this.
pip install PIL --allow-external PIL --allow-unverified PIL
I need to add the PIL package in setup.py file. Adding PIL in the install_requires list do install PIL but it doesn't work, as I need to install PIL with the additional arguments.
So how can I add the PIL to the install_requires list with additional arguments ?
Currently, there is no way to specify extra arguments in install_requires in setup.py. But, I solved my problem of installing dependencies with global-options by sub-classing setuptools.command.install class and overriding its run() method, like following code -
from setuptools import setup
from setuptools.command.install import install
from subprocess import call
class CustomInstall(install):
def run(self):
install.run(self)
call(['pip', 'install', 'PIL', '--allow-external', 'PIL', '--allow-unverified', 'PIL'])
setup( ...
cmdclass={
'install': CustomInstall,
},
)
Just replace PIL with Pillow (in your install_requires). It's a fork of PIL with bugfixes, py3k support and proper hosting. You don't need to change your code.