:Version: 0.2.2 :Last Revised: Aug 23, 2006 :ChangeLog: Update the setuptools/egg section due to a new setuptools in Extras.
Hints on how to Package Python modules
Hints on how to Package Python modules
Python version
In the past (FC3 and earlier) it was mandatory to add the line
Requires: python-abi = %(%{__python} -c "import sys ; print sys.version[[3]] ")
to the spec file to require a specific version of the python-abi. This is not needed anymore in FC4 and later because rpm adds a automatic dependency on python(abi) now on its own.
System Architecture
If you are installing anything into the global site_packages directory, use the following trick. First, define python_sitelib at the top of your specfile:
%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
On an i386 python-2.4 system, for example, %{python_sitelib} will be /usr/lib/python2.4/site-packages
. During %install, or when listing %files, you can use the %{python_sitelib} macro to specify the path. For example:
%files %defattr(-,root,root,-) %dir %{python_sitelib}/modulename %{python_sitelib}/modulename/*.py %{python_sitelib}/modulename/*.pyc
For python modules that include any architecture-specific libraries (like those written in C), you should additionally use:
%{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
This will ensure the package is installed correctly on multilib architectures. By using these macros instead of hardcoding the directory in the specfile your spec remains compatible with the installed python version even if the diretory structure changes radically (for instance, if python_sitelib moves into %{_datadir})
You shouldn't rely on INSTALLED_FILES, as that will not list directories, which will need to be specified in the %files section as well. Using globs in the %files section is safer.
setuptools/eggs
Python packages that use setuptools need to add python-setuptools as a Build'Requires and must either add --single-version-externally-managed
to the line invoking setup.py in %install, or must add a .pth file containing the path to the egg or egg directory to %{python_sitelib}.
- As of setuptools-0.6a11 the setuptools homepage recommends using the
--root
switch instead of--single-version-externally-managed
. This needs to be looked at further, but seems like it is okay to do this way.
Further egg information that needs to be distilled out here: http://permalink.gmane.org/gmane.comp.python.distutils.devel/2567 http://mail.python.org/pipermail/distutils-sig/2005-November/005399.html
Byte Compiled Files
Python will automatically try to byte compile files when it runs in order to speed up startup the next time it is run. These files are saved in files with the extension of .pyc (compiled python) or .pyo (optimized compiled python). These files are a byte code that is portable across OSes. If you do not include them in your packages, python will try to create them when the user runs the program. If the system administrator uses them, then the files will be successfully written. Later, when the package is removed, the .pyc and .pyo files will be left behind on the filesystem. To prevent that you need to byte compile the files when building your package and include the files in the %files section.
If you are only going to build for FC4+, rpm has a script that will create the files for you. All you have to do is remember to include the files in your spec file. The following are all acceptable ways to accomplish this:
%install install -d %{python_sitelib}/foo install -pm 0644 foo.py %{python_sitelib}/foo/ Either: %files %dir %{python_sitelib}/foo %{python_sitelib}/foo/foo.py %{python_sitelib}/foo/foo.pyc %{python_sitelib}/foo/foo.pyo Or: %files %dir %{python_sitelib}/foo %{python_sitelib}/foo/foo.py* Or even: %files %{python_sitelib}/foo/
For Core releases earlier than FC4, you need to generate the .pyc and .pyo files yourself.
If your module is using distutils, use the following commands during %install:
%{__python} setup.py install --skip-build --root $RPM_BUILD_ROOT %{__python} setup.py install -O1 --skip-build --root $RPM_BUILD_ROOT
And remember to add the .pyc and .pyo files to your %files section.
Including pyos
In the past it was common practice to %ghost .pyo files in order to save a small amount of space on the users filesystem. However, this has two issues: 1. With SELinux, if a user is running python -O [APP] it will try to write the .pyos when they don't exist. This leads to AVC denial records in the logs. 2. If the system administrator runs python -OO [APP] the .pyos will get created with no docstrings. Some programs require docstrings in order to function. On subsequent runs with python -O [APP] python will use the cached .pyos even though a different optimization level has been requested. The only way to fix this is to find out where the .pyos are and delete them.
The current method of dealing with pyo files is to include them as is, no %ghosting.
Unnecessary Byte compilation
From FC4 to current development, the automatic byte compilation of python files that is performed by brp-python-bytecompile byte compiles all files that match *.py This is undesirable for program files in %{_bindir} and %{_sbindir} because the user will probably never invoke these files, only the main program file and python won't use these files. Until the bug is resolved, there are two workarounds: 1. Rename scripts in %{_bindir} to not have a .py extension: For instance, from /usr/bin/orient.py to /usr/bin/orient. 2. Use %exclude to exclude the scripts from the file listing:
%files %{_bindir}/orient.py %exclude %{_bindir}/orient.pyc %exclude %{_bindir}/orient.pyo
An open bug to address this issue is here: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=182498