jinja2 通过添加自定义parser实现macro的名称调整
实际上是dbt 在设计macro 中的一个技巧,比较有意思,对于系统或者三方包开发的macro 添加自己prefix
比如,原始macro name 为dremio__alter_column_type
dbt 会将解析的macro 添加一个dbt_macro__的前缀为
dbt_macro__dremio__alter_column_type
,以下说明下实现
参考实现
- 自定义解析&env
import jinja2
import jinja2.sandbox
import jinja2.parser
import jinja2.nodes
# 类似dbt get_dbt_macro_name 工具方法
def get_dbt_macro_name(name):
return f"dbt_macro__{name}"
# 自定义解析
class MacroFuzzParser(jinja2.parser.Parser):
def parse_macro(self):
node = jinja2.nodes.Macro(lineno=next(self.stream).lineno)
# 解析名称添加前边的前缀
node.name = get_dbt_macro_name(self.parse_assign_target(name_only=True).name)
self.parse_signature(node)
node.body = self.parse_statements(("name:endmacro",), drop_needle=True)
return node
# 自定义env
class MacroFuzzEnvironment(jinja2.sandbox.SandboxedEnvironment):
def _parse(self, source, name, filename):
return MacroFuzzParser(self, source, name, filename).parse()
- 使用
from jinja import MacroFuzzEnvironment,get_dbt_macro_name
env = MacroFuzzEnvironment()
macro_template = """
{% macro mydemo(name, age) -%}
{{name}} -----{{age}}
{%- endmacro %}
"""
# 通过string 模式的模版加载
template = env.from_string(macro_template)
context = {"name":"dalong","age":18}
# template.make_module 创建模块
module = template.make_module(vars=context, shared=False)
# module 会包含一个macro 名称的属性(是一个方法)
print(module.__dict__)
macro_func = module.__dict__[get_dbt_macro_name("mydemo")]
# 调用方法
info = macro_func(**context)
print(info)
- 效果
说明
dbt 对于jinja2 的一些扩展比较有意思,很值得学习, 可以方便的实现一个隔离
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
2023-04-14 使用cups + ipp 协议client 进行网络打印处理
2023-04-14 melange+ apko 基于的alpine docker 镜像集成玩法
2023-04-14 melange 基于源码构建apk 包的工具
2021-04-14 cube.js 通过prepareCompiler获取 meta
2020-04-14 easy-rules spring boot集成使用二
2020-04-14 easy-rules spring boot集成使用
2019-04-14 edgedb 基本试用