本文中的Hook就是钩子,钩子就是Hook

使用生成前/生成后钩子脚本

你可以在项目生成之前和/或之后运行Python或Shell脚本。

像这样把它们放进Hook里:

  1. cookiecutter-something/
  2. ├── {{cookiecutter.project_slug}}/
  3. ├── hooks
  4. ├── pre_gen_project.py
  5. └── post_gen_project.py
  6. └── cookiecutter.json

Shell脚本工作方式类似:

  1. cookiecutter-something/
  2. ├── {{cookiecutter.project_slug}}/
  3. ├── hooks
  4. ├── pre_gen_project.sh
  5. └── post_gen_project.sh
  6. └── cookiecutter.json

将Cookiecutter扩展到使用其他类型的脚本应该不会太难。你可以根据你系统中存在的脚本系统尝试一下。

为了可移植性,你应该为Hook使用Python脚本(扩展名为.py),因为这些脚本可以在任何平台上运行。但是,如果您希望模板仅在单个平台上运行,则shell脚本(或Windows上的.bat文件)原则上都是可行的。

编写钩子

这里有一些关于如何编写生成前/生成后钩子脚本的细节。

以适当的状态退出

确保钩子脚本以一种健壮的方式工作。如果钩子脚本运行失败(也就是说它以非零退出状态结束),项目生成将停止,生成的目录将被清除。

当前工作目录

运行钩子脚本时,它们的工作目录是生成的项目的根目录。这使得后生成挂钩可以使用相对路径轻松查找生成的文件。

** 模板变量在脚本中呈现**

就像你的项目模板一样,Cookiecutter也在你的脚本中呈现Jinja模板语法。这使您可以将Jinja模板变量合并到脚本中。例如,这行Python将module_name设置为cookiecutter.module_name模板变量的值:

  1. module_name = '{{ cookiecutter.module_name }}'

示例:验证模板变量

下面是一个脚本示例,它在生成项目之前验证模板变量,将其保存到hooks/pre_gen_project.py:中:

  1. import re
  2. import sys
  3. MODULE_REGEX = r'^[_a-zA-Z][_a-zA-Z0-9]+$'
  4. module_name = '{{ cookiecutter.module_name }}'
  5. if not re.match(MODULE_REGEX, module_name):
  6. print('ERROR: %s 不是有效的Python模块名称!' % module_name)
  7. # 以状态1退出,表示失败
  8. sys.exit(1)

用户配置

如果你经常使用Cookiecutter,你会发现有一个用户配置文件很有用。默认情况下,Cookiecutter尝试从主目录中的.cookiecutterrc文件中检索设置。从1.3.0版本开始,您还可以通过--config-file在命令行上指定配置文件。

  1. $ cookiecutter --config-file /home/tacey/my-custom-config.yaml cookiecutter-pypackage

或者你可以设置COOKIECUTTER_CONFIG环境变量:

  1. export COOKIECUTTER_CONFIG=/home/tacey/my-custom-config.yaml

如果您希望坚持使用内置配置而不加载任何用户配置文件,请使用cli选项--default-config。阻止Cookiecutter加载用户设置对于在隔离环境中编写集成测试至关重要。

用户配置示例:

  1. default_context:
  2. full_name: "Tacey Wong"
  3. email: "xinyong.wang@qq.com"
  4. github_username: "taceywong"
  5. cookiecutters_dir: "/home/tacey/my-custom-cookiecutters-dir/"
  6. replay_dir: "/home/tacey/my-custom-replay-dir/"
  7. abbreviations:
  8. pp: https://github.com/audreyr/cookiecutter-pypackage.git
  9. gh: https://github.com/{0}.git
  10. 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

  1. from cookiecutter.main import cookiecutter
  2. #根据cookiecutter-pypackage/ 模板创建项目
  3. cookiecutter('cookiecutter-pypackage/')
  4. # 根据cookiecutter-pypackage.git repo 模板创建项目
  5. cookiecutter('https://github.com/audreyr/cookiecutter-pypackage.git')

如果您正在编写一个web框架,并且需要为开发人员提供一个类似于django-admin.py startproject或npm init的工具,这将非常有用。

抑制命令行提示

使用no_input抑制要求输入的提示。

