Quickstart tutorial¶
Let’s discover piecutter with simple stories!
Hello world!¶
Let’s produce the traditional Hello world!
with minimal code:
>>> render = piecutter.Cutter()
>>> template = u'Hello {who}!'
>>> data = {u'who': u'world'}
>>> output = render(template, data)
>>> print(output.read())
Hello world!
Notes about this example:
- text datatype is recognized as a template
- the template engine is Python’s format() [1] by default
- data is a mapping
- output is a file-like object
piecutter.Cutter
encapsulates full rendering pipeline.
Setup a template engine¶
piecutter uses Engines to render the templates against data.
piecutter has builtin support for the following template engines: Python’s format() [1], Jinja2 [2] and Django [3]. Additional engines could be supported, including non-Python ones!
Learn more about template engines at Engines.
Load templates from various locations¶
piecutter uses Loaders to fetch templates from various locations and to distinguish files from directories.
See loaders for details.
File-like objects¶
If you pass a file-like object to piecutter‘s default loader, it will automatically use it as a template.
As an example, let’s render an in-memory file:
>>> from StringIO import StringIO
>>> render = piecutter.Cutter()
>>> template = StringIO(u'Hello {who}!')
>>> output = render(template, data)
>>> print(output.read())
Hello world!
Of course, we can render an opened file object:
>>> render = piecutter.Cutter()
>>> with open('demo/simple/hello.txt') as template:
... output = render(template, data)
... print(output.read())
Hello world!
Templates on local filesystem¶
Use file://
(or file:///
for absolute paths) to tell piecutter‘s
default loader to read templates on local filesystem:
>>> template = u'file://demo/simple/hello.txt'
>>> output = render(template, data)
>>> print(output.read())
Hello world!
Templates over HTTP¶
Use http://
or https://
to tell piecutter‘s default loader to fetch
templates from remote HTTP server:
>>> template = u'https://raw.github.com/diecutter/piecutter/cutter-api-reloaded/demo/simple/hello.txt'
>>> output = render(template, data)
>>> print(output.read())
Hello world!
Additional loaders¶
Feel free to write custom loaders in order to support additional locations!
Basically, if you can determine template type (file or directory), fetch file contents and list directory items, you can implement a loader.
Render directories¶
Collections of templates, a.ka. directories, are also supported. By default, they are rendered as generator of rendered items.
Given the following directory:
demo/simple/
├── hello.txt # Contains "Hello {who}!\n"
└── {who}.txt # Contains "Whatever the content.\n"
When we render the directory, we can iterate generated items and use their attributes and methods:
>>> for item in render(u'file://demo/simple', data):
... print('Name: {}'.format(item.name))
... print('Content: {}'.format(item.read()))
Name: hello.txt
Content: Hello world!
Name: world.txt
Content: Whatever the content.
Write generated files to disk¶
piecutter uses writers to post-process generated content.
As an example, piecutter.FileWriter
writes generated files to disk.
Let’s setup some output directory and check it does not exist yet.
>>> import os
>>> output_directory = os.path.join(temp_dir, 'directory')
>>> os.path.exists(output_directory)
False
Now generate files in output directory:
>>> render = piecutter.Cutter(
... writer=piecutter.FileWriter(target=output_directory),
... )
>>> written_files = render('file://demo/simple/', data)
... and inspect the results:
>>> sorted(os.listdir(output_directory))
['simple']
>>> sorted(os.listdir(os.path.join(output_directory, 'simple')))
['hello.txt', 'world.txt']
>>> print(open(os.path.join(output_directory, 'simple', 'hello.txt'), 'rb').read())
Hello world!
>>> written_files # Contains absolute path to generated files.
['/.../directory/simple/hello.txt', '/.../directory/simple/world.txt']
Learn more at Writers.
Notes & references
[1] | (1, 2) https://docs.python.org/2.7/library/string.html#formatstrings |
[2] | (1, 2) http://jinja.pocoo.org/ |
[3] | (1, 2) https://docs.djangoproject.com/en/1.8/topics/templates/ |