本文中的Hook就是鈎子,鈎子就是Hook
使用生成前/生成后鈎子腳本
你可以在項目生成之前和/或之后運行Python或Shell腳本。
像這樣把它們放進Hook里:
cookiecutter-something/
├── {{cookiecutter.project_slug}}/
├── hooks
│ ├── pre_gen_project.py
│ └── post_gen_project.py
└── cookiecutter.json
Shell腳本工作方式類似:
cookiecutter-something/
├── {{cookiecutter.project_slug}}/
├── hooks
│ ├── pre_gen_project.sh
│ └── post_gen_project.sh
└── cookiecutter.json
將Cookiecutter擴展到使用其他類型的腳本應該不會太難。你可以根據你系統中存在的腳本系統嘗試一下。
為了可移植性,你應該為Hook使用Python腳本(擴展名為.py),因為這些腳本可以在任何平台上運行。但是,如果您希望模板僅在單個平台上運行,則shell腳本(或Windows上的.bat文件)原則上都是可行的。
編寫鈎子
這里有一些關於如何編寫生成前/生成后鈎子腳本的細節。
以適當的狀態退出
確保鈎子腳本以一種健壯的方式工作。如果鈎子腳本運行失敗(也就是說它以非零退出狀態結束),項目生成將停止,生成的目錄將被清除。
當前工作目錄
運行鈎子腳本時,它們的工作目錄是生成的項目的根目錄。這使得后生成掛鈎可以使用相對路徑輕松查找生成的文件。
** 模板變量在腳本中呈現**
就像你的項目模板一樣,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}
可用的設置是:
- default_context: 每當使用Cookiecutter生成項目時,您希望作為上下文注入的鍵/值對的列表。生成任何項目時,這些值將被視為cookiecutter.json中的默認值。
- cookiecutters_dir: 當你使用Cookiecutter和git repo參數時,你的Cookiecutter模板被克隆到的目錄。
- replay_dir: Cookiecutter轉儲上下文數據的目錄,稍后您可以在使用replay功能時獲取該目錄。
- abbreviations: cookiecutters的縮寫列表。縮寫可以是repo名稱的簡單別名,也可以用作
別名:后綴
形式的前綴。任何后綴都將使用標准的Python字符串格式插入到擴展中以代替文本{0},使用上面的別名,你可以簡單地通過cookiecutter pp
或或cookiecutter gh:audreyr/cookiecutter-pypackage
來使用cookiecutter -pypackage模板。上面顯示的gh (github)、bb (bitbucket)和gl (gitlab)縮略語實際上是內置的,不需要自己定義就可以使用它們。
在Python代碼中調用Cookiecutter
你可以在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
,則模板化值將為:
- my-new-project
- mynewproject
或者,如果用戶提供Yet Another New Project,則值為:
- yet-another-new-project
- yetanothernewproject
復制而不渲染
可以在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。