github gitlab twitter
Wrapping up our Cookiecutter template
Feb 2, 2015
8 minutes read

We are about to wrap up this tutorial on how to create a Cookiecutter template for an Android application running Kivy.

If you haven’t checked out Create your own Cookiecutter template and Extending our Cookiecutter template yet, please do so as this post draws on them.

The current project structure of Cookiedozer is as follows:

├── cookiecutter.json
├── {{cookiecutter.repo_name}}
│   ├── {{cookiecutter.repo_name}}
│   │   ├── {{cookiecutter.app_class_name}}.kv
│   │   ├── {{cookiecutter.repo_name}}.py
│   │   ├──
│   │   └──
│   ├── LICENSE
│   ├──
│   ├── README.rst
│   ├──
│   └── tests
│       └── test_{{cookiecutter.repo_name}}.py
├── cookiedozer01.png
├── cookiedozer02.png
├── hooks
│   └──
└── README.rst

Setting up Sphinx

Following the instructions of the ReadTheDocs tutorial, we are going to create a docs folder at the template level.

$ cd cookiedozer/\{\{cookiecutter.repo_name\}\}/
$ mkdir docs


Sphinx comes with a very handy CLI tool to set up docs named sphinx-quickstart.

$ cd docs
$ sphinx-quickstart

We can feed the Cookiecutter variables to it. Feel free to change the values according to your needs.

> Root path for the documentation [.]: <ENTER>
> Separate source and build directories (y/n) [n]: y
> Name prefix for templates and static dir [_]: <ENTER>

> Project name: {{cookiecutter.app_title}}
> Author name(s): {{cookiecutter.full_name}}
> Project version: {{cookiecutter.version}}
> Project release [{{cookiecutter.version}}]: <ENTER>

> Source file suffix [.rst]: <ENTER>
> Name of your master document (without suffix) [index]: <ENTER>
> Do you want to use the epub builder (y/n) [n]: <ENTER>
> autodoc: automatically insert docstrings from modules (y/n) [n]: y
> doctest: automatically test code snippets in doctest blocks (y/n) [n]: n
> intersphinx: link between Sphinx documentation of different projects (y/n) [n]: y
> todo: write "todo" entries that can be shown or hidden on build (y/n) [n]: n
> coverage: checks for documentation coverage (y/n) [n]: n
> pngmath: include math, rendered as PNG images (y/n) [n]: n
> mathjax: include math, rendered in the browser by MathJax (y/n) [n]: n
> ifconfig: conditional inclusion of content based on config values (y/n) [n]: y
> viewcode: include links to the source code of documented Python objects (y/n) [n]: n
> Create Makefile? (y/n) [y]: y
> Create Windows command file? (y/n) [y]: n


Sphinx creates an index.rst file inside of the source folder which should look similiar to the following:

.. {{cookiecutter.app_title}} documentation master file, created by
   sphinx-quickstart on Thu Jan 29 23:09:48 2015.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

Welcome to {{cookiecutter.app_title}}'s documentation!


.. toctree::
   :maxdepth: 2

Indices and tables

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

Adding more pages to the docs is fairly straightforward. You need to create another rst file and insert it to the table of contents respectively.

readme and app docs

We can reuse README.rst from part 1 of this tutorial. We will also create a separate file for our application.

$ cd source
$ touch readme.rst
$ touch {{cookiecutter.repo_name}}.rst

Open readme.rst and insert the following code:

.. _readme:

.. include:: ../../README.rst

We instruct sphinx to render the contents of {{cookiecutter.repo_name}}.rst based on our Python source code:

{{cookiecutter.repo_name}} Package

:mod:`{{cookiecutter.repo_name}}` Module

.. automodule:: {{cookiecutter.repo_name}}.{{cookiecutter.repo_name}}

Next up, we add the new pages to index.rst and also instruct cooiecutter to render the short_description:

.. {{cookiecutter.app_title}} documentation master file, created by
   sphinx-quickstart on Thu Jan 29 23:09:48 2015.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

Welcome to {{cookiecutter.app_title}}'s documentation!



.. toctree::
   :maxdepth: 2


.. _apiref:

API Reference

.. toctree::
   :maxdepth: 2


Indices and tables

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

Package location

The autodoc extension needs to know where to find our package. It turns out already features an according example, so we have to insert the folder two levels about source to the sys path:

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.

sys.path.insert(0, os.path.abspath('../..'))

Change doc style

If you have read the previous parts of this tutorial, you might have noticed the slightly different doc string style syntax. I generally prefer Google Style doc strings over regular sphinx, as they are slightly more readable and usually require less boilerplate.

