mako-render が今ひとつなので

あるだけマシではあるんだけれど。

Jinja2 とは違い、一応 Mako には mako-render というコマンドラインスクリプトが付属していて、なのでスクリプトを作る手間なくテンプレートエンジンを使える。まぁ多くのテンプレートエンジンがそうなんだけど、Jinja2 でこれがないのが不思議。そして mako-render はね…、いかんせん単純過ぎて、ちょっと日常使いするのは無理がある。これはどっちかというと Mako そのものの検証や実験用だわ。

で、「日常使い」についてなんだけれども、たとえば「python スクリプトを作るのに毎度一から書き始めるのダルいじゃん」みたいなニーズね。「みんな大好きえくりぷす」が大嫌いだったり、もしくは「えくりぷすほどじゃねーんだわ」なんてよくあることでしょ、ないとは言わせない。

完成品とは言わないけど、mako-render よりはやや日常使い目指せる、それでもまだまだシンプルなのをさくっと作った:

my-mako-render.py
 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 から。


…実はこのネタ、何年も寝かせてたんだよね。ずっとやろうやろうと思ってたんだけど、なんかスッキリした解が思いつかなくてさ。なんだけどいざ手をつけてみたら、割とシンプルで使いやすいものになったと思う。