Translation(s): English


Main Python page

Introduction

Pybuild is a newer (as in 2013) and more modular build system for Python packages.

Features:

debian/control

dh-python is a mandatory build dependency.

pybuild dh integration script (not pybuild itself) uses Build-Depends to figure out which interpreters it should build for. If package provides Python 2.X module it should build-depend on python-all (or python-all-dev in case of Python extensions), if it builds extensions with debug symbols: python-all-dbg; if it provides Python 3 script - python3 needs to be added to Build-Depends, etc.

One very important thing to get right is the Build-Depends line in the source package stanza. setuptools/distribute-based packages have the nasty habit of downloading dependencies from PyPI if they are needed at python setup.py build time. If the package is available from the system (as would be the case when Build-Depends is up-to-date), then distribute will not try to download the package, otherwise it will try to download it. This is a huge no-no, and pybuild internally sets the http_proxy and https_proxy environment variables (to http[s]://127.0.0.1:9/) to prevent this from happening.

dh_python2 and dh_python3 will correctly fill in the installation dependencies (via ${python:Depends and ${python3:Depends respectively), but it cannot fill in the build dependencies. Take extra care in getting this right, and double check your build logs for illegal access to pypi.python.org.

debian/rules

Here is a debian/rules file for you to start with. First, I'll show you the whole thing, then I'll explain it line by line.

#export DH_VERBOSE=1
export PYBUILD_NAME=foo

%:
        dh $@ --with python2,python3 --buildsystem=pybuild

The file starts with the standard #! line. I like adding the (commented out when uploading) DH_VERBOSE line because it can make build problems easier to debug.

The next line is:

export PYBUILD_NAME=foo

pybuild supports a number of variables which can be used to control such things as the destination directory for build artifacts for both the Python 2 and Python 3 builds. The defaults generally do the right thing, but you do need to at least tell pybuild the name of your package. Here, we're telling it that the name is foo. This should match the module name, so for example, in enum34, you'd see:

export PYBUILD_NAME=enum34

even though the binary packages that get produced are python-enum34 and python3-enum34.

The next line is the standard debhelper-based catch-all rule which is used to get the whole build started:

%:
        dh $@ --with python2,python3 --buildsystem=pybuild

What's important to note here is that both of the dh_python2 and dh_python3 helpers are being invoked, and also that the build system that dh will use is pybuild. There's a lot of magic packed into this line, and the pybuild manpage goes into more detail, but essentially what this does is:

Once all that's done, it properly installs all the files into binary packages.

You usually won't need debian/python-foo.install or debian/python3-foo.install files even if you have multiple binary packages, because again, pybuild does the magic for you (if PYBUILD_NAME is correctly set). You might need these if there are some non-standard installation tricks you need to implement.

CUSTOMIZATION

Pybuild can be configured via command line or CDBS-like - by exporting

PYBUILD_OPTION
PYBUILD_OPTION_$interpreter
PYBUILD_OPTION_$interpreter$version

env. variables in debian/rules, f.e.

export PYBUILD_DESTDIR_python2=debian/python-foo/
export PYBUILD_DESTDIR_python2-dbg=debian/python-foo-dbg/
export PYBUILD_DESTDIR_python3=debian/python3-foo/
export PYBUILD_DESTDIR_python3-dbg=debian/python3-foo-dbg/
export PYBUILD_DESTDIR_python3.1-dbg=debian/spam-pkg-with-python3.1-only/
export PYBUILD_DESTDIR_pypy=debian/pypy-foo/

export PYBUILD_INSTALL_ARGS_python3=--install-scripts=/usr/share/foo/

export PYBUILD_DISABLE=configure
export PYBUILD_DISABLE_python3.1=test

export PYBUILD_INTERPRETERS=python{version} python{version}-dbg
export PYBUILD_VERSIONS=2.7 3.3

export PYBUILD_SYSTEM=distutils

export PYBUILD_BEFORE_BUILD=echo {version} >> '{dir}/enabled'
export PYBUILD_AFTER_INSTALL=rm -rf '{destdir}/{install_dir}/foo/tests'

export PYBUILD_SYSTEM=custom
export PYBUILD_CLEAN_ARGS=rm -rf {build_dir}/python{version}/
export PYBUILD_CONFIGURE_ARGS=./configure --python={version}
export PYBUILD_BUILD_ARGS=make build --dir={build_dir} --python={version}
export PYBUILD_INSTALL_ARGS=make --destdir={destdir} --python={version} --install-dir={install_dir}
export PYBUILD_TEST_ARGS_python2=cd {build_dir}; nosetests
export PYBUILD_TEST_ARGS_python3=cd {build_dir}; python{version} -m discover

export PYBUILD_BEFORE_TEST=cp -r {dir}/tests {build_dir}
export PYBUILD_BEFORE_TEST_python3=cp -r {dir}/tests {build_dir}; 2to3 -w {build_dir}/tests
export PYBUILD_AFTER_TEST=rm -rf {build_dir}/tests

export PYBUILD_TEST_ARGS=-k-test_that_needs_internet

export PYBUILD_INSTALL_ARGS=--install-lib=/usr/share/packagename/ --install-scripts=/usr/share/packagename/

Resources

Examples of packages using Pybuild on codesearch: search

introduction to pybuild and Python packaging talk at DebConf14: slides, video