Packaging/Python

From openSUSE

Note: the page is not yet updated to fully reflect the new noarch-ness of python modules. This will be corrected soon, but for now, use with care.

Contents

Hints on how to Package Python modules

A simplest case

Here's a simple (probably incomplete) spec of the simplest possible pure python package.

# norootforbuild

Name:           python-yourpackage
Version:        1.0
Release:        1
Summary:        The coolest ever pythonic package
License:        Your Package License
Group:          Development/Libraries/Python
Source:         python-yourpackage-%{version}.tar.bz2
BuildRequires:  python-devel
BuildRoot:      %{_tmppath}/%{name}-%{version}-build
%{py_requires}


%description
(whatever)


%prep
%setup -q


%build
%{__python} setup.py build


%install
%{__python} setup.py install --prefix=%{_prefix} --root=%{buildroot} --record-rpm=INSTALLED_FILES


%files -f INSTALLED_FILES
%defattr(-,root,root)

Noarch modules

Note: this section only applies to bleeding_edge_python repositories (see devel:languages:python:Factory project in OBS) and the VERY LATEST factory (at this moment, the request is not accepted yet). I hope to get this into 11.2, but i guarantee nothing.

It is now possible (and even necessary) to build pure python modules as noarch. To do that can be as simple as including the noarch parameter into the spec:

BuildArch: noarch

If you are writing filelist on your own (i.e. not using --record-rpm), you will need new fedora-compatible macros, %python_sitelib for pure python modules (expands to /usr/lib/pythonX.Y/site-packages) and %python_sitearch for arch-dependent (expands to /usr/lib(64)/pythonX.Y/site-packages). Those macros are defined within our python.
But if you want to be compatible, use Fedora's definitions.

Split python

Since 11.1, openSUSE's python is split into three important packages:

  • python-base contains the python interpreter and parts of the standard library that don't pull in extra dependencies (i.e. most of it). A subpackage of this is python-xml.
  • python contains bsddb, hashlib, sqlite3, ssl and readline. It also has some subpackages, the important being python-gdbm, python-curses, python-idle and python-tk
  • python-devel is what you'd expect, the include files and .so symlink

For everyday use, you would want python (because of readline).
For development of pure python packages, you only need python-base, unless of course your package uses one of the separated parts of stdlib.
Distutils come as a part of python-base.
For everything else, as they say, there's python-devel.

Naming policy

All python modules, whether pure python or C-based, should be called python-modulename. The build process check for this and issues a warning whenever it finds a python file in a package not named this way.

modulename should be the name of this module's directory in site-packages.

This policy doesn't apply to end-user applications written in python.

BuildRequires

In the simplest case, use %{py_requires} macro.

If you are building a C module, use %{py_requires -d}. That pulls in python-devel.

If you are aiming for the simplest possible BuildRequires, you will want to manually include python-base and possibly python-devel instead of using the macro. Note that this works only in openSUSE from 11.1 up, in earlier versions you always needed to buildrequire python-devel that had a big dependency list.

Python version

In openSUSE, even version-agnostic python packages need to depend on a specific python series. A python series is denoted by python's major and minor version. For example, the current (as of 8.6.2009) python series is 2.6 for the stable (legacy) line and 3.1 for py3k.
This is because you are installing into version-specific directory /usr/lib(64)/pythonX.Y/site-packages, where X.Y is the series.

The %{py_requires} macro will require the correct version for you.

Since 11.0, you can require python = %{py_ver}. %{py_ver} expands to series denomination.

In earlier openSUSE versions, you need to either require the specific python release (including subminor version), or require python >= X.Y and python < X.(Y+1). Again, %{py_requires} will do this for you.
Note, however, that this approach is flawed. For one, to work with multiple python versions, you'd need to calculate X.(Y+1) for yourself (see /usr/lib/rpm/macros for how to do that). And for two, such requirement is also satisfied if there are two different pythons installed, one from a newer series and one from an older series.

System Architecture

Even pure python packages in openSUSE must be arch-dependent. Again, that is because you're installing into /usr/lib(64)/pythonX.Y.

For file lists, you can use some predefined macros. %{py_libdir} expands to either /usr/lib/pythonX.Y or /usr/lib64/pythonX.Y depending on the architecture, and %{py_sitedir} expands to %{py_libdir}/site-packages.

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 py_sitedir moves into %{_datadir})

File locations

Since 10.3, openSUSE's distutils are configured to install into /usr/local by default, mimicking autotools. When issuing the install command, you need to specify --prefix=%{_prefix} so that the package is installed into the correct /usr prefix.

All python source and bytecode files should go into /usr/lib(64)/pythonX.Y/site-packages, or maybe /usr/lib(64)/yourapp. FHS says that /usr/share hierarchy should only contain data, so don't install sources in there.
This is not a strict requirement, though, only a recommendation. If your package's upstream is bent on installing to /usr/share, please try to convince them of the error of their ways, but don't feel obliged to patch the package to death just so it installs into /usr/lib.

File lists

openSUSE's python defines a pretty useful extension to distutils install command: --record-rpm=<filename> is mostly the same as --record=<filename>, except it also lists directories in rpm-compatible format. Therefore, you can easily use the following:

%install
python setup.py install --prefix=%{_prefix} --root=$RPM_BUILD_ROOT --record-rpm=INSTALLED_FILES

%files -f INSTALLED_FILES

Hopefully we'll manage to push this enhancement upstream.

setuptools/eggs

Warning
This text was imported from Fedora Guidelines and not reviewed for use in openSUSE yet. Use at your own risk.

In the past, Fedora has done the minimal amount to support eggs for upstream distros. As eggs are being adopted more widely upstream we need to have more comprehensive documentation on how to handle this. The following are a summary of the guidelines for reviewers to go over. The complete policy includes examples and rationale for the way we do things.

  • Must: Python eggs must be built from source. They cannot simply drop an egg from upstream into the proper directory.
  • Must: Python eggs must not download any dependencies during the build process.
  • Must: If egg-info files are generated by the modules build scripts they must be included in the package.
  • Must: When building a compat package, it must install using easy_install -m so it won't conflict with the main package.
  • Must: When building multiple versions (for a compat package) one of the packages must contain a default version that is usable via "import MODULE" with no prior setup.
  • Should: A package which is used by another package via an egg interface should provide egg info.

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.

Many packages install byte-compiled .pycs and .pyos by themselves. If your package doesn't do that, you should use %{py_compile} <directory> to create .pyc and %{py_compile -O} <directory> for .pyo files.

Most of the time, .pyo files are exactly the same as .pyc. From 11.0 up, you can save space by running fdupes to hardlink them together.

BuildRequires: fdupes
(...)

%install
(...)
%fdupes $RPM_BUILD_ROOT%{py_sitedir}

Summary of useful rpm macros

  • %py_ver - python series denomination (major.minor version number)
  • %py_prefix - python installation prefix (should be /usr most of the time)
  • %py_libdir - python's directory within %_libdir. Expands to %{py_prefix}/%{_lib}/python%{py_ver}
  • %py_incdir - python's directory within %_includedir. Expands to %{py_prefix}/include/python%{py_ver}
  • %py_sitedir - site-packages directory. Expands to %{py_libdir}/site-packages
  • %py_compile - byte-compiles python sources from the specified directory. Use %{py_compile -O} to produce optimized bytecode (.pyo)
  • %py_requires - specifies a BuildRequires for the python interpreter and Requires (actually PreReq) for specific python series. Use %{py_requires -d} to also require python-devel