本文中的Hook就是钩子,钩子就是Hookhtml
你能够在项目生成以前和/或以后运行Python或Shell脚本。python
像这样把它们放进Hook里:git
cookiecutter-something/ ├── {{cookiecutter.project_slug}}/ ├── hooks │ ├── pre_gen_project.py │ └── post_gen_project.py └── cookiecutter.json
Shell脚本工做方式相似:github
cookiecutter-something/ ├── {{cookiecutter.project_slug}}/ ├── hooks │ ├── pre_gen_project.sh │ └── post_gen_project.sh └── cookiecutter.json
将Cookiecutter扩展到使用其余类型的脚本应该不会太难。你能够根据你系统中存在的脚本系统尝试一下。web
为了可移植性,你应该为Hook使用Python脚本(扩展名为.py),由于这些脚本能够在任何平台上运行。可是,若是您但愿模板仅在单个平台上运行,则shell脚本(或Windows上的.bat文件)原则上都是可行的。shell
这里有一些关于如何编写生成前/生成后钩子脚本的细节。npm
以适当的状态退出django
确保钩子脚本以一种健壮的方式工做。若是钩子脚本运行失败(也就是说它以非零退出状态结束),项目生成将中止,生成的目录将被清除。编程
当前工做目录json
运行钩子脚本时,它们的工做目录是生成的项目的根目录。这使得后生成挂钩可使用相对路径轻松查找生成的文件。
** 模板变量在脚本中呈现**
就像你的项目模板同样,Cookiecutter也在你的脚本中呈现Jinja模板语法。这使您能够将Jinja模板变量合并到脚本中。例如,这行Python将module_name
设置为cookiecutter.module_name
模板变量的值:
module_name = '{{ cookiecutter.module_name }}'
下面是一个脚本示例,它在生成项目以前验证模板变量,将其保存到hooks/pre_gen_project.py:
中:
import re import sys MODULE_REGEX = r'^[_a-zA-Z][_a-zA-Z0-9]+$' module_name = '{{ cookiecutter.module_name }}' if not re.match(MODULE_REGEX, module_name): print('ERROR: %s 不是有效的Python模块名称!' % module_name) # 以状态1退出,表示失败 sys.exit(1)
若是你常用Cookiecutter,你会发现有一个用户配置文件颇有用。默认状况下,Cookiecutter尝试从主目录中的.cookiecutterrc文件中检索设置。从1.3.0版本开始,您还能够经过--config-file
在命令行上指定配置文件。
$ cookiecutter --config-file /home/tacey/my-custom-config.yaml cookiecutter-pypackage
或者你能够设置COOKIECUTTER_CONFIG
环境变量:
export COOKIECUTTER_CONFIG=/home/tacey/my-custom-config.yaml
若是您但愿坚持使用内置配置而不加载任何用户配置文件,请使用cli选项--default-config
。阻止Cookiecutter加载用户设置对于在隔离环境中编写集成测试相当重要。
用户配置示例:
default_context: full_name: "Tacey Wong" email: "xinyong.wang@qq.com" github_username: "taceywong" cookiecutters_dir: "/home/tacey/my-custom-cookiecutters-dir/" replay_dir: "/home/tacey/my-custom-replay-dir/" abbreviations: pp: https://github.com/audreyr/cookiecutter-pypackage.git gh: https://github.com/{0}.git bb: https://bitbucket.org/{0}
可用的设置是:
别名:后缀
形式的前缀。任何后缀都将使用标准的Python字符串格式插入到扩展中以代替文本{0},使用上面的别名,你能够简单地经过cookiecutter pp
或或cookiecutter gh:audreyr/cookiecutter-pypackage
来使用cookiecutter -pypackage模板。上面显示的gh (github)、bb (bitbucket)和gl (gitlab)缩略语其实是内置的,不须要本身定义就可使用它们。你能够在Python代码中使用Cookiecutter
from cookiecutter.main import cookiecutter #根据cookiecutter-pypackage/ 模板建立项目 cookiecutter('cookiecutter-pypackage/') # 根据cookiecutter-pypackage.git repo 模板建立项目 cookiecutter('https://github.com/audreyr/cookiecutter-pypackage.git')
若是您正在编写一个web框架,而且须要为开发人员提供一个相似于django-admin.py startproject或npm init的工具,这将很是有用。
使用no_input
抑制要求输入的提示。
基本示例:使用默认设置
若是与no_input
一块儿使用,Cookiecutter将选择一个默认值:
from cookiecutter.main import cookiecutter cookiecutter( 'cookiecutter-django', no_input=True, )
在这种状况下,它将使用cookiecutter.json或.cookiecutterrc中定义的默认值。(来自cookiecutter.json的值将被.cookiecutterrc中的值覆盖)
高级示例:默认+额外的上下文
若是将extra_context dict
与no_input
参数组合在一块儿, 您可使用设置的上下文参数列表以编程方式建立项目,而无需任何命令行提示:
cookiecutter('cookiecutter-pypackage/', no_input=True, extra_context={'project_name': 'TheGreatest'})
有关这部分的更多详细信息,请参阅API参考。
cookiecutter.json的值(但不是键!)也是Jinja2模板。用户提示符中的值会当即添加到上下文中,这样就能够从之前的值派生出一个上下文值。经过提供更合理的默认值,这种方法能够潜在地为用户节省许多键盘按键操做。
Python包显示了其命名约定的一些模式:
这是一个带有此模式模板值的cookiecutter.json:
{ "project_name": "My New Project", "project_slug": "{{ cookiecutter.project_name|lower|replace(' ', '-') }}", "pkg_name": "{{ cookiecutter.project_slug|replace('-', '') }}" }
若是用户采用默认值或使用no_input
,则模板化值将为:
或者,若是用户提供Yet Another New Project,则值为:
能够在cookiecutter.json中使用_copy_without_render键来避免渲染cookiecutter的目录和文件。此键的值接受Unix shell样式通配符列表:
{ "project_slug": "sample", "_copy_without_render": [ "*.html", "*not_rendered_dir", "rendered_dir/not_rendered_file.ini" ] }
在调用时,Cookiecutter将json文件转储到〜/.cookiecutter_replay/
,这使你能够稍后重放。
换句话说,它会保留您对模板的输入,并在您再次运行相同模板时获取它。
重播文件的示例(经过cookiecutter gh:hackebrot/cookiedoze
r建立):
{ "cookiecutter": { "app_class_name": "FooBarApp", "app_title": "Foo Bar", "email": "raphael@example.com", "full_name": "Raphael Pierzina", "github_username": "hackebrot", "kivy_version": "1.8.0", "project_slug": "foobar", "short_description": "A sleek slideshow app that supports swipe gestures.", "version": "0.1.0", "year": "2015" } }
要在不在命令行上提示的状况下获取此上下文数据,您可使用如下任一方法。
在命令行上传递相应选项:
cookiecutter --replay gh:hackebrot/cookiedozer
或者使用Python API:
from cookiecutter.main import cookiecutter cookiecutter('gh:hackebrot/cookiedozer', replay=True)
若是要从更新的模板建立新项目,此功能就会派上用场。
-V, --version
显示版本并退出。
--no-input
不要提示参数,只使用cookiecutter.json文件内容
-c, --checkout
branch, tag or commit to checkout after git clone
-v, --verbose
打印调试信息
--replay
不要提示参数,只使用以前输入的信息
-f, --overwrite-if-exists
若是输出目录的内容已经存在,则覆盖它
-o, --output-dir
将生成的项目目录输出到哪里,即指定建立项目的目录。
--config-file
指定用户配置文件
--default-config
不要加载配置文件。使用默认值
--debug-file
指定用做DEBUG日志记录流文件
选择变量在建立项目时提供不一样的选择。 根据用户的选择,模板以不一样的方式渲染内容。
选择变量是常规键/值对,但值是字符串列表。
例如,若是在cookiecutter.json
中提供如下选项变量:
{ "license": ["MIT", "BSD-3", "GNU GPL v3.0", "Apache Software License 2.0"] }
运行Cookiecutter时你会获得如下选择:
Select license: 1 - MIT 2 - BSD-3 3 - GNU GPL v3.0 4 - Apache Software License 2.0 Choose from 1, 2, 3, 4 [1]:
根据用户的选择,Cookiecutter将渲染不一样的许可证。
上面的许可选择变量建立了cookiecutter.license
,能够像下面这样使用:
{%- if cookiecutter.license == "MIT" -%} # 此处可能的许可内容 {%- elif cookiecutter.license == "BSD-3" -%} # 这里有更多可能的许可内容
Cookiecutter使用Jinja2 s if条件表达式来肯定正确的许可证。
建立的选择变量仍然是常规的Cookiecutter变量,能够像这样使用:
License ------- Distributed under the terms of the `{{cookiecutter.license}}`_ license,
选择变量可使用用户配置文件覆盖。
例如,可使用列表做为值在cookiecutter.json
中建立选择变量:
{ "license": ["MIT", "BSD-3", "GNU GPL v3.0", "Apache Software License 2.0"] }
默认状况下,值列表中的第一个条目用做提示中的默认值。
将默认许可协议设置为Apache Software License 2.0能够在用户配置文件中使用如下方法完成:
default_context: license: "Apache Software License 2.0"
提示会发生变化,以下所示:
Select license: 1 - Apache Software License 2.0 2 - MIT 3 - BSD-3 4 - GNU GPL v3.0 Choose from 1, 2, 3, 4 [1]
注意:如你所见,选项的顺序从1 - MIT
更改成1 - Apache Software License 2.0
。 Cookiecutter将列表中的第一个值做为默认值。
字典变量提供了一种在渲染模板时定义深层结构化信息的方法。
顾名思义,字典变量是键值对的字典。 字典值自己能够是其余字典和列表 - 数据结构能够根据须要进行深刻。
例如,您能够在cookiecutter.json
中提供如下字典变量:
{ "project_slug": "new_project", "file_types": { "png": { "name": "Portable Network Graphic", "library": "libpng", "apps": [ "GIMP" ] }, "bmp": { "name": "Bitmap", "library": "libbmp", "apps": [ "Paint", "GIMP" ] } } }
上面的file_type字典变量建立了cookiecutter.file_types,能够像这样使用:
{% for extension, details in cookiecutter.file_types|dictsort %} <dl> <dt>Format name:</dt> <dd>{{ details.name }}</dd> <dt>Extension:</dt> <dd>{{ extension }}</dd> <dt>Applications:</dt> <dd> <ul> {% for app in details.apps -%} <li>{{ app }}</li> {% endfor -%} </ul> </dd> </dl> {% endfor %}
Cookiecutter使用Jinja2 for表达式来迭代字典中的条目。
模板可使用自定义Jinja2扩展扩展Cookiecutter环境,能够添加额外的过滤器,测试,全局变量甚至扩展解析器。
为此,模板做者必须在cookiecutter.json
中指定所需的扩展名,以下所示:
{ "project_slug": "Foobar", "year": "{% now 'utc', '%Y' %}", "_extensions": ["jinja2_time.TimeExtension"] }
在调用时,Cookiecutter尝试导入扩展并分别将它们添加到其环境中。
在上面的示例中,Cookiecutter在安装jinja2_time.TimeExtension以后提供了附加标记now,并在cookiecutter.json
中启用它。
请注意,Cookiecutter不会自行安装任何依赖项! 做为用户,您须要确保已安装全部扩展,而后在须要自定义Jinja2扩展的模板上运行Cookiecutter。