基本示例:使用默认设置

如果与no_input一起使用,Cookiecutter将选择一个默认值:

  1. from cookiecutter.main import cookiecutter
  2. cookiecutter(
  3. 'cookiecutter-django',
  4. no_input=True,
  5. )

在这种情况下,它将使用cookiecutter.json或.cookiecutterrc中定义的默认值。(来自cookiecutter.json的值将被.cookiecutterrc中的值覆盖)

高级示例:默认+额外的上下文

如果将extra_context dictno_input参数组合在一起, 您可以使用设置的上下文参数列表以编程方式创建项目,而无需任何命令行提示:

  1. cookiecutter('cookiecutter-pypackage/',
  2. no_input=True,
  3. extra_context={'project_name': 'TheGreatest'})

有关这部分的更多详细信息,请参阅API参考

上下文值中的模板

cookiecutter.json的值(但不是键!)也是Jinja2模板。用户提示符中的值会立即添加到上下文中,这样就可以从以前的值派生出一个上下文值。通过提供更合理的默认值,这种方法可以潜在地为用户节省许多键盘按键操作。

基础示例:上下文中的模板

Python包显示了其命名约定的一些模式:

  • 一个人类可读的项目名称
  • 小写、横岗组成的库名
  • 一个可导入的,无破折号的包名称

这是一个带有此模式模板值的cookiecutter.json:

  1. {
  2. "project_name": "My New Project",
  3. "project_slug": "{{ cookiecutter.project_name|lower|replace(' ', '-') }}",
  4. "pkg_name": "{{ cookiecutter.project_slug|replace('-', '') }}"
  5. }

如果用户采用默认值或使用no_input,则模板化值将为:

  • my-new-project
  • mynewproject

或者,如果用户提供Yet Another New Project,则值为:

  • yet-another-new-project
  • yetanothernewproject

复制而不渲染

可以在cookiecutter.json中使用_copy_without_render键来避免渲染cookiecutter的目录和文件。此键的值接受Unix shell样式通配符列表:

  1. {
  2. "project_slug": "sample",
  3. "_copy_without_render": [
  4. "*.html",
  5. "*not_rendered_dir",
  6. "rendered_dir/not_rendered_file.ini"
  7. ]
  8. }

重播项目生成

在调用时,Cookiecutter将json文件转储到〜/.cookiecutter_replay/,这使你可以稍后重放。

换句话说,它会保留您对模板的输入,并在您再次运行相同模板时获取它。

重播文件的示例(通过cookiecutter gh:hackebrot/cookiedozer创建):

  1. {
  2. "cookiecutter": {
  3. "app_class_name": "FooBarApp",
  4. "app_title": "Foo Bar",
  5. "email": "raphael@example.com",
  6. "full_name": "Raphael Pierzina",
  7. "github_username": "hackebrot",
  8. "kivy_version": "1.8.0",
  9. "project_slug": "foobar",
  10. "short_description": "A sleek slideshow app that supports swipe gestures.",
  11. "version": "0.1.0",
  12. "year": "2015"
  13. }
  14. }

要在不在命令行上提示的情况下获取此上下文数据,您可以使用以下任一方法。

在命令行上传递相应选项:

  1. cookiecutter --replay gh:hackebrot/cookiedozer

或者使用Python API:

  1. from cookiecutter.main import cookiecutter
  2. 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中提供以下选项变量:

  1. {
  2. "license": ["MIT", "BSD-3", "GNU GPL v3.0", "Apache Software License 2.0"]
  3. }

运行Cookiecutter时你会得到以下选择:

  1. Select license:
  2. 1 - MIT
  3. 2 - BSD-3
  4. 3 - GNU GPL v3.0
  5. 4 - Apache Software License 2.0
  6. Choose from 1, 2, 3, 4 [1]:

根据用户的选择,Cookiecutter将渲染不同的许可证。

上面的许可选择变量创建了cookiecutter.license,可以像下面这样使用:

  1. {%- if cookiecutter.license == "MIT" -%}
  2. # 此处可能的许可内容
  3. {%- elif cookiecutter.license == "BSD-3" -%}
  4. # 这里有更多可能的许可内容

