Cookiecutter: 更好的項目模板工具:(3)高級用法

本文中的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}

可用的設置是:

  • 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 dictno_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/cookiedozer建立):

{
    "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。

相關文章
相關標籤/搜索