jinja2のCLIラッパーのエラー表示を良い感じにした

github.com

jinja2のCLIラッパーのエラー表示を良い感じにした。元々最近余暇に元気がなくて機能を追加したりする気が起きなかったのだけれど。それを機会に自分の作っていたrepositoryのexamplesを整理していた。そのようなことをしている最中に幾つか気になる点が出てきて調整したりなどしていた。

↑のリポジトリはjinja2というpythonのtemplate engineのCLI用のラッパーなのだけれど。syntaxエラーになったときのエラーがわかりにくかったのでそこそこ良い感じにした。まだpypiにはあげていない。その他readmeの例も増やした。

example

実際のエラーの例

例えば以下の様な{{}}のとじ忘れのtemplateがあるとする。

hello.j2

hello
hello
hello
hello
hello {{name}
hello
hello
hello
hello

対抗馬(?)になりそうなのはj2cliなのでこのコマンドとの比較をすることにする。

$ pip install j2cli
$ cat data.json
{"name": "world"}

$ j2 hello.j2 data.json
Traceback (most recent call last):
  File "$HOME/venvs/my/bin/j2", line 11, in <module>
    sys.exit(main())
  File "$HOME/venvs/my/lib/python3.7/site-packages/j2cli/cli.py", line 175, in main
    sys.argv[1:]
  File "$HOME/venvs/my/lib/python3.7/site-packages/j2cli/cli.py", line 155, in render_command
    result = renderer.render(args.template, context)
...
  File "$HOME/venvs/my/lib/python3.7/site-packages/jinja2/lexer.py", line 683, in tokeniter
    filename)
jinja2.exceptions.TemplateSyntaxError: unexpected '}'

長ったらしいエラー。微妙な感じ。一方こちらで作ったコマンドは以下の様な出力を返してくれる。

$ kamidana hello.j2 --data data.json
------------------------------------------------------------
exception: jinja2.exceptions.TemplateSyntaxError
message: unexpected '}'
where: hello.j2
------------------------------------------------------------
    2: hello
    3: hello
    4: hello
->  5: hello {{name}
    6: hello
    7: hello
    8: hello

エラー行を中心に3行ずつ余分に表示してくれる(ちなみに元のtemplate(hello.j2)に無駄にhelloの文字列を追加したのはこの上下3行を見せるため)。

実際には->のカーソルが存在する行はANSI-Colorで黄色にハイライトされる(冒頭にあった画像がそれ)。

エラーの例その2

今度はファイルが見つからなかった場合の話。

# xxxxxx.j2 なんてファイル存在しない
$ kamidana xxxxxx.j2 data.json
------------------------------------------------------------
exception: jinja2.exceptions.TemplateNotFound
message: [Errno 2] No such file or directory: 'xxxxxx.j2'
where: None
------------------------------------------------------------
Traceback (most recent call last):
  File "$HOME/venvs/my/kamidana/kamidana/debug/__init__.py", line 10, in error_handler
    yield
  File "$HOME/venvs/my/kamidana/kamidana/commands/onefile.py", line 60, in main
    driver.run(args.template, args.dst)
  File "$HOME/venvs/my/kamidana/kamidana/driver.py", line 59, in run
    template = self.load(src)
jinja2.exceptions.TemplateNotFound: [Errno 2] No such file or directory: 'xxxxxx.j2'

ちなみに過去のエラーの形式(一行だけの表示)に戻したい場合には --quietを付ければ良い。

$ kamidana xxxxxx.j2 -d data.json --quiet
TemplateNotFound: [Errno 2] No such file or directory: 'xxxxxx.j2'

元々の生のtracebackをみたい場合には--debugも付けます。

$ kamidana xxxxxx.j2 -d data.json --quiet --debug
Traceback (most recent call last):
  File "$HOME/venvs/my/bin/kamidana", line 12, in <module>
    sys.exit(main())
  File "$HOME/venvs/my/kamidana/kamidana/commands/onefile.py", line 60, in main
    driver.run(args.template, args.dst)
...
  File "$HOME/venvs/my/kamidana/kamidana/loader.py", line 34, in load
    raise jinja2.TemplateNotFound(where, message=str(e)) from None
jinja2.exceptions.TemplateNotFound: [Errno 2] No such file or directory: 'xxxxxx.j2'

はい。