github gitlab twitter
Create your own Cookiecutter template
Jan 7, 2015
7 minutes read

Are you doing the same steps over and over again every time you start a new programming project? More particularly when creating an application that a features a test suite along with auto-generated documentation? A package that you later want to publish on PyPI?

If so, you should definitely check out Cookiecutter! 😉

Cookiecutter is a cross-platform command-line utility that creates projects from project templates. E.g. Python package projects, jQuery plugin projects. It prompts users for input and uses the given information to render templates.

There are numerous cookiecutter templates available online including a fully-fledged PyPackage template by the original creator of Cookiecutter @audreyr herself.

The goal of this series of blog posts is to give an example for creating your very own template. The resulting project will be a fully functional Kivy app, ready to be deployed to your android mobile device.

I am using Python 2.7 on Ubuntu 14.04 (Trusty Tahr) 64-bit but it should work with slight adaptations on your OS of choice. Please note that albeit Kivy being cross-platform the tool at hand for creating the apk named Buildozer is not, from what I know. It is in early development stage and only supports Linux at the time of this writing. For debugging purposes feel free to check out the Kivy Launcher on the Google play store.


Install Cookiecutter

Given that you have pip installed you can run the following:

$ pip install --user cookiecutter

Please see the official cookiecutter docs for more information on how to set up Cookiecutter.


Create a new cookiecutter template project

GitHub repository

Cookiecutter is capable of deadling with remote templates, which is why I tend to create a new GitHub repository and initialize it with a LICENSE and .gitignore file.

See cookiedozer 😄

Local directory

If you prefer to create a local directory instead, that’s fine too. Cookiecutter does not require templates to be git repositories.

$ mkdir cookiedozer

Project structure

After successfully cloning the template repository, you should find the following folder structure:

$ cd cookiedozer
$ tree -a -L 1
.
├── .git
├── .gitignore
├── LICENSE
└── README.md

If you prefer reStructuredText over markdown for your README file, you can rename the file created by GitHub for you and convert the syntax if need be. Then git commit your changes.

$ git mv README.md README.rst
$ git commit -m "Convert README.md to rst format"

Please note that I will leave out git commands for the rest of this post for the sake of brevity. However I would like to encourage you to commit sets of changes as you go.


Template structure

Cookiecutter uses jinja2 under the hood to render templates. The syntax will probably look familiar if you have worked on Flask or Django projects before.

The idea is to generate text from so called context variables:

{{cookiecutter.repo_name}}

Create Python package

You need to create two nested folders. One will be the project root and the other one is the Python package root containing the application code.

$ mkdir -p {{cookiecutter.repo_name}}/{{cookiecutter.repo_name}}

Next we want to create the compulsory __init__.py to have a package as well as a module for our application:

$ cd \{\{cookiecutter.repo_name\}\}/\{\{cookiecutter.repo_name\}\}/
$ touch __init__.py
$ touch {{cookiecutter.repo_name}}.py

It is recommended to set the encoding to utf-8 for both of the files and insert meta data into __init__.py:

# -*- coding: utf-8 -*-

__author__ = '{{cookiecutter.full_name}}'
__email__ = '{{cookiecutter.email}}'
__version__ = '{{cookiecutter.version}}'

Context file

We need to register variables that we want to use in a JSON file with name cookiecutter.json at the top level of your template. In its most basic form it contains a number of key-value pairs, that refer to variable names and default values for these variables.

$ touch cookiecutter.json
{
    "full_name": "Raphael Pierzina",
    "email": "[email protected]",
    "repo_name": "helloworld",
    "version": "0.1.0"
}

Kivy app

Kivy is an open source Python framework for rapid development of cross-platform applications with natural user interfaces (NUI). Kivy runs on Linux, Windows, OS X, Android and iOS.

A basic kivy app

Let’s edit the previously created Python file {{cookiecutter.repo_name}}.py and start off with a basic setup.

We need to have an additional cookiecutter variable for our app as PEP8 recommends a CamelCase class name while the repository and package is supposed to have an all lowercase name.

Please note the variable kivy_version which is mandatory for a kivy app. Your kivy installation must be of this version or higher, so that features your app build on top of are available and the app is working as expected. For any additional information concerning this please visit the official Kivy API docs.

Entrypoint

It is common practice for Kivy apps to have a main.py module to launch the application:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from {{cookiecutter.repo_name}} import {{cookiecutter.app_class_name}}


