跳转到主要内容

为Copier提供的特殊Jinja2扩展,允许使用相对于模板根的文件路径来加载扩展,而不是Python点路径。

项目描述

Copier Templates Extensions

ci documentation pypi version gitpod gitter

为Copier提供的特殊Jinja2扩展,允许使用相对于模板根的文件路径来加载扩展,而不是Python点路径。

安装

使用 pip

pip install copier-templates-extensions

使用 pipx

pip install --user pipx

pipx install copier
pipx inject copier copier-templates-extensions

使用方法

在模板配置中,首先添加我们的加载器扩展,然后添加使用相对文件路径的模板扩展,并在冒号后添加类名

_jinja_extensions:
- copier_templates_extensions.TemplateExtensionLoader
- extensions/context.py:ContextUpdater
- extensions/slugify.py:SlugifyExtension

在这个例子中,你应该在模板根目录下有一个名为 extensions 的目录,包含两个模块: context.pyslugify.py

📁 template_root
├── 📄 abc.txt.jinja
├── 📄 copier.yml
└── 📁 extensions
    ├── 📄 context.py
    └── 📄 slugify.py

请参阅 上下文钩子扩展 了解如何编写 ContextUpdater 类。

SlugifyExtension 类可以写成这样

import re
import unicodedata

from jinja2.ext import Extension


# taken from Django
# https://github.com/django/django/blob/main/django/utils/text.py
def slugify(value, allow_unicode=False):
    """
    Convert to ASCII if 'allow_unicode' is False. Convert spaces or repeated
    dashes to single dashes. Remove characters that aren't alphanumerics,
    underscores, or hyphens. Convert to lowercase. Also strip leading and
    trailing whitespace, dashes, and underscores.
    """
    value = str(value)
    if allow_unicode:
        value = unicodedata.normalize('NFKC', value)
    else:
        value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii')
    value = re.sub(r'[^\w\s-]', '', value.lower())
    return re.sub(r'[-\s]+', '-', value).strip('-_')


class SlugifyExtension(Extension):
    def __init__(self, environment):
        super().__init__(environment)
        environment.filters["slugify"] = slugify

上下文钩子扩展

此包还提供了一个方便的扩展类,允许模板编写者更新用于渲染模板的上下文,以添加、修改或删除上下文中的项。

在你的相对路径扩展模块之一中,创建一个继承自 ContextHook 的类,并重写其 hook 方法

from copier_templates_extensions import ContextHook


class ContextUpdater(ContextHook):
    def hook(self, context):
        new_context = {}
        new_context["say"] = "hello " + context["name"]
        return new_context

使用上述示例,您的上下文将被方法返回的 new_context 更新。如果您希望就地修改上下文,例如从其中 删除 项目,将 update 类属性设置为 False

from copier_templates_extensions import ContextHook


class ContextUpdater(ContextHook):
    update = False

    def hook(self, context):
        context["say"] = "hello " + context["name"]
        del context["name"]

在您的 Jinja 模板中,您现在可以直接访问 {{ say }} 变量。

这对于不想向用户提出太多问题,而是从他们的答案中推断一些值的模板项目来说非常有用。

考虑以下示例:您询问您的用户他们是否想生成 CLI 应用程序或 Web API。根据他们的答案,主 Python 模块应命名为 cli.pyapp.py

没有上下文钩子,您需要在某处编写 Jinja 宏,或在 Jinja 中直接更新上下文,并导入此文件(仍在使用 Jinja)在模块的文件名中

{# using macros #}
{%- macro module_name() %}
  {%- if project_type == "webapi" %}app{% else %}cli{% endif %}
{%- endmacro %}
{# or enhancing the context #}
{#- Initiate context with a copy of Copier answers -#}
{%- set ctx = _copier_answers.copy() -%}

{#- Populate our new variables -#}
{%- set _ = ctx.update({"module_name": ("app" if project_type == "webapi" else "cli") -%}
📁 template_root
├── 📄 copier.yml
├── 📄 macros      # the macros file
├── 📄 context     # the context file
├── 📁 extensions
│   └── 📄 slugify.py
└── 📁 {{project_name|slugify}}
    │
    │   # using the macros
    ├── 📄 {% import 'macros' as macros with context %}{{macros.module_name()}}.py.jinja
    │
    │   # or using the enhanced context
    └── 📄 {% from 'context' import ctx with context %}{{ctx.module_name}}.py.jinja

如您所见,两种形式都很难写

  • 宏或 context 只能放在根目录,因为文件名中不允许有斜杠 /
  • 您必须在模板文件名中使用空格和单引号(双引号不是有效的文件名字符,在 Windows 上),这并不干净
  • 文件名非常长

使用我们的上下文钩子可以使它变得非常简单和干净!

from copier_templates_extensions import ContextHook


class ContextUpdater(ContextHook):
    def hook(self, context):
        return {"module_name": "app" if context["project_type"] == "webapi" else "cli"}
📁 template_root
├── 📄 copier.yml
├── 📁 extensions
│   ├── 📄 slugify.py
│   └── 📄 context.py
└── 📁 {{project_name|slugify}}
    └── 📄 {{module_name}}.py.jinja

它是如何工作的?

注意丑陋的技巧!当加载特殊的 loader 扩展时,负责使用点路径(字符串)导入 Python 对象的函数在 jinja.environment 模块中被修补,在那里它用于加载扩展。修补后的版本增加了使用相对文件路径加载扩展的支持。Jinja 环境的文件系统加载器和其 searchpaths 属性用于查找模板的本地副本并确定要加载的扩展的绝对路径。

项目详情


下载文件

为您的平台下载文件。如果您不确定选择哪一个,请了解更多关于 安装包 的信息。

源分发

copier-templates-extensions-0.3.0.tar.gz (12.1 kB 查看哈希)

上传时间

构建分发

copier_templates_extensions-0.3.0-py3-none-any.whl (7.4 kB 查看哈希)

上传时间 Python 3

由以下机构支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面