RPMing Python

I was fighting with packaging some software at work, trying to produce a workable RPM package to replace the manually installed kludge currently polluting one of our servers, and discovered the --spec-only option to the bdist_rpm action.

Now, this particular option only makes sense since a spec file must be generated for bdist_rpm to work anyway, but I never thought about it. What it provides is an awesome shortcut to doing packaging slightly more complicated than merely relying on what bdist_rpm produces. Why? Because of the sdist action.

After having obtained the automatically generated spec file, I altered it to include some shell scripts that weren’t really part of the distribution, but were in the source repository. This let me alter the %build, %install, and %files sections of the spec file to work the way I wanted. Then I left the resulting spec file in the same directory as setup.py so it would be included when sdist built the source distribution. What this gives you, is that the RPM can now be built without even unpacking the tarball.

rpmbuild -ta yourpackage-1.0.0.tar.gz

How handy is that?

In addition, the parts I overrode in my static spec file can be placed in their own files and referred to in setup.cfg.


I should also note that there is no way to override or append the %files section, but that’s easy to fix. Setuptools appends all the files it needs to install in a file named INSTALLED_FILES. This file is fully compatible with all RPM commands valid in the %files section, so you can add something like this to your install_script:

echo "%{_bindir}/run_some_script" >> INSTALLED_FILES
echo "%{_libdir}/etl/mylib.sh" >> INSTALLED_FILES

Combine these two methods, and you can always generate a static spec file before a release to go with your package for distribution, or even have setup.py generate it for you. It’s fairly common for a spec file to be included with source distributions, so users will enjoy the addition, even if you don’t realize it.