結局面倒くさくなってjinja2のtemplateをサポートした

github.com

はじめに

結局面倒くさくなってjinja2のtemplateをサポートした。なんだかんだでtemplateの機能はすごく便利。とは言えせっかくのdict(yaml)の構造が全て無視され文字列として扱われるというところが微妙といえば微妙。

どうしてtemplateが便利なのかということをちょっと考えてみたけれど。templateを定義できるというのは遠くの位置の場所に穴をあけてそこに後で値を埋め込むというようなことが出来るから便利。

$jinja2_template

例えば、before,afterは決まっていて、bodyだけを書き変えたいような状況。がんばって自分でdictのように扱って埋め込んでも良いのだけれど。やっぱりつらい。

section:
  before:
    <before text>
  body:
    <本文>  # ここだけ差し替えたい
  after:
    <after text>

簡単に実装出来るならと思ってとりあえず実装してみたら瞬殺だったので、加えてみることにした。

上の例に対応するものをこのjinja2のtemplateの機能を使うとこういう感じになる。$jinja2_templateは関数を返す。関数はletで束縛しておくと普通のactionとして使える。(個人的には、束縛した変数はkebab-caseで書かれているのが好きかも。pythonなどでは定義出来ない形式なのでこの言語上で格納している情報ということが分かって便利)

$let:
  template-section:
    $jinja2_template: |
      section:
        before: <before text>
        body: {{body}}
        after: <after text>
body:
  - $template-section: {body: body1}
  - $template-section: {body: body2}

こういう感じ。

$ zenmai main.yaml
- section:
    before: <before text>
    body: body1
    after: <after text>
- section:
    before: <before text>
    body: body2
    after: <after text>

j2cliについて

ちょっとした脱線だけれどj2cliについても考えたい。現状の実装で静的な参照関係には対応しているものの動的な参照関係には対応していないような気がする。やり方は色々あるのだけれど。どのように対応したら良いのかと言うのがまだ見えていない。j2cliの仕組みはすごく単純なので参考になるかもしれない。

j2cliのコマンドのj2の使い方の最も単純化した例は以下の様な感じ。

$ j2 <template> <data>

j2cliはそもそもjinja2というtemplate engineのコマンドライン用のclientでしかないので、jsonyamlだとかの構造は関係ないのだけれど。やっていることは単純でtemplate用のファイルとは別に設定情報的な情報を取るような仕組み。取り込んだ情報をそのままrenderingに使うという感じ。

使い方はこういう感じ

例えば、dev用の情報staging用の情報production用の情報を別々の設定ファイルに入れておき、template部分は共通化するというような使い方。参照関係が複雑なわけではなければこのままでも十分。

とは言え、ちょっとした違いのバリエーションを用意したいときなどに困ることがあったりする。例えば、loggingのlevelだけdebugにしたlocalを作りたいだとか。local用の設定はチームの全体で共有されているが、自分用の設定ファイルには一部の変更を加えたいと言うような状況。このあたりの対応についてどうするかということがまだ正確には見えていない。

そろそろreadme

そろそろreadmeをどうにかしたいというような気持ちが出てきた。なんだか見てみると順を追って説明ができていないような気がする。直したいと思うんだけれど直すための気力が捻出できずにいる。

一時的に今まで存在していたコード用の例と共にコマンドラインのコマンドを使った例を併記していたのだけれど。考えてみるとコード用の例が必要になる人は存在しないのではと思ったりしたので、readmeにはコマンドラインだけの例にした。

(code exampleの方$inc,$inc2で解釈の関係明らかになったりとか、sys.modules[name]渡しているので定義した関数がすぐに利用できるとか、importできるとかは明らかになっているけれど。コード例自体には意味がない。あと、今なら別ファイルを相対パスでもimport出来るので、command line exampleの方の感じで書けば十分みたいなところもあるし。 あと、いきなりdictknife(別のライブラリ)使っているのも例としては微妙)