forked from ArduPilot/MethodicConfigurator
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathargparse_check_range.py
More file actions
70 lines (54 loc) · 2.42 KB
/
Copy pathargparse_check_range.py
File metadata and controls
70 lines (54 loc) · 2.42 KB
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
"""
Check the range of an Argparse parameter.
This file is part of ArduPilot Methodic Configurator. https://github.com/ArduPilot/MethodicConfigurator
SPDX-FileCopyrightText: 2024 Dmitriy Kovalev
SPDX-License-Identifier: Apache-2.0
https://gist.github.com/dmitriykovalev/2ab1aa33a8099ef2d514925d84aa89e7
"""
from argparse import Action, ArgumentError, ArgumentParser, Namespace
from collections.abc import Sequence
from operator import ge, gt, le, lt
from typing import Any, Union
from ardupilot_methodic_configurator import _
class CheckRange(Action):
"""Check if the Argparse argument value is within the specified range."""
def __init__(self, *args, **kwargs) -> None:
if "min" in kwargs and "inf" in kwargs:
raise ValueError(_("either min or inf, but not both"))
if "max" in kwargs and "sup" in kwargs:
raise ValueError(_("either max or sup, but not both"))
self.ops = {"inf": gt, "min": ge, "sup": lt, "max": le}
for name in self.ops:
if name in kwargs:
setattr(self, name, kwargs.pop(name))
super().__init__(*args, **kwargs)
def interval(self) -> str:
if hasattr(self, "min"):
_lo = f"[{self.min}" # pyright: ignore[reportAttributeAccessIssue]
elif hasattr(self, "inf"):
_lo = f"({self.inf}" # pyright: ignore[reportAttributeAccessIssue]
else:
_lo = "(-infinity"
if hasattr(self, "max"):
_up = f"{self.max}]" # pyright: ignore[reportAttributeAccessIssue]
elif hasattr(self, "sup"):
_up = f"{self.sup})" # pyright: ignore[reportAttributeAccessIssue]
else:
_up = "+infinity)"
msg = _("valid range: {_lo}, {_up}")
return msg.format(**locals())
def __call__(
self,
parser: ArgumentParser, # noqa: ARG002
namespace: Namespace,
values: Union[str, Sequence[Any], None],
option_string: Union[None, str] = None, # noqa: ARG002
) -> None:
if not isinstance(values, (int, float)):
raise ArgumentError(self, _("Value must be a number."))
for name, op in self.ops.items():
if hasattr(self, name):
check_value = getattr(self, name)
if check_value is not None and not op(values, check_value):
raise ArgumentError(self, self.interval())
setattr(namespace, self.dest, values)