def main():
    {{cookiecutter.app_class_name}}().run()


if __name__ == '__main__':
    main()

GUI code

Kivy has its own DSL for defining GUIs named kvlang, which lets you define user interface components in a declarative way. We use a separate file to

Create a new file:

$ touch {{cookiecutter.app_class_name}}.kv

Paste the following into the file:

#:kivy {{cookiecutter.kivy_version}}

Button:
    text: '{{cookiecutter.app_title}}'

Learn more about the syntax of a kvlang file here.

There a several ways in which a Kivy app can load kvlang files:

  • By explicitly calling the Builder and passing the desired kv file to it
  • By using the application name in lower-case without App at the end for your kv file

We will use the latter for now to demonstrate cookiecutter hooks.


Cookiecutter hooks

You can have Python or Shell scripts that run before and/or after your project is generated. Create a hooks folder at the top level of your template project and create a new Python file.

$ cd ../..
$ mkdir hooks
$ touch hooks/post_gen_project.py

The following code renames the kv file after the project has been generated to follow the convention mentioned above, so HelloWorldApp.kv becomes helloworld.kv. Although the kivy source code itself accepts a kv file ending with either App or app, I encourage you to stick to the docs. Hence our post generation script closely resembles the original implementation of App.load_kv() at kivy/app.py.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Rename the generated kv file to be compatible with the
original kivy kv file detection of `App.load_kv()`.
"""

import os


package_dir = '{{cookiecutter.repo_name}}'
old_kv_file = os.path.join(package_dir, '{{cookiecutter.app_class_name}}.kv')

lower_app_class_name = '{{cookiecutter.app_class_name}}'.lower()

if (lower_app_class_name.endswith('app')):
    lower_app_class_name = lower_app_class_name[:-3]

new_kv_file = os.path.join(package_dir, '{}.kv'.format(lower_app_class_name))

os.rename(old_kv_file, new_kv_file)

LICENSE file

If you want others to be able to use your source code, you should add a LICENSE file. I chose the MIT License for this template and I want to use the same file for the project that cookiecutter will render.

Copy the license file to the root of the project.

$ cp LICENSE \{\{cookiecutter.repo_name\}\}/

After that we need to replace the current values by cookiecutter variables, so the beginning of the licence file should read as follows:

The MIT License (MIT)

Copyright (c) {{cookiecutter.year}} {{cookiecutter.full_name}}

README file

Create a new file:

$ touch \{\{cookiecutter.repo_name\}\}/README.rst
{{cookiecutter.app_title}}
==========================

{{cookiecutter.short_description}}

----

This `Kivy`_ app was generated with `Cookiecutter`_ along with `@hackebrot`_'s
`Cookiedozer`_ template.

.. _`Kivy`: https://github.com/kivy/kivy
.. _`Cookiecutter`: https://github.com/audreyr/cookiecutter
.. _`@hackebrot`: https://github.com/hackebrot
.. _`Cookiedozer`: https://github.com/hackebrot/cookiedozer

Update context file

Since we introduced a couple of new variables, we need to update cookiecutter.json. Default values for variables can be templated, so that when a user is prompted for input default values for other variables update automatically.

Feel free to try it yourself, see Templates in Context Values.

{
    "full_name": "Raphael Pierzina",
    "email": "[email protected]",
    "repo_name": "helloworld",
    "app_class_name": "HelloWorldApp",
    "app_title": "Hello World!",
    "short_description": "Simple app that features a gray button!",
    "version": "0.1.0",
    "kivy_version": "1.8.0",
    "year": "2015"
}

Run Cookiecutter

That’s it, we can execute Cookiecutter now and pass our template to it. 😄

$ cookiecutter cookiedozer

Launch the app

Now run the app with python from the package dir level.

$ cd helloworld/helloworld
$ python main.py

This should get you started with Kivy and Cookiecutter. In the next part of this tutorial we will be setting up tests, documentation as well as Builozer which we can use to deploy the app to an Android mobile device.

You can also always check out the latest version of the Cookiecutter template that we are creating on GitHub at https://github.com/hackebrot/cookiedozer.

It produces a visually appealing app, that features a sleek slide show displaying the passed values instead of a simple button. It has support for internationalization, links to be opened in your webbrowser as well as swipe gestures. Feel free to give it a try and let me know what you think! 😄

cookiedozer screenshot 1 cookiedozer screenshot 2


Back to posts