In this particular case we will use the standard syntax though, so they seamingly integrate with Kivy’s docs. At the end of the day, it’s totally up to you which style you would like to use for your project.

You will need to install the Napoleon extension to be able to use the Google style doc strings with Sphinx.


Buildozer is yet another great tool developed by the Kivy team. As I mentioned right in the beginning of Create your own Cookiecutter, Buildozer is still in alpha-development stage with limited OS support. However it is working just fine though on Ubuntu 14.04 (Trusty Tahr) 64-bit. If you are using Windows or MacOSX you may want to check out this guide on the Kivy Android Virtual Machine.


Back when I set it up Buildozer on Ubuntu Trusty Tahr I followed this guide. The official Buildozer Docs feature a similar chapter on the installation process for older Ubuntu versions, namely Precise Pangolin and Saucy Salamander.

Buildozer itself does not require anything aside from Python, which means you don’t need to install any of the 32bit libraries and not even Cython, in order to create a spec for your template.

$ pip install --upgrade buildozer

Create spec file

Assuming you have successfully installed Buildozer, you can now run the following command to create a spec file. It needs to be at the project root (next to

$ cd ../..
$ buildozer init

ℹ️ As a side note, if you are using GitHubs gitignore file for Python projects any *.spec files are excluded from version control. So I’ll quickly add the following line to Cookiedozers gitignore:

# Do not ignore buildozer.spec as it is required for our template

Next up I open buildozer.spec in a text editor and replace several values with Cookiecutter variables. You may want to have a brief look at the buildozer.spec of the game 2048 by Kivy core committer @tito as it is a great example of what you actually need to set to create a working Android apk.

For reasons of clarity and comprehensibility the following listings only contain the settings that are different from the defaults.

# (str) Title of your application
title = {{cookiecutter.app_title}}

# (str) Package name = {{cookiecutter.repo_name}}

# (str) Package domain (needed for android/ios packaging)
package.domain = {{cookiecutter.full_name|lower|replace(' ', '.')}}

# (str) Source code where the live
source.dir = {{cookiecutter.repo_name}}
# (str) Application versioning (method 1)
version.regex = __version__ = ['"](.*)['"]
version.filename = %(source.dir)s/

Once again I make use of Cookiecutters features to automatically transform the author’s name to all-lowercase separated by a dot which will be the package domain of our app. So Raphael Pierzina ultimately becomes raphael.pierzina.

Find out more about advanced usage of Cookiecutter features in the documentation.

Build an apk

We are now able to create a deployable distribution of a project, which has been generated from the template.

The first time you actually run the according Buildozer command it will download a bunch of tools including the Android SDK and NDK. In other words don’t worry if it takes quite a while as it’s just this one time for all your Buildozer projects. See Buildozer Quickstart.

Go ahead and give it a try! 😉

$ buildozer -v android debug

Deploy to your Android device

Once you have enabled USB Debugging on your device, you can deploy with the following command:

$ buildozer android deploy logcat


I personally find it very convenient to define aliases for commands, that I use frequently, in a Makefile:

Create a new file at the top level of the app:

$ touch Makefile

What you define in your Makefile depends on your personal preference really. As for my part, I constantly run the test suite and occasionally forget the correct command to generate a html coverage report.

So it makes sense for me to add them 🙂

.PHONY: docs

    @echo "test - run the test py.test suite"
    @echo "coverage - generate a coverage report and open it"
    @echo "docs - generate Sphinx HTML documentation and open it"
    @echo "apk - build an android apk with buildozer"
    @echo "deploy - deploy the app to your android device"

    python test

    python test -a '--cov={{cookiecutter.repo_name}} --cov-report=html'
    xdg-open htmlcov/index.html

    $(MAKE) -C docs html
    xdg-open docs/build/html/index.html

    buildozer -v android debug

    buildozer android deploy logcat

I’m using xgd-open to view the generated html files in Firefox, in case your wondering. Other than that I implemented a help command and put it right in the beginning of the file. Invoking make without any arguments runs the first target, namely help.

Yay! We made it. 👍

We created a fully-fledged Cookiecutter template for a Kivy app that features a pytest suite, sphinx docs and a Makefile. You can easily deploy the app to your favourite Android mobile device via Buildozer. Last but not least the application is an installable Python Package, with entry points set up, which you can even upload to PyPI.

You can find the latest version of the Cookiedozer template on GitHub!

Hope you liked this tutorial and it was useful to you. I would love to hear from you. Please send me feedback via twitter or email. Thank you! 👋

Back to posts