Cookiecutter使用Jinja2 s if条件表达式来确定正确的许可证。

创建的选择变量仍然是常规的Cookiecutter变量,可以像这样使用:

  1. License
  2. -------
  3. Distributed under the terms of the `{{cookiecutter.license}}`_ license,

覆盖默认选择值

选择变量可以使用用户配置文件覆盖。

例如,可以使用列表作为值在cookiecutter.json中创建选择变量:

  1. {
  2. "license": ["MIT", "BSD-3", "GNU GPL v3.0", "Apache Software License 2.0"]
  3. }

默认情况下,值列表中的第一个条目用作提示中的默认值。

将默认许可协议设置为Apache Software License 2.0可以在用户配置文件中使用以下方法完成:

  1. default_context:
  2. license: "Apache Software License 2.0"

提示会发生变化,如下所示:

  1. Select license:
  2. 1 - Apache Software License 2.0
  3. 2 - MIT
  4. 3 - BSD-3
  5. 4 - GNU GPL v3.0
  6. Choose from 1, 2, 3, 4 [1]

注意:如你所见,选项的顺序从1 - MIT更改为1 - Apache Software License 2.0。 Cookiecutter将列表中的第一个值作为默认值。

字典变量

字典变量提供了一种在渲染模板时定义深层结构化信息的方法。

基础使用

顾名思义,字典变量是键值对的字典。 字典值本身可以是其他字典和列表 - 数据结构可以根据需要进行深入。

例如,您可以在cookiecutter.json中提供以下字典变量:

  1. {
  2. "project_slug": "new_project",
  3. "file_types": {
  4. "png": {
  5. "name": "Portable Network Graphic",
  6. "library": "libpng",
  7. "apps": [
  8. "GIMP"
  9. ]
  10. },
  11. "bmp": {
  12. "name": "Bitmap",
  13. "library": "libbmp",
  14. "apps": [
  15. "Paint",
  16. "GIMP"
  17. ]
  18. }
  19. }
  20. }

上面的file_type字典变量创建了cookiecutter.file_types,可以像这样使用:

  1. {% for extension, details in cookiecutter.file_types|dictsort %}
  2. <dl>
  3. <dt>Format name:</dt>
  4. <dd>{{ details.name }}</dd>
  5. <dt>Extension:</dt>
  6. <dd>{{ extension }}</dd>
  7. <dt>Applications:</dt>
  8. <dd>
  9. <ul>
  10. {% for app in details.apps -%}
  11. <li>{{ app }}</li>
  12. {% endfor -%}
  13. </ul>
  14. </dd>
  15. </dl>
  16. {% endfor %}

Cookiecutter使用Jinja2 for表达式来迭代字典中的条目。

模板扩展

模板可以使用自定义Jinja2扩展扩展Cookiecutter环境,可以添加额外的过滤器,测试,全局变量甚至扩展解析器。

为此,模板作者必须在cookiecutter.json中指定所需的扩展名,如下所示:

  1. {
  2. "project_slug": "Foobar",
  3. "year": "{% now 'utc', '%Y' %}",
  4. "_extensions": ["jinja2_time.TimeExtension"]
  5. }

在调用时,Cookiecutter尝试导入扩展并分别将它们添加到其环境中。

在上面的示例中,Cookiecutter在安装jinja2_time.TimeExtension之后提供了附加标记now,并在cookiecutter.json中启用它。

请注意,Cookiecutter不会自行安装任何依赖项! 作为用户,您需要确保已安装所有扩展,然后在需要自定义Jinja2扩展的模板上运行Cookiecutter。

