File size: 3,930 Bytes
4d0da28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import abc
import argparse
import inspect
from argparse import ArgumentParser

from pricePrediction import config


class ArgParseable(abc.ABC):

    @property
    @abc.abstractmethod
    def DESIRED_PARAMS_TO_ASK(self): #TOOD: Properties always apply to instances, not classes. to be modified
        raise NotImplementedError()

    @classmethod
    def fromTypeStrToType(cls, strType: str):
        if strType == "str":
            return str
        elif strType == "float":
            return float
        elif strType == "int":
            return int
        elif strType == "bool":
            return bool
        else:
            raise ValueError("Parser not recognized type: "+str(strType))

    @classmethod
    def fromDefaultStrToValue(cls, argname:str, typeFun:type, defaultStr: str): #Currently not used
        '''
        TO BE USED if  defaults in the docstring E.g.    :param int batch_size: Batch size. defaults to %(config.BATCH_SIZE)s

        :param argname:
        :param typeFun:
        :param defaultStr:
        :return:
        '''

        if defaultStr is None or defaultStr == "None":
            return None
        return typeFun(defaultStr)

    @classmethod
    def getArgsForParser(cls):
        from docstring_parser import parse
        docstring = cls.__init__.__doc__
        config_vars = vars(config)
        config_vars = { "config."+key: val for key,val in config_vars.items() }
        docstring = docstring%config_vars
        docstring = parse(docstring)

        signature = inspect.signature(cls.__init__)
        name_to_default = {
            k: v.default
            for k, v in signature.parameters.items()
            if v.default is not inspect.Parameter.empty
        }

        params = []
        for elem in docstring.params:
            if elem.arg_name in cls.DESIRED_PARAMS_TO_ASK:
                typeFun = cls.fromTypeStrToType(elem.type_name)
                # print(elem.default, elem.description)
                ### default = cls.fromDefaultStrToValue(elem.arg_name, typeFun, elem.default)
                default = name_to_default[elem.arg_name]
                params.append((elem.arg_name, typeFun, default, elem.description))
        return params

    # @classmethod
    # def _addParamToArgParse(cls, parser:ArgumentParser, paramTuple):
    #     name, typeFun, default, help= paramTuple
    #     if typeFun == bool:
    #         if default is True:
    #             name = "no_"+name
    #             help = "Deactivate "+help
    #         parser.add_argument("--" + name, help=help+" Default=%(default)s", action="store_true")
    #     else:
    #         parser.add_argument("--"+name, type=typeFun, help=help+" Default=%(default)s", default=default)
    #     return parser

    @classmethod
    def addParamsToArgParse(cls, parser: ArgumentParser):
        '''

        :param parser: Argparser to which methods will be added
        :return: the input parser but with added arguments
        '''
        for paramTuple in cls.getArgsForParser():
            name, typeFun, default, help= paramTuple
            if typeFun == bool:
                if default is True:
                    action="store_false"
                else:
                    action="store_true"
                help += " Action: "+action
                parser.add_argument("--" + name, help=help, action=action)
            else:
                parser.add_argument("--"+name, type=typeFun, help=help+" Default=%(default)s", default=default)
        return parser



class MyArgParser(argparse.ArgumentParser):
    def parse_args(self, args=None, namespace=None):
        args = super().parse_args(args=args, namespace=namespace)
        arg_groups = {}
        for group in self._action_groups:
            group_dict = {a.dest: getattr(args, a.dest, None) for a in group._group_actions}
            arg_groups[group.title] = group_dict

        return arg_groups