Cookiecutter 将一个文件夹复制到多个不同名称的文件夹

Cookiecutter copy one folder to multiple folders with different names

我的 Cookiecutter 项目结构如下

├── project
│   ├── {{Cookiecutter.client_name}}
│   │   ├── {{Cookiecutter.account_name}}
│   │   │   │── some-folder  
│   │   │   ├── {{Cookiecutter.account_name}}.py

cookiecutter.json 看起来像这样

{
    "client_name": "client",
    "account_name": "account"
}

现在,代替一个 account_name。我想添加多个 account_names 以便当 Cookiecutter 生成项目时 {{Cookiecutter.client_name}} 应该有多个文件夹,如 account1、account2、account3 等等..

我已经浏览了 Cookiecutter 文档,找不到任何有意义的内容或关于如何去做的内容。

据我所知,如果帐户数量未事先固定,则使用 cookiecutter 是不可能的。但是你可以用钩子达到同样的效果。像这样的东西:(n.b。未经测试)

├── project
│   ├── {{ client_name }}
│   │   ├── account_name
│   │   │   │── some-folder  
│   │   │   ├── account_name.py
|   |-- hooks
|   |   |-- post_gen_project.py
# post_gen_project.py
# runs from the *generated* project
from pathlib import Path
from shutil import copy, rmtree
accounts = [x.strip() for x in {{ accounts }}.split(",")] # cookiecutter will render this for you
client_name = {{ client_name }}
src = Path(client_name)
for account in accounts:
    copy(src / "account_name", src/account)
    fn = src/ f"account/account_name.py"
    fn.rename(fn.with_name(f"{account}.py"))
rmtree(src)

如果您有 很多 的事情要做,您最好自己编写部署脚本并避免使用 cookiecutter。

我假设您的帐户输入 , 分开:我不记得是否有任何方法可以在 cookiecutter 中获取原始列表类型。

另一种选择是使用 nested cookiecutters——具体来说,从 post_gen 挂钩中为 account 调用一个 cookiecutter,循环直到用户不想再添加帐户。像这样的东西(再次未经测试,作为起点提供):

├── project
│   ├── {{ client_name }}
│   │   ├── account_template
|   |   |   |-- {{ account_name }}
│   |   │   │   │── some-folder  
│   |   │   │   ├── {{ account_name }}.py
|   |-- hooks
|   |   |-- post_gen_project.py
# cookiecutter_project.json
...
"_copy_without_render": ["account_template/"]

这会将我们的内部 cookiecutter 部署到我们想要的位置,而无需渲染它。然后在里面的 cookiecutter:

# account_template/cookiecutter.json
{ "account_name": "default account", "client_name": "default client"}

然后最后,在外层千篇一律的钩子中:

# hooks/post_gen_project.py
from shutil import rmtree
from cookiecutter.main import cookiecutter

client_name = {{ client_name }}
cont = True
while cont:
    account_name = input("Enter account name: ")
    cookiecutter(
                 "template_account", 
                  no_input=True,
                  extra_content=dict(
                                     account_name=account_name,
                                     client_name=client_name
                                     )
                )
    cont = not input("Press enter to continue").strip()

rmtree("template_account")

如果帐户数量 预先固定的,这很容易---只需命名一组 account1,下一组 account2 等等。

参考文献:

https://cookiecutter.readthedocs.io/en/1.7.3/advanced/hooks.html https://cookiecutter.readthedocs.io/en/1.7.3/advanced/suppressing_prompts.html#suppressing-command-line-prompts