Cookiecutter: 更好的项目模板工具:(3)高级用法的更多相关文章

  1. Cookiecutter: 更好的项目模板工具:(2)安装及基础使用

    安装 通过python包管理工具 命令行输入 $pip install cookiecutter 或者 # mac os经常会禁止用户全局安装python包 $pip install --user c ...

  2. Cookiecutter: 更好的项目模板工具:(1)简介及可用资源汇总

    原文档地址:https://cookiecutter.readthedocs.io/en/latest/ 本系列只介绍cookiecutter的基础使用,而且会删除与功能使用无关的部分.深度使用及了解 ...

  3. Vue.js——60分钟webpack项目模板快速入门

    概述 browserify是一个 CommonJS风格的模块管理和打包工具,上一篇我们简单地介绍了Vue.js官方基于browserify构筑的一套开发模板.webpack提供了和browserify ...

  4. Vue.js——60分钟browserify项目模板快速入门

    概述 在之前的一系列vue.js文章,我们都是用传统模式引用vue.js以及其他的js文件的,这在开发时会产生一些问题. 首先,这限定了我们的开发模式是基于页面的,而不是基于组件的,组件的所有代码都直 ...

  5. Gulp.js - 简单、直观的自动化项目构建工具

    Gulp.js 是一个简单.直观的构建系统.崇尚代码优于配置,使复杂的任务更好管理.通过结合 NodeJS 的数据流的能力,你能够快速构建.通过简单的 API 接口,只需几步就能搭建起自己的自动化项目 ...

  6. 20Spring_JdbcTemplatem模板工具类

    JdbcTemplate 是Spring提供简化Jdbc开发模板工具类.为了更好的了解整个JdbcTemplate配置数据库连接池的过程,这篇文章不采用配置文件的方式,而是采用最基本的代码 的方式来写 ...

  7. cocos2d-x创建新项目模板

    1.起因 长期使用项目中自带的HelloWorldScene来创建模板工程,不知大家有木有感到厌烦? 我是个懒人,所以就弄了个新的模板工程.这样最起码可以不用每次都把HelloWorldScene删掉 ...

  8. Vue.jsbrowserify项目模板

    Vue.js——60分钟browserify项目模板快速入门   概述 在之前的一系列vue.js文章,我们都是用传统模式引用vue.js以及其他的js文件的,这在开发时会产生一些问题. 首先,这限定 ...

  9. 后端开发实践——Spring Boot项目模板

    在我的工作中,我从零开始搭建了不少软件项目,其中包含了基础代码框架和持续集成基础设施等,这些内容在敏捷开发中通常被称为"第0个迭代"要做的事情.但是,当项目运行了一段时间之后再来反 ...

随机推荐

  1. Go语言二叉树定义及遍历算法实现

    // binary_tree 二叉树 package Algorithm import ( "reflect" ) // 二叉树定义 type BinaryTree struct ...

  2. ACC自适应巡航控制系统介绍

    本文是关于ACC自适应巡航控制系统的介绍,罗孚从个人视角出发,描述对ACC系统的理解,以及在一些使用场景下的思考. 什么是ACC? ACC系统是在定速巡航装置的基础上发展而来的,区别在于定速巡航只能限 ...

  3. Mongodb: Sort operation used more than the maximum 33554432 bytes of RAM

    上线许久的产品突然爆出了一个Mongodb 查询的BUG,错误如下: "exception":"org.springframework.data.mongodb.Unca ...

  4. Javascript正则表达入参是null

    今天群友问了一个问题,如下的执行结果是什么? var reg = /^[a-z0-9\u4e00-\u9fa5]{0,15}$/; console.log(reg.test(null)); // tr ...

  5. wait-for

    Use a tool such as wait-for-it, dockerize, or sh-compatible wait-for. These are small wrapper script ...

  6. Docker 的插件式设计

    http://www.tuicool.com/articles/MnIRZvJ http://uzhima.com/2016/08/02/what-is-docker-volume-plugin/ 在 ...

  7. iOS 线上版本图片资源格式的问题导致的闪退

    链接:https://www.jianshu.com/p/6492779cb89e來源:简书 导致这种问题的原因是:在 Xcode 8 中,当你资源文件中[含有16位图]或者[图片显示模式γ值为'P3 ...

  8. 分析轮子(七)- RandomAccess.java

    1:还是先上一个类的继承关系比较图吧! 2:看一下 RandomAccess.java 的源码,空空如也,什么都没有,那她有什么用处呢? /** * Marker interface used by ...

  9. Effective Java 第三版——66. 明智谨慎地使用本地方法

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  10. Java读取Excel内容

    借助于apathe的poi.jar,由于上传文件不支持.jar所以请下载后将文件改为.jar,在应用程序中添加poi.jar包,并将需要读取的excel文件放入根目录即可 本例使用java来读取exc ...