Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Cookiecutter - PyData Berlin 2017

Cookiecutter - PyData Berlin 2017

Cookiecutter is a command-line utility that generates projects from templates. You can use Cookiecutter to create new Python projects and to generate the initial code for different types of applications.

In this talk, I will give an introduction to Cookiecutter, how to install it
from PyPI, how to use the CLI and finally how to author your own template.

https://pydata.org/berlin2017/schedule/presentation/49/

Raphael Pierzina

July 01, 2017
Tweet

More Decks by Raphael Pierzina

Other Decks in Programming

Transcript

  1. Kickstarting projects
    with Cookiecutter
    PyData Berlin - July 1, 2017
    Raphael Pierzina

    View Slide

  2. Thanks to the organizers
    for a great event!

    View Slide

  3. $ whoami

    View Slide

  4. Hi there! I’m
    Raphael

    View Slide

  5. • Maintainer and core developer of Cookiecutter
    • Contributor to pytest and community person
    • Creator of the cookiecutter-pytest-plugin template
    • Software Engineer at moovel Group

    View Slide

  6. @hackebrot

    View Slide

  7. Agenda
    1. What is Cookiecutter?
    2. How does Cookiecutter work?
    3. Create your own Cookiecutter template
    4. Popular Cookiecutter templates
    5. Demo: A custom Jupyter widget

    View Slide

  8. 1. What is
    Cookiecutter?

    View Slide

  9. @hackebrot

    View Slide

  10. @hackebrot

    View Slide

  11. $ cookiecutter
    gh:pytest-dev/cookiecutter-pytest-plugin

    View Slide

  12. full_name [Raphael Pierzina]:
    email [[email protected]]:
    github_username [hackebrot]:
    plugin_name [foobar]: emoji
    module_name [emoji]:
    short_description [A simple plugin to use with Pytest]: emoji plugin
    version [0.1.0]:
    pytest_version [3.1.1]: 3.1.2
    Select docs_tool:
    1 - mkdocs
    2 - sphinx
    3 - none
    Choose from 1, 2, 3 [1]: 1
    Select license:
    1 - MIT
    2 - BSD-3
    3 - GNU GPL v3.0
    4 - Apache Software License 2.0
    5 - Mozilla Public License 2.0
    Choose from 1, 2, 3, 4, 5 [1]: 2
    INFO:post_gen_project:Moving files for mkdocs.
    INFO:post_gen_project:Removing all temporary license files
    INFO:post_gen_project:Removing jinja2 macros
    py
    @hackebrot

    View Slide

  13. pytest-emoji/
    ├── LICENSE
    ├── MANIFEST.in
    ├── README.rst
    ├── appveyor.yml
    ├── docs
    │ └── index.md
    ├── mkdocs.yml
    ├── pytest_emoji.py
    ├── setup.py
    ├── tests
    │ ├── conftest.py
    │ └── test_emoji.py
    └── tox.ini
    py
    @hackebrot

    View Slide

  14. Project
    • GitHub: https://github.com/audreyr/cookiecutter
    • Documentation: https://cookiecutter.readthedocs.io
    • PyPI: https://pypi.python.org/pypi/cookiecutter
    @hackebrot

    View Slide

  15. Features
    • Cross-platform: Windows, Mac, and Linux are
    officially supported
    • Works with CPython 2.7, 3.3, 3.4, 3.5, 3.6 and PyPy
    • Project templates can be in any programming
    language or markup format
    @hackebrot

    View Slide

  16. $ pip install cookiecutter

    View Slide

  17. $ brew install cookiecutter

    View Slide

  18. $ sudo apt-get install
    cookiecutter

    View Slide

  19. $ conda install
    -c conda-forge cookiecutter

    View Slide

  20. Community
    • Free and open source software: BSD license
    • 154 individual contributors from around the world
    • More than 1000 public templates on GitHub
    @hackebrot

    View Slide

  21. Contributing
    • Development of Cookiecutter is community-driven
    • Connect with other Cookiecutter contributors and
    users on https://gitter.im/audreyr/cookiecutter
    • Everyone is invited to contribute!
    @hackebrot

    View Slide

  22. 2. How does
    Cookiecutter work?

    View Slide

  23. CLI + Python API
    • Cookiecutter can be either used as a command-
    line interface app or as a Python library
    • Both interfaces support a number of options for
    controlling the level of verbosity, suppressing user
    prompting, providing extra context and many other
    things
    @hackebrot

    View Slide

  24. $ cookiecutter [OPTIONS]
    TEMPLATE
    [EXTRA_CONTEXT] ...

    View Slide

  25. $ cookiecutter -v --no-input
    cookiecutter-pytest-plugin
    license=BSD-3 docs_tool=sphinx

    View Slide

  26. # -*- coding: utf-8 -*-
    from cookiecutter.main import cookiecutter
    def run_cookiecutter():
    template = 'gh:pytest-dev/cookiecutter-pytest-plugin'
    project_dir = cookiecutter(template)
    print(f"Project generated in {project_dir}!")
    if __name__ == '__main__':
    run_cookiecutter()
    py
    @hackebrot

    View Slide

  27. Templating with Jinja2
    • Jinja2 is a modern and designer-friendly templating
    language for Python, modelled after Django’s
    templates.
    • It is fast, widely used and secure with the optional
    sandboxed template execution environment
    @hackebrot

    View Slide

  28. # -*- coding: utf-8 -*-
    import pytest
    def pytest_addoption(parser):
    group = parser.getgroup('{{cookiecutter.plugin_name}}')
    group.addoption(
    ' --foo',
    action='store',
    dest='dest_foo',
    default='{% now "utc", "%Y" %}',
    help='Set the value for the fixture "bar".'
    )
    parser.addini('HELLO', 'Dummy pytest.ini setting')
    py
    @hackebrot

    View Slide

  29. {
    "full_name": "Raphael Pierzina",
    "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": "3.1.1",
    "docs_tool": ["mkdocs", "sphinx", "none"],
    "license": [
    "MIT",
    "BSD-3",
    "GNU GPL v3.0",
    "Apache Software License 2.0",
    "Mozilla Public License 2.0"
    ]
    }
    json
    @hackebrot

    View Slide

  30. git + mercurial (+ zip)
    • Cookiecutter works with local templates on your
    filesystem or remote Git or Mercurial repositories
    • Short-hands for GitHub, BitBucket, and GitLab
    • Open Pull Request for adding support for
    templates from zip files or zip URLs (#961)
    @hackebrot

    View Slide

  31. 3. Create your own
    Cookiecutter template

    View Slide

  32. Template project
    • Cookiecutter takes a source directory tree and
    copies it into your new project
    • It replaces all the names that it finds surrounded by
    templating tags {{ and }} with names that it finds
    in the cookiecutter.json file
    @hackebrot

    View Slide

  33. $ mkdir hello-pydata
    $ cd hello-pydata
    $ mkdir {{cookiecutter.project_slug}}
    $ cd {{cookiecutter.project_slug}}
    @hackebrot

    View Slide

  34. Cookiecutter namespace
    • Anything inside templating tags can be placed
    inside a namespace.
    • cookiecutter.project_slug will be looked up
    as project_slug in cookiecutter.json
    @hackebrot

    View Slide

  35. $ touch {{cookiecutter.script_name}}.py
    @hackebrot

    View Slide

  36. # -*- coding: utf-8 -*-
    def hello_pydata():
    print('Hello PyData {{cookiecutter.location}}!')
    if __name__ == '__main__':
    hello_pydata()
    py
    @hackebrot

    View Slide

  37. Context
    • Cookiecutter needs a context file to look up all your
    templates items
    • This file goes into our hello-pydata directory,
    and contains all the names we’ve used
    @hackebrot

    View Slide

  38. $ cd ..
    $ touch cookiecutter.json
    @hackebrot

    View Slide

  39. {
    "project_slug": "project",
    "location": "World",
    "script_name": "hello_{{cookiecutter.location|lower}}"
    }
    json
    @hackebrot

    View Slide

  40. hello-pydata/
    ├── cookiecutter.json
    └── {{cookiecutter.project_slug}}
    └── {{cookiecutter.script_name}}.py
    py
    @hackebrot

    View Slide

  41. $ cookiecutter ~/hackebrot/hello-pydata/

    View Slide

  42. project_slug [project]: hello-project
    location [World]: Berlin
    script_name [hello_berlin]:
    py
    @hackebrot

    View Slide

  43. hello-project/
    !"" hello_berlin.py
    py
    @hackebrot

    View Slide

  44. $ cd hello-project/
    $ python hello_berlin.py
    Hello PyData Berlin!

    View Slide

  45. View Slide

  46. Jinja2 syntax
    • {% … %} for statements
    • {{ … }} for expressions to print the template
    output
    • {# … #} for comments not included in the
    template output
    @hackebrot

    View Slide

  47. Jinja2 control structures
    • For: Loop over each item in a sequence
    • If: Test if a variable is defined or if it’s equal to
    some other value
    • Macros: Useful to put often used idioms into
    reusable functions
    @hackebrot

    View Slide

  48. {%- from "macros/rst" import doc_title, doc_subtitle -%}
    {{ doc_title('pytest-' + cookiecutter.plugin_name) }}
    rst
    @hackebrot

    View Slide

  49. Jinja2 control structures
    • Assignments: Assign values to variables
    • Include: Return a rendered template into the
    current namespace
    • …
    @hackebrot

    View Slide

  50. {%- if cookiecutter.license == "MIT" -%}
    {%- include 'licenses/MIT' %}
    {%- elif cookiecutter.license == "BSD-3" -%}
    {%- include 'licenses/BSD-3' %}
    {%- elif cookiecutter.license == "GNU GPL v3.0" -%}
    {%- include 'licenses/GPL-3' %}
    {%- elif cookiecutter.license == "Apache Software License 2.0" -%}
    {%- include 'licenses/Apache-2' %}
    {%- elif cookiecutter.license == "Mozilla Public License 2.0" -%}
    {%- include 'licenses/MPL-2' %}
    {%- endif -%}
    txt
    @hackebrot

    View Slide

  51. Jinja2 filters
    • replace: Return a copy of the value with all
    occurrences of a substring replaced
    • lower: Convert a value to lowercase
    • upper: Convert a value to uppercase
    @hackebrot

    View Slide

  52. {
    "full_name": "Raphael Pierzina",
    "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": "3.1.1",
    "docs_tool": ["mkdocs", "sphinx", "none"],
    "license": [
    "MIT",
    "BSD-3",
    "GNU GPL v3.0",
    "Apache Software License 2.0",
    "Mozilla Public License 2.0"
    ]
    }
    json
    @hackebrot

    View Slide

  53. Jinja2 filters
    • tojson: Dump a structure to a JSON string
    • sort: Sort an iterable in ascending order by
    default, or descending with an extra arg. Also
    allows to sort by an attribute
    @hackebrot

    View Slide

  54. Jinja2 filters
    • select: Filter a sequence of objects by applying a
    test to each object
    • groupby: Group a sequence of objects by a
    common attribute
    @hackebrot

    View Slide

  55. Jinja2 extensions
    • jinja2-time: Builtin into cookiecutter to insert a
    string representation of a datetime object
    • …
    • …
    @hackebrot

    View Slide

  56. {#- source: http: //opensource.org/licenses/MIT #}
    The MIT License (MIT)
    Copyright (c) {% now 'utc', '%Y' %} {{cookiecutter.full_name}}
    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:
    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
    txt
    @hackebrot

    View Slide

  57. 4. Popular
    Cookiecutter templates

    View Slide

  58. https://github.com/audreyr/
    cookiecutter-pypackage
    @hackebrot

    View Slide

  59. cookiecutter-pypackage
    • Project structure for Python packages
    • Testing with unittest or pytest
    • Tox for testing compatibility across Python versions
    • Sphinx for documentation
    @hackebrot

    View Slide

  60. https://github.com/pydanny/
    cookiecutter-django
    @hackebrot

    View Slide

  61. cookiecutter-django
    • Template for Django 1.10 and Python 3.4 or 3.5
    • Optimized development and production settings
    • tests with unittest or pytest and 100% test coverage
    • Docker support using docker-compose
    • Bootstrap, 12-Factor, SSL, many other features
    @hackebrot

    View Slide

  62. https://github.com/pytest-dev/
    cookiecutter-pytest-plugin
    @hackebrot

    View Slide

  63. cookiecutter-pytest-plugin
    • Installable PyPI package with comprehensive README.rst file
    • Tests for your plugin with tox, pytest, and CI config
    • Example code for a fixture, a CLI option, and a pytest.ini option
    • Optional documentation with either Sphinx or MkDocs
    • Choose from several FOSS licenses
    @hackebrot

    View Slide

  64. https://github.com/pybee/
    Python-iOS-template
    @hackebrot

    View Slide

  65. Python-iOS-template
    • Generates Python apps that will run under iOS
    • Supports Python 2.7, 3.4, and 3.5
    • Works well with the toga GUI toolkit for native iOS
    widgets
    @hackebrot

    View Slide

  66. 5. Demo: A custom
    Jupyter widget

    View Slide

  67. https://github.com/jupyter-
    widgets/widget-cookiecutter
    @hackebrot

    View Slide

  68. View Slide

  69. If you or your company are using
    Cookiecutter, please support its
    development!
    patreon.com/hackebrot
    @hackebrot

    View Slide

  70. @hackebrot

    View Slide