python: getopt: implement required flag on options and OptionParser
authorRob van der Linde <rob@catalyst.net.nz>
Thu, 5 Oct 2023 23:58:46 +0000 (12:58 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 24 Oct 2023 23:31:29 +0000 (23:31 +0000)
Signed-off-by: Rob van der Linde <rob@catalyst.net.nz>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/getopt.py

index 4fae3c07700ea086689eeb901672a30f4c84dc91..11af22f496e3f7770a41753c0d3050de4f74e95b 100644 (file)
@@ -73,6 +73,26 @@ def check_bytes(option, opt, value):
         raise optparse.OptionValueError(msg)
 
 
+class OptionMissingError(optparse.OptionValueError):
+    """One or more Options with required=True is missing."""
+
+    def __init__(self, options):
+        """Raised when required Options are missing from the command line.
+
+        :param options: list of 1 or more option
+        """
+        self.options = options
+
+    def __str__(self):
+        if len(self.options) == 1:
+            missing = self.options[0]
+            return f"Argument {missing} is required."
+        else:
+            options = sorted([str(option) for option in self.options])
+            missing = ", ".join(options)
+            return f"The arguments {missing} are required."
+
+
 class ValidationError(Exception):
     """ValidationError is the exception raised by validators.
 
@@ -93,7 +113,7 @@ class Validator(metaclass=ABCMeta):
 
 
 class Option(optparse.Option):
-    ATTRS = optparse.Option.ATTRS + ["validators"]
+    ATTRS = optparse.Option.ATTRS + ["required", "validators"]
     TYPES = optparse.Option.TYPES + ("bytes",)
     TYPE_CHECKER = copy(optparse.Option.TYPE_CHECKER)
     TYPE_CHECKER["bytes"] = check_bytes
@@ -136,6 +156,20 @@ class OptionParser(optparse.OptionParser):
                          conflict_handler, description, formatter,
                          add_help_option, prog, epilog)
 
+    def check_values(self, values, args):
+        """Loop through required options if value is missing raise exception."""
+        missing = []
+        for option in self._get_all_options():
+            if option.required:
+                value = getattr(values, option.dest)
+                if value is None:
+                    missing.append(option)
+
+        if missing:
+            raise OptionMissingError(missing)
+
+        return super().check_values(values, args)
+
 
 class SambaOptions(optparse.OptionGroup):
     """General Samba-related command line options."""