Building python packages for debian

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 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
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

MIT Licensed.

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

and rules:

#!/usr/bin/make -f

%:
    dh $@ --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. It is 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


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!