summaryrefslogtreecommitdiff
path: root/argparse_utils.py
blob: 02db0f08e762e9a430c9f03f7ce08a4a0acdb7b6 (plain)
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
113
114
115
116
117
118
119
#!/usr/bin/python3

import argparse
import datetime
import logging
import os

logger = logging.getLogger(__name__)


class ActionNoYes(argparse.Action):
    def __init__(
            self,
            option_strings,
            dest,
            default=None,
            required=False,
            help=None
    ):
        if default is None:
            msg = 'You must provide a default with Yes/No action'
            logger.critical(msg)
            raise ValueError(msg)
        if len(option_strings) != 1:
            msg = 'Only single argument is allowed with YesNo action'
            logger.critical(msg)
            raise ValueError(msg)
        opt = option_strings[0]
        if not opt.startswith('--'):
            msg = 'Yes/No arguments must be prefixed with --'
            logger.critical(msg)
            raise ValueError(msg)

        opt = opt[2:]
        opts = ['--' + opt, '--no_' + opt]
        super().__init__(
            opts,
            dest,
            nargs=0,
            const=None,
            default=default,
            required=required,
            help=help
        )

    def __call__(self, parser, namespace, values, option_strings=None):
        if (
                option_strings.startswith('--no-') or
                option_strings.startswith('--no_')
        ):
            setattr(namespace, self.dest, False)
        else:
            setattr(namespace, self.dest, True)


def valid_bool(v):
    if isinstance(v, bool):
        return v
    from string_utils import to_bool
    return to_bool(v)


def valid_ip(ip: str) -> str:
    from string_utils import extract_ip_v4
    s = extract_ip_v4(ip.strip())
    if s is not None:
        return s
    msg = f"{ip} is an invalid IP address"
    logger.warning(msg)
    raise argparse.ArgumentTypeError(msg)


def valid_mac(mac: str) -> str:
    from string_utils import extract_mac_address
    s = extract_mac_address(mac)
    if s is not None:
        return s
    msg = f"{mac} is an invalid MAC address"
    logger.warning(msg)
    raise argparse.ArgumentTypeError(msg)


def valid_percentage(num: str) -> float:
    num = num.strip('%')
    n = float(num)
    if 0.0 <= n <= 100.0:
        return n
    msg = f"{num} is an invalid percentage; expected 0 <= n <= 100.0"
    logger.warning(msg)
    raise argparse.ArgumentTypeError(msg)


def valid_filename(filename: str) -> str:
    s = filename.strip()
    if os.path.exists(s):
        return s
    msg = f"{filename} was not found and is therefore invalid."
    logger.warning(msg)
    raise argparse.ArgumentTypeError(msg)


def valid_date(txt: str) -> datetime.date:
    from string_utils import to_date
    date = to_date(txt)
    if date is not None:
        return date
    msg = f'Cannot parse argument as a date: {txt}'
    logger.warning(msg)
    raise argparse.ArgumentTypeError(msg)


def valid_datetime(txt: str) -> datetime.datetime:
    from string_utils import to_datetime
    dt = to_datetime(txt)
    if dt is not None:
        return dt
    msg = f'Cannot parse argument as datetime: {txt}'
    logger.warning(msg)
    raise argparse.ArgumentTypeError(msg)