mako な「Python functions in Mako templates (not in module-level blocks)」

あえて書くことか?

「あぁこれならなんでもありだなと思った」という、「ほぼ単なる感想」。

mako 化前がこんななわけなのよ:

 1 # ...
 2 
 3 def _ts_to_tss(ts, frac=3):
 4     # ...
 5 
 6 # ...
 7 
 8 def _video_insert_chmark_by_blank_main():
 9     # ...
10     impl = _ImplMain(args)
11     #
12     impl.result_lines.append("#")
13     impl.result_lines.append(" ".join(
14             filter(
15                 None,
16                 ['"${ffmpeg}"', '-y \\\n    ',
17                  '-i', '"${inmov}"', "\\\n    ",
18                  '-i', "pipe:",
19                  "-map_metadata", "1",
20                  "-c", "copy",
21                  '"${outbase}.${ext}"',
22                  "<<'__END__'"
23                  ])))
24     impl.result_lines.append(";FFMETADATA1")
25     for i, (s, e) in impl.get_part_ranges():
26         impl.result_lines.append("")
27         impl.result_lines.append("[CHAPTER]")
28         impl.result_lines.append("TIMEBASE=1/1000")
29         impl.result_lines.append(
30             "# %s -> %s (%.3f secs)" % (
31                 _ts_to_tss(s), _ts_to_tss(e), e - s))
32         impl.result_lines.append("START=%d" % int(s * 1000))
33         impl.result_lines.append("END=%d" % int(e * 1000))
34         impl.result_lines.append("title=%s%s" % (
35                 args.chapter_title_base,
36                 impl.seqno_format % (i + 1)))
37     impl.result_lines.append("__END__")
38     if args.replace:
39         impl.result_lines.append('if test $? -eq 0 ; then')
40         impl.result_lines.append('    mv -fv "${inmov}" "${inmov}".orig && \\')
41         impl.result_lines.append('    mv -fv "${outbase}.${ext}" "${inmov}"')
42         impl.result_lines.append('fi')
43     print(impl.get_result())

何を言いたいかというと、「データをテンプレートに渡す」ということだけでなく、「機能」も渡したい、てこと。内部的に使っている関数「_ts_to_tss」もテンプレートの著者が使えるように expose したいわけだ。テンプレートを書く立場からは「組み込み関数」に見えろ、てこと。(こういう「組み込み」でない「テンプレート共通」的なものは Defs and Blocks などで書ける。今したいのはそういうことではなくて。)

想像通りのやり方で出来る:

上で引用したコードの「部分移植」
 1 # ...
 2 from mako.template import Template  # requires Mako
 3 
 4 # ...
 5     tmpl = Template("""\
 6 %for i, (s, e) in splp:
 7 
 8 [CHAPTER]
 9 TIMEBASE=1/1000
10 # ${_ts_to_tss(s)} -> ${_ts_to_tss(e)} (${"%.3f" % (e - s)} secs)
11 START=${int(s*1000)}
12 END=${int(e*1000)}
13 title=${args.chapter_title_base + impl.seqno_format % (i + 1)}
14 %endfor
15 """)
16     print(
17         tmpl.render(
18             splp=list(impl.get_part_ranges()),
19             _ts_to_tss=_ts_to_tss, args=args, impl=impl))

まぁそりゃそうだよなとは思う。

にしてもあれだ。もちっと元のコードを整理してからじゃないと保守でけんもんになるわ。