--- /dev/null
+# -*- coding: utf-8 -*-
+"""
+@author: Frank Brehm
+@contact: frank.brehm@pixelpark.com
+@copyright: © 2023 by Frank Brehm, Berlin
+@summary: A module containing some useful argparse actions.
+"""
+from __future__ import absolute_import
+
+# Standard modules
+import logging
+import argparse
+
+# Own modules
+from . import MAX_PORT_NUMBER
+
+from .xlate import XLATOR
+
+__version__ = '0.3.1'
+LOG = logging.getLogger(__name__)
+
+_ = XLATOR.gettext
+
+
+# =============================================================================
+class PortOptionAction(argparse.Action):
+
+ # -------------------------------------------------------------------------
+ def __init__(self, option_strings, what, *args, **kwargs):
+
+ self.what = what
+
+ super(PortOptionAction, self).__init__(option_strings=option_strings, *args, **kwargs)
+
+ # -------------------------------------------------------------------------
+ def __call__(self, parser, namespace, values, option_string=None):
+
+ if values is None:
+ setattr(namespace, self.dest, None)
+ return
+
+ try:
+ port = int(values)
+ except (ValueError, TypeError) as e:
+ msg = _("Value {v!r} for a {what} port is invalid:").format(v=values, what=self.what)
+ msg += ' ' + str(e)
+ raise argparse.ArgumentError(self, msg)
+
+ if port <= 0 or port > MAX_PORT_NUMBER:
+ msg = _("Value {v!r} for a {what} port must be greater than 0 and less than {max}.")
+ msg = msg.format(v=values, what=self.what, max=(MAX_PORT_NUMBER + 1))
+ raise argparse.ArgumentError(self, msg)
+
+ setattr(namespace, self.dest, port)
+
+# =============================================================================
+class NonNegativeItegerOptionAction(argparse.Action):
+
+ # -------------------------------------------------------------------------
+ def __call__(self, parser, namespace, value, option_string=None):
+
+ try:
+ val = int(value)
+ except Exception as e:
+ msg = _("Got a {c} for converting {v!r} into an integer value: {e}").format(
+ c=e.__class__.__name__, v=value, e=e)
+ raise argparse.ArgumentError(self, msg)
+
+ if val < 0:
+ msg = _("The option must not be negative (given: {}).").format(value)
+ raise argparse.ArgumentError(self, msg)
+
+ setattr(namespace, self.dest, val)
+
+
+# =============================================================================
+class LimitedIntegerOptionAction(argparse.Action):
+
+ # -------------------------------------------------------------------------
+ def __init__(self, option_strings, min_val=None, max_val=None, *args, **kwargs):
+
+ self._min_val = min_val
+ self._max_val = max_val
+
+ super(LimitedIntegerOptionAction, self).__init__(
+ option_strings=option_strings, *args, **kwargs)
+
+ # -------------------------------------------------------------------------
+ def __call__(self, parser, namespace, value, option_string=None):
+
+ val = 0
+ try:
+ val = int(value)
+ except Exception as e:
+ msg = _("Got a {c} for converting {v!r} into an integer value: {e}").format(
+ c=e.__class__.__name__, v=value, e=e)
+ raise argparse.ArgumentError(self, msg)
+
+ if self._min_val is not None:
+ if val < self._min_val:
+ msg = _("The option must be greater or equal to {m} (given: {v}).").format(
+ m=self._min_val, v=val)
+ raise argparse.ArgumentError(self, msg)
+
+ if self._max_val is not None:
+ if val > self._max_val:
+ msg = _("The option must be less or equal to {m} (given: {v}).").format(
+ m=self._max_val, v=val)
+ raise argparse.ArgumentError(self, msg)
+
+ setattr(namespace, self.dest, val)
+
+
+# =============================================================================
+class LimitedFloatOptionAction(argparse.Action):
+
+ # -------------------------------------------------------------------------
+ def __init__(self, option_strings, min_val=None, max_val=None, *args, **kwargs):
+
+ self._min_val = min_val
+ self._max_val = max_val
+
+ super(LimitedFloatOptionAction, self).__init__(
+ option_strings=option_strings, *args, **kwargs)
+
+ # -------------------------------------------------------------------------
+ def __call__(self, parser, namespace, value, option_string=None):
+
+ val = 0
+ try:
+ val = float(value)
+ except Exception as e:
+ msg = _("Got a {c} for converting {v!r} into a float value: {e}").format(
+ c=e.__class__.__name__, v=value, e=e)
+ raise argparse.ArgumentError(self, msg)
+
+ if self._min_val is not None and val < self._min_val:
+ msg = _("The option must be greater or equal to {m} (given: {v}).").format(
+ m=self._min_val, v=val)
+ raise argparse.ArgumentError(self, msg)
+
+ if self._max_val is not None and val > self._max_val:
+ msg = _("The option must be less or equal to {m} (given: {v}).").format(
+ m=self._max_val, v=val)
+ raise argparse.ArgumentError(self, msg)
+
+ setattr(namespace, self.dest, val)
+
+
+# =============================================================================
+if __name__ == "__main__":
+
+ pass
+
+# =============================================================================
+
+# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list