あるだけマシではあるんだけれど。
Jinja2 とは違い、一応 Mako には mako-render というコマンドラインスクリプトが付属していて、なのでスクリプトを作る手間なくテンプレートエンジンを使える。まぁ多くのテンプレートエンジンがそうなんだけど、Jinja2 でこれがないのが不思議。そして mako-render はね…、いかんせん単純過ぎて、ちょっと日常使いするのは無理がある。これはどっちかというと Mako そのものの検証や実験用だわ。
で、「日常使い」についてなんだけれども、たとえば「python スクリプトを作るのに毎度一から書き始めるのダルいじゃん」みたいなニーズね。「みんな大好きえくりぷす」が大嫌いだったり、もしくは「えくりぷすほどじゃねーんだわ」なんてよくあることでしょ、ないとは言わせない。
完成品とは言わないけど、mako-render よりはやや日常使い目指せる、それでもまだまだシンプルなのをさくっと作った:
1 # -*- coding: utf-8 -*-
2 import io
3 import re
4 import os
5 import json
6 from mako.template import Template
7
8
9 def cmdline():
10 import argparse
11 parser = argparse.ArgumentParser()
12 parser.add_argument("template_dir")
13 parser.add_argument("--out-dir", default="_dist")
14 parser.add_argument("--vars-from-json")
15 parser.add_argument("--vars-from-jsonfile")
16 parser.add_argument("--filename-mapping") # eval?
17 args = parser.parse_args()
18 #
19 data = {}
20 if args.vars_from_jsonfile:
21 data.update(
22 json.load(
23 io.open(args.vars_from_jsonfile, encoding="utf-8")))
24 if args.vars_from_json:
25 data.update(
26 json.loads(args.vars_from_json))
27 #
28 for root, dirs, files in os.walk(args.template_dir):
29 outdir = os.path.normpath(
30 os.path.join(
31 args.out_dir,
32 os.path.relpath(root, args.template_dir)))
33 if not os.path.exists(outdir):
34 os.mkdir(outdir)
35 for fn in files:
36 ofnbase = fn
37 if args.filename_mapping:
38 ofnbase = eval(args.filename_mapping)
39 ofn = os.path.join(outdir, ofnbase)
40 template = Template(
41 filename=os.path.join(root, fn))
42 s = template.render(**data).encode("utf-8")
43 with io.open(ofn, "wb") as fo:
44 fo.write(s)
45
46
47 if __name__ == "__main__":
48 cmdline()
mako-render が「Windows ユーザにとって」いやらしいのが、レンダリング結果が標準出力固定であることだったりする。お馴染みちゃぁお馴染みなんだけれど、これだと「Unix改行コードにしたい」と思ってもかなわない。して私のスクリプトは、テンプレートのファイル名で書き出すようにしてある。
ただ「テンプレートのファイル名≠出力ファイル名」てのはありがちなので、このリネームを --filename-mapping
オプションでまかなってる。eval なのでやや危険でもあるんだけれども、まぁ「俺様さえよければいいのだ」のノリで。
あとテンプレートに埋め込むデータについては、元の mako-render がそうしているように「--vars
」で延々追加していくノリが鬱陶しいので json から。
…実はこのネタ、何年も寝かせてたんだよね。ずっとやろうやろうと思ってたんだけど、なんかスッキリした解が思いつかなくてさ。なんだけどいざ手をつけてみたら、割とシンプルで使いやすいものになったと思う。