#!/usr/bin/python3
+# © Copyright 2021-2022, Scott Gasch
+
+"""Helpers for commandline argument parsing."""
+
import argparse
import datetime
import logging
from overrides import overrides
-
# This module is commonly used by others in here and should avoid
# taking any unnecessary dependencies back on them.
class ActionNoYes(argparse.Action):
- def __init__(
- self,
- option_strings,
- dest,
- default=None,
- required=False,
- help=None
- ):
+ """An argparse Action that allows for commandline arguments like this:
+
+ cfg.add_argument(
+ '--enable_the_thing',
+ action=ActionNoYes,
+ default=False,
+ help='Should we enable the thing?'
+ )
+
+ This creates cmdline arguments:
+
+ --enable_the_thing
+ --no_enable_the_thing
+
+ """
+
+ 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'
+ msg = 'Only single argument is allowed with NoYes action'
logger.critical(msg)
raise ValueError(msg)
opt = option_strings[0]
const=None,
default=default,
required=required,
- help=help
+ help=help,
)
@overrides
def __call__(self, parser, namespace, values, option_strings=None):
- if (
- option_strings.startswith('--no-') or
- option_strings.startswith('--no_')
- ):
+ if option_strings.startswith('--no-') or option_strings.startswith('--no_'):
setattr(namespace, self.dest, False)
else:
setattr(namespace, self.dest, True)
if isinstance(v, bool):
return v
from string_utils import to_bool
+
try:
return to_bool(v)
- except Exception:
- raise argparse.ArgumentTypeError(v)
+ except Exception as e:
+ raise argparse.ArgumentTypeError(v) from e
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)
+ logger.error(msg)
raise argparse.ArgumentTypeError(msg)
"""
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)
+ logger.error(msg)
raise argparse.ArgumentTypeError(msg)
if 0.0 <= n <= 100.0:
return n
msg = f"{num} is an invalid percentage; expected 0 <= n <= 100.0"
- logger.warning(msg)
+ logger.error(msg)
raise argparse.ArgumentTypeError(msg)
if os.path.exists(s):
return s
msg = f"{filename} was not found and is therefore invalid."
- logger.warning(msg)
+ logger.error(msg)
raise argparse.ArgumentTypeError(msg)
-ANYTHING-
"""
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)
+ logger.error(msg)
raise argparse.ArgumentTypeError(msg)
-ANYTHING-
"""
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)
+ logger.error(msg)
raise argparse.ArgumentTypeError(msg)
"""
from datetime_utils import parse_duration
+
try:
secs = parse_duration(txt)
- except Exception as e:
- raise argparse.ArgumentTypeError(e)
- finally:
return datetime.timedelta(seconds=secs)
+ except Exception as e:
+ logger.exception(e)
+ raise argparse.ArgumentTypeError(e) from e
if __name__ == '__main__':
import doctest
+
doctest.ELLIPSIS_MARKER = '-ANYTHING-'
doctest.testmod()