docopt main template

docopt用のメイン関数のテンプレートを作成した。以下のdocoptのライブテンプレートを登録しておくと、コマンドラインパーサーを書くのが全く苦にならなくなるので、行なっとこう。 tf_argを追加している。docoptは型チェックがなく、複雑なオプションだとどこのフラグの設定が間違っているのかがわかりにくいので、エラーメッセージにフラグの情報を追加する物だ。 コピペとpycharmのlive template用のものを作成した。

for copy and paste

#! /usr/bin/env python3
# encoding: utf-8

"""{f}\n
Usage:
    {f}
    {f} <str> <int> <path> <list>...
    {f} -h | --help

Options:
    <str>                    str arg
    <int>                    int arg
    <path>                   path arg
    -h --help                Show this screen and exit.
"""
from docopt import docopt
from pathlib import Path
from typing import TypeVar


class DocArgs:
    A = TypeVar("A", str, Path, int, float, bool, list)

    def __init__(self, argd: dict):
        self.argd = argd

    def __call__(self, value_type: A, flag: str) -> A:
        """
        transformer from docopt option string to another class
        :param value_type: ex) int, float32, etc
        :param flag:
        :return:
        """
        try:
            print(f" v is {flag}")
            print(value_type, type(value_type(self.argd[flag])))
            arg = value_type(self.argd[flag])
            if isinstance(arg, list):
                inner_type = value_type.__args__[0]
                arg = [inner_type(z) for z in arg]
            return arg
        except ValueError as e:
            print("check your args")
            raise e
    
    def __str__(self) -> str:
        return self.argd.__str__()
    

if __name__ == "__main__":
    args = DocArgs(docopt(__doc__.format(f=__file__, version='0.0.1')))
    print(args)
    arg_str = args(str, "<str>")
    arg_int = args(int, "<int>")
    arg_path = args(Path, "<path>")
    arg_list = args(list[int], "<list>")
    print(arg_str)
    print(arg_int)
    print(arg_path)
    print(arg_list)
    

pycharm live template

#! /usr/bin/env python3
# encoding: utf-8

"""{f}\n
$DISCRIPTION$
Usage:
    {f}
    {f} -h | --help

Options:
    -h --help                Show this screen and exit.
"""
from docopt import docopt
from pathlib import Path
from typing import TypeVar


class DocArgs:
    A = TypeVar("A", str, Path, int, float, bool, list)

    def __init__(self, argd: dict):
        self.argd = argd

    def __call__(self, value_type: A, flag: str) -> A:
        """
        transformer from docopt option string to another class
        :param value_type: ex) int, float32, etc
        :param flag:
        :return:
        """
        try:
            print(f" v is {flag}")
            print(value_type, type(value_type(self.argd[flag])))
            arg = value_type(self.argd[flag])
            if isinstance(arg, list):
                inner_type = value_type.__args__[0]
                arg = [inner_type(z) for z in arg]
            return arg
        except ValueError as e:
            print("check your args")
            raise e
    
    def __str__(self) -> str:
        return self.argd.__str__()


if __name__ == "__main__":
    args = DocArgs(docopt(__doc__.format(f=__file__, version='0.0.1')))