packageを指定してのgoコードの生成に対するgofmt(goimports)について
おそらくニッチな話になってしまっているけれど。メモ。
はじめに
goawayを使ってコード生成をしたときの典型的なコードの利用方法は以下の様な形になる。
$ python myscript.py --package=github.com/podhmo/myscript --position=. # 実際にGOPATHに対応した位置に生成したい場合には --positionを外す # python myscript.py --package=github.com/podhmo/myscript
ここで生成されるファイルのパスはpythonスクリプトに委ねられる。一方で生成されるファイルに対してgofmtやgoimportsを適用したい。 解決策は2つ
今回は後者について考えてみた
典型的なコード
goを生成する典型的なコードは以下の様な感じになる。
import logging from goaway import get_repository def run(package_path, position): r = get_repository() package = r.package(package_path) f = package.file("person.go") person = f.struct("person") person.define_field("name", f.string) f = package.file("group.go") group = f.struct("group") group.define_field("name", f.string) group.define_field("members", person.slice) d = r.resolve_package_path(position, package) r.emitter.emit_package(package, d=d) def main(): import argparse parser = argparse.ArgumentParser() parser.add_argument("--package", default=None) parser.add_argument("--position", default=None) args = parser.parse_args() logging.basicConfig(level=logging.INFO) run(args.package, args.position) if __name__ == "__main__": main()
これは実行すると以下の様なperson.goとgroup.goを生成する。
$ python main.py --package="github.com/podhmo/goaway/onemit" --position=. INFO:goaway.emitter:write: ./onemit/person.go INFO:goaway.emitter:write: ./onemit/group.go
person.go
package onemit type person struct { name string }
group.go
package onemit type group struct { name string members []person }
このpythonに委ねられて生成されるgoのファイルにどうやってgofmt(goimports)を適用しようかという話。
on emit hook
とりあえず雑な対応としてonemitというhookを取るようにした。
@@ -2,6 +2,10 @@ from goaway import get_repository +def onemit(f, fname): + print("gofmt -w {}".format(fname)) + + def run(package_path, position): r = get_repository() @@ -17,7 +21,7 @@ group.define_field("members", person.slice) d = r.resolve_package_path(position, package) - r.emitter.emit_package(package, d=d) + r.emitter.emit_package(package, d=d, onemit=onemit) def main():
onemitのhookでは生成されるパス名が手に入るのでここでおもむろにgofmtを実行するコードをprintしてあげるようにする。 そして以下の様な感じでリダイレクトした結果をbashなどで実行して適用する。
$ python main.py --package="github.com/podhmo/goaway/onemit" --position=. > fmt.sh INFO:goaway.emitter:write: ./onemit/person.go INFO:goaway.emitter:write: ./onemit/group.go $ bash -x fmt.sh + gofmt -w ./onemit/person.go + gofmt -w ./onemit/group.go
hookのところでsubprocessを作っても良いけれど。この方が楽な気がした。