Building python packages for debian

How to build and distribute python packages in deb files

Posted on Sun 04 June 2017

There are many ways how to build & distribute python packages: pypi, devpi. But if you happen to use debian based OSes you can build python packages as debian native ones. This blog post is all about it - let's go!

Let's say you have following structure of your project:

├── Makefile
├── MANIFEST.in
├── requirements.txt
├── setup.py
└── src
    └── python_deb_pkg
        ├── __init__.py
        └── main.py

How to pack it for debian? First create a new folder in root directory of your project: debian. Then create a couple of files that are required to properly build the package:

changelog:

python-deb-pkg (0.1.0-1) UNRELEASED; urgency=low

* python-deb-pkg: Initial debian packaging

-- Krzysztof Zuraw <[email protected]>  Sat, 3 Jun 2017 12:34:56 +0000

compat:

9

control:

# ------------------------------------------------------------------------- #
# DEBIAN PACKAGE CONTROL FILE                                               #
#                                                                           #
# This file is a Debian control file. For more information on the config in #
# this file, please run `man deb-control`.                                  #
# ------------------------------------------------------------------------- #

Source: python-deb-pkg
Section: contrib/python
Priority: extra
Maintainer: Krzysztof Żuraw <[email protected]>
Build-Depends: debhelper (>= 9), python3.5, python3-setuptools, dh-virtualenv (>> 0.6)
Standards-Version: 3.9.5

Package: python-deb-pkg
Architecture: any
Pre-Depends: dpkg (>= 1.16.1),  python3.5
Depends: make
Description: python-deb-pkg service

copyright:

Copyright (c) 2017+, Krzysztof Żuraw <[email protected]>

MIT Licensed.

**TODO** Copy main project's license file here.

and rules:

#!/usr/bin/make -f

%:
    dh [email protected] --with python-virtualenv

override_dh_virtualenv:
    dh_virtualenv --python /usr/bin/python3.5 \
        --setuptools

override_dh_builddeb:
    dh_builddeb --destdir=/tmp/python-deb-pkg/debian/dist

Changelog will tell debian packaging tools what version they need to build. Compat contains a magic number for compatibility issues. copyright is license and rights. One of the two most important files is control. It tells what are dependencies that need to be resolved before the package will be built and installed. Second is rules that have makefile like syntax and specify how a package will be built.

I'm using here really cool package called dh-virtualenv. Basically, it doing all hard work: making sure that virtualenv is correctly setup or files are in their places. In my example, I tell dh_virtualenv to use python3.5 which is by default in ubuntu 16.04. In override_dh_builddeb I specified where build package should be present root_folder/debian/dist.

How to use all these files combined? I use docker for that! I have Dockerfile inside debian folder:

FROM ubuntu:16.04
MAINTAINER Krzysztof Zuraw <[email protected]>


RUN apt-get update && apt-get install --yes \
        software-properties-common \
        build-essential \
        debhelper \
        devscripts \
        equivs \
        python3-dev


ADD ./debian/control /tmp/python-deb-pkg/debian/control
RUN mk-build-deps --install /tmp/python-deb-pkg/debian/control --tool "apt-get --allow-downgrades --yes"

WORKDIR /tmp/python-deb-pkg

ADD . /tmp/python-deb-pkg

The most interesting line here is the one that builds and install build dependencies for my package - mk-build-deps.

Everything is controlled via Makefile inside the main folder:

.PHONY: deb deb-build-env deb-enter-docker

    deb-build-env:
        docker build \
            --file=./debian/Dockerfile \
            --tag=python-deb-pkg \
            ./

    deb: deb-build-env
        if [ ! -d ./debian/dist ]; then \
            mkdir ./debian/dist; \
        fi;
        if [ -e ./debian/dist/*.deb ]; then \
            sudo rm ./debian/dist/*.deb; \
        fi;
        docker run \
            --volume=$$(pwd)/debian/dist:/tmp/python-deb-pkg/debian/dist \
            python-deb-pkg dpkg-buildpackage -us -uc -b --changes-option=-udebian/dist/

    deb-enter-docker:
        docker run \
            --interactive \
            --tty=true \
            --volume=$$(pwd):/tmp/python-deb-pkg \
            python-deb-pkg /bin/bash

deb rule is creating a debian package inside docker by dpkg-buildpackage -us -uc -b --changes-option=-udebian/dist/ which means that deb file won't be signed and exit directory should be debian/dist.

And thats all for today! Repo is available under this address. Feel free to comment!

Cover image from Unsplash under CC0.

If you find this blog post interesting please share:

Comments !