Slide 1

Slide 1 text

Cookiecutter or what we can learn from templates

Slide 2

Slide 2 text

Raphael Pierzina Python Glasgow - February, 2016

Slide 3

Slide 3 text

Who am I? • Night owl, comic lover, overall geek • Software Engineer at FanDuel • Stuttgart ✈ Edinburgh

Slide 4

Slide 4 text

/ hackebrot @hackebrot

Slide 5

Slide 5 text

Open Source Projects • Cookiecutter • Pytest and plugins • Kivy Blueprints • … a couple of smaller projects

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

What is Cookiecutter? • Command-line utility that helps you to start new projects following best practices of the community or simply based on your very own experience. • Renders templates based on user-input on the CLI • Project templates can be in any programming language or markup format

Slide 8

Slide 8 text

What is Cookiecutter? • 100% Python - using click and jinja2 • Compatible with CPython 2.7, 3.3, 3.4, 3.5 and also PyPy • Available on OS X, Linux and Windows • Free software, permissive BSD license

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

Community • The core committer team is @audreyr, @pydanny, @michaeljoseph, @pfmoore, and @hackebrot • Close to 3k stars on GitHub, around 12k downloads per month on PyPI with 600 templates on GitHub • Talks at multiple conferences (PyCon ZA, EuroPython, …) • Open Source sponsor for PyCon US 2016

Slide 11

Slide 11 text

Why Templates? • A great addition to user documentation that you can explore • Even in Python we sometimes do the same stuff over and over again • Writing scripts is really easy, polishing a package to upload it to PyPI can be tricky • Some packages require (or recommend) a certain project structure and naming convention

Slide 12

Slide 12 text

Templates • Local templates (that you’ve downloaded or created) • Mercurial/Git repositories on BitBucket and GitHub

Slide 13

Slide 13 text

Templates 54 “official” Templates Python 36 Python C C++ C# Common Lisp JS LaTeX/XeTeX Berkshelf-Vagrant HTML Scala 6502 Assembly Kotlin

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

Installation $ pip install cookiecutter # Recommended! $ brew install cookiecutter # OS X $ apt-get install cookiecutter # Ubuntu ...

Slide 16

Slide 16 text

CLI or API • Python API to run cookiecutter from your own tools • Command-line interface using click # http://click.pocoo.org/5/python3/ export LC_ALL=en_US.UTF-8 export LANG=en_US.UTF-8

Slide 17

Slide 17 text

CLI Options Usage: cookiecutter [OPTIONS] TEMPLATE Create a project from a Cookiecutter project template (TEMPLATE). Options: -V, --version Show the version and exit. --no-input Do not prompt for parameters and only use cookiecutter.json file content -c, --checkout TEXT branch, tag or commit to checkout after git clone -v, --verbose Print debug information --replay Do not prompt for parameters and only use information entered previously -f, --overwrite-if-exists Overwrite the contents of the output directory if it already exists -o, --output-dir PATH Where to output the generated project dir into --config-file PATH User configuration file --default-config Do not load a config file. Use the defaults instead -h, --help Show this message and exit.

Slide 18

Slide 18 text

Usage $ cookiecutter gh:pytest-dev/cookiecutter-pytest-plugin

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

Demo Using Cookiecutter

Slide 21

Slide 21 text

cookiecutter.json { "full_name": "Raphael Pierzina", "email": "[email protected]", "github_username": "hackebrot", "plugin_name": "foobar", "module_name": "{{ cookiecutter.plugin_name|lower|replace('-', '_') }}", "short_description": "A simple plugin to use with Pytest", "version": "0.1.0", "pytest_version": "2.8.1", "year": "2015", "docs_tool": ["mkdocs", "sphinx", "none"], "license": ["MIT", "BSD-3", "GNU GPL v3.0", "Apache Software License 2.0"] }

Slide 22

Slide 22 text

Template Structure cookiecutter-pytest-plugin/ !"" LICENSE !"" Makefile !"" README.md !"" cookiecutter.json !"" docs # !"" contributor-guide # # !"" documentation.md # # $"" quickstart.md # !"" index.md # $"" user-guide # !"" publish-plugin.md # $"" quickstart.md !"" hooks # !"" post_gen_project.py # $"" pre_gen_project.py !"" mkdocs.yml

Slide 23

Slide 23 text

Template Structure !"" pytest-{{cookiecutter.plugin_name}} # !"" LICENSE # !"" README.rst # !"" appveyor.yml # !"" mkdocs # # !"" index.md # # $"" mkdocs.yml # !"" pytest_{{cookiecutter.module_name}}.py # !"" setup.py

Slide 24

Slide 24 text

Template Structure # !"" sphinxdocs # # !"" Makefile # # !"" _build # # !"" _static # # !"" _templates # # !"" conf.py # # !"" index.rst # # $"" make.bat # !"" tests # # !"" conftest.py # # $"" test_{{cookiecutter.module_name}}.py # $"" tox.ini

Slide 25

Slide 25 text

Template Structure !"" tests # !"" conftest.py # $"" test_create_template.py $"" tox.ini 12 directories, 29 files

Slide 26

Slide 26 text

Templated File name='pytest-{{cookiecutter.plugin_name}}', version='{{cookiecutter.version}}', author='{{cookiecutter.full_name}}', author_email='{{cookiecutter.email}}', maintainer='{{cookiecutter.full_name}}', maintainer_email='{{cookiecutter.email}}', license='{{cookiecutter.license}}',

Slide 27

Slide 27 text

Templated File {% if cookiecutter.license == "MIT" -%} 'License :: OSI Approved :: MIT License', {%- elif cookiecutter.license == "BSD-3" -%} 'License :: OSI Approved :: BSD License', {%- elif cookiecutter.license == "GNU GPL v3.0" -%} 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', {%- elif cookiecutter.license == "Apache Software License 2.0" -%} 'License :: OSI Approved :: Apache Software License', {%- endif %}

Slide 28

Slide 28 text

Sphinx Quickstart > Root path for the documentation [.]: > Separate source and build directories (y/n) [n]: y > Name prefix for templates and static dir [_]: > Project name: pytest-{{cookiecutter.plugin_name}} > Author name(s): {{cookiecutter.full_name}} > Project version: {{cookiecutter.version}} > Project release [{{cookiecutter.version}}]: > Source file suffix [.rst]:

Slide 29

Slide 29 text

Jinja2 Template {% for item in commands.split(',') -%} {% set command = item.strip().lower() %} @cli.command('{{command}}', help="Meaningful message here") def {{command}}_cmd(*args, **kwargs): pass {% endfor %}

Slide 30

Slide 30 text

Jinja2 Output @cli.command('foo', help="Meaningful message here") def foo_cmd(*args, **kwargs): pass @cli.command('bar', help="Meaningful message here") def bar_cmd(*args, **kwargs): pass @cli.command('helloworld', help="Meaningful message here") def helloworld_cmd(*args, **kwargs): pass

Slide 31

Slide 31 text

Demo Creating a “HelloWorld” Template

Slide 32

Slide 32 text

~/.cookiecutterrc default_context: full_name: "Raphael Pierzina" email: "[email protected]" github_username: "hackebrot" abbreviations: cookiedozer: https://github.com/hackebrot/cookiedozer.git gh: https://github.com/{0}.git

Slide 33

Slide 33 text

Showcase User Config $ cookiecutter gh:audreyr/cookiecutter-pypackage Cloning into 'cookiecutter-pypackage'... remote: Counting objects: 505, done. remote: Total 505 (delta 0), reused 0 (delta 0), pack-reused 505 Receiving objects: 100% (505/505), 77.43 KiB | 0 bytes/s, done. Resolving deltas: 100% (265/265), done. Checking connectivity... done. full_name [Raphael Pierzina]: email [[email protected]]: github_username [hackebrot]: project_name [Python Boilerplate]: Test User Config repo_name [boilerplate]: project_short_description [Python Boilerplate contains all the boilerplate you need to create a Python package.]: release_date [2015-01-11]: year [2015]: version [0.1.0]:

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

psst…cibopath

Slide 36

Slide 36 text

cibopath $ cibopath search django cookiecutter-django................. https://github.com/pydanny/cookiecutter-django cookiecutter-django-cms............. https://github.com/palazzem/cookiecutter-django-cms cookiecutter-django-crud............ https://github.com/wildfish/cookiecutter-django-crud cookiecutter-django-lborgav......... https://github.com/lborgav/cookiecutter-django cookiecutter-django-paas............ https://github.com/pbacterio/cookiecutter-django-paas cookiecutter-django-rest............ https://github.com/agconti/cookiecutter-django-rest cookiecutter-django-rest-framework.. https://github.com/jpadilla/cookiecutter-django-rest-framework cookiecutter-djangopackage.......... https://github.com/pydanny/cookiecutter-djangopackage cookiecutter-simple-django.......... https://github.com/marcofucci/cookiecutter-simple-django cookiecutter-wagtail................ https://github.com/torchbox/cookiecutter-wagtail wagtail-cookiecutter-foundation..... https://github.com/chrisdev/wagtail-cookiecutter-foundation

Slide 37

Slide 37 text

Questions?

Slide 38

Slide 38 text

pytest sprint 2016 https://www.indiegogo.com/projects/ python-testing-sprint-mid-2016#/

Slide 39

Slide 39 text

https://speakerdeck.com/hackebrot

Slide 40

Slide 40 text

/ hackebrot @hackebrot