The branch, master has been updated via 50b8a2de2aa python: getopt: HostOptions and other option groups inherit from samba OptionGroup class via 7c389e19212 netcmd: auth policy: add OptionGroup classes for user, service and computer options via 0667708cef2 python: netcmd: make use of HostOptions for claims and sites commands via e1244ba304a python: getopt: Add HostOptions to avoid need to manually add -H via 0f3d6d80dab python: netcmd: make use of required flag on Option for claims commands via e60f3afcc5f python: getopt: implement required flag on options and OptionParser via 837e1d9fdad python: getopt: subclass OptionParser to populate option_class via 6943a58bff3 netcmd: tests: stop checking for ERROR prefix from CommandError via fb058e7f2ce python: netcmd: remove OptionError alias to OptionValueError via 14b21298687 python: netcmd: catch parent exception class OptParseError instead via f77064c8225 python: getopt: rename SambaOption to Option via d54f52b847f python: netcmd: parser class in getSamDB should set option_class via b7a1946d8b7 python: netcmd: fix import grouping and sorting in base first via 5f8c46d1dec python: netcmd: remove redundant Option subclass via 32032937ed9 python: netcmd: SUPPRESS_HELP constant has no effect here via a930456f0c9 python: netcmd: dbcheck: fix import grouping and order via 3a5a5cae3a6 python: netcmd: ntacl: fix import grouping and order via 90f7ad08b53 python: tests: fix some hidden tab characters in tests.py via 0f93e1d17f8 python: add docstrings to Validator and ValidationError via dc513a82a6a python: move Validator base class and ValidationError to getopt via 29c9991594f python: getopt: move validators logic to parent class via bdad257a312 netcmd: don't turn exception into CommandError in run_validators via 99c93c1e89e netcmd: PEP8: minor whitespace fix, file did not pass PEP8 via c3876242fdf netcmd: move comment above class to docstring via 8b575612975 netcmd: correctly pass Samba option class to OptionParser via 96959b72679 python: getopt: move SambaOption to the top of the file via c688e73358c python: getopt: correctly group and sort imports via 1f8b4913c60 python: getopt: update super calls to python3 style via e209b8d79c2 python: move comment for check_bytes to docstring via 22316fea335 python: PEP8 fixup whitespace in getopt.py first via 029e0457ccc netcmd: tests: make check_run and related methods classmethod for consistency via b543874abc3 tests: minor indentation and whitespace fixes from 7c8dea14da6 smbtorture: add test for fruit:validate_afpinfo option
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 50b8a2de2aadd94386fb0525bfc741867121c929 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Fri Oct 20 14:46:40 2023 +1300 python: getopt: HostOptions and other option groups inherit from samba OptionGroup class Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Wed Oct 25 00:31:37 UTC 2023 on atb-devel-224 commit 7c389e19212f76aaf9cba8ac8315742c7294e2c8 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Tue Oct 10 23:31:33 2023 +1300 netcmd: auth policy: add OptionGroup classes for user, service and computer options Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 0667708cef2e4375552860ae67ac24e6b0f593d0 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Fri Oct 6 15:49:27 2023 +1300 python: netcmd: make use of HostOptions for claims and sites commands Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit e1244ba304a2de598779f9fcf1307244f333ab65 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Fri Oct 6 15:47:43 2023 +1300 python: getopt: Add HostOptions to avoid need to manually add -H Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 0f3d6d80dab0be046663e8bac2357b20520c70e3 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Fri Oct 6 14:50:32 2023 +1300 python: netcmd: make use of required flag on Option for claims commands Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit e60f3afcc5fca7ec1d8aacfc7abf19009b3d831c Author: Rob van der Linde <r...@catalyst.net.nz> Date: Fri Oct 6 12:58:46 2023 +1300 python: getopt: implement required flag on options and OptionParser Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 837e1d9fdad79ea3a7fdce1232d8dd834f181a63 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 19 15:05:56 2023 +1300 python: getopt: subclass OptionParser to populate option_class The option_class needs to be set correctly for OptionGroups that use self.add_option Override OptionParser `__init__` to change the default Option class to the samba one. Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6943a58bff37c815aa993f74fbbbe2587a21202b Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 19 14:26:46 2023 +1300 netcmd: tests: stop checking for ERROR prefix from CommandError Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit fb058e7f2ce3878713af959e8e35d1991bde24ee Author: Rob van der Linde <r...@catalyst.net.nz> Date: Fri Oct 6 12:45:35 2023 +1300 python: netcmd: remove OptionError alias to OptionValueError The other methods in this file already raise optparse.OptionValueError directly, except for two older ones. They are using an alias which changes the name to OptionError, the confusing part about this is that optparse.OptionError actually does exist, so the incorrect alias needs to be removed. Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 14b2129868748d3732d5361e2b34f3a5a0a66ff2 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Fri Oct 6 12:39:30 2023 +1300 python: netcmd: catch parent exception class OptParseError instead This covers both OptionError and OptionValueError Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit f77064c8225c79d137e225e962d885e83e113d85 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 16:26:40 2023 +1300 python: getopt: rename SambaOption to Option * Nothing uses SambaOption directly, everything imports it through samba.netcmd.Option * Avoid an unnecessary rename on import Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit d54f52b847fe03b9e3946f25db51e4cc980bedfa Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 16:00:36 2023 +1300 python: netcmd: parser class in getSamDB should set option_class Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit b7a1946d8b750ed1fdd888317798d476be145051 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 15:52:54 2023 +1300 python: netcmd: fix import grouping and sorting in base first Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 5f8c46d1decd8aea12713cb471db25a7932706d8 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 15:22:58 2023 +1300 python: netcmd: remove redundant Option subclass Instead, just import SambaOption as Option, so all the existing commands don't need changing. Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 32032937ed905d5f5b9ac8ba94381e7cb03f443c Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 15:18:32 2023 +1300 python: netcmd: SUPPRESS_HELP constant has no effect here Where it is used, on a few options, the constant should be used directly instead. This means that in the following commit, the Option subclass of SambaOption can be removed, as it will become redundant. Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit a930456f0c9043ddfed216c0726046fb1ff8da43 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 15:13:45 2023 +1300 python: netcmd: dbcheck: fix import grouping and order Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 3a5a5cae3a688c0276ae1a50113907afff2e6b31 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 15:10:06 2023 +1300 python: netcmd: ntacl: fix import grouping and order Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 90f7ad08b536a47c9b35b238ab4eaeab0dd76681 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 14:47:46 2023 +1300 python: tests: fix some hidden tab characters in tests.py Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 0f93e1d17f8130180e039fcd1230737308a962ce Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 14:33:32 2023 +1300 python: add docstrings to Validator and ValidationError Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit dc513a82a6a2795b22820146ca583cbe169a7499 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 14:30:20 2023 +1300 python: move Validator base class and ValidationError to getopt It makes more sense for these to exist in the top package, because they are used by SambaOption. validators.py can still exist in netcmd, just not the base class and exception. Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 29c9991594f71c4fecc04f3d7701ab93e92ec7ab Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 14:17:01 2023 +1300 python: getopt: move validators logic to parent class Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit bdad257a31210e7d6195212bd051f1136854ce6f Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 14:03:14 2023 +1300 netcmd: don't turn exception into CommandError in run_validators It's the wrong place to do it. Instead, let it raise the original exception, capture it in _run, and call existing show_command_error method. Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 99c93c1e89e974e12793f305dc4f8f7812bf2574 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 13:47:11 2023 +1300 netcmd: PEP8: minor whitespace fix, file did not pass PEP8 Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit c3876242fdf56f1edfda790e1f52589bf95c0c24 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 13:42:14 2023 +1300 netcmd: move comment above class to docstring Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 8b575612975df853cf7718fb2c9dea3bbf064508 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 12:05:17 2023 +1300 netcmd: correctly pass Samba option class to OptionParser On OptionGroups it will set option_class and then this gets used by self.add_option Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 96959b72679f4a5cac1c5d300bb4013bd100fcfe Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 11:32:30 2023 +1300 python: getopt: move SambaOption to the top of the file This is needed for the next commit Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit c688e73358c465bdb44b36fbba2953bfa7931640 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 11:50:22 2023 +1300 python: getopt: correctly group and sort imports Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 1f8b4913c60efaa97bb56d97ab1fca0d2627ef3e Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 11:48:14 2023 +1300 python: getopt: update super calls to python3 style Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit e209b8d79c2f232ba668bfff79c8bda951895084 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 11:29:59 2023 +1300 python: move comment for check_bytes to docstring Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 22316fea3359a808031a550c6612811f3f816f80 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Thu Oct 5 11:27:40 2023 +1300 python: PEP8 fixup whitespace in getopt.py first Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 029e0457ccc78b0b9de01ede16c39c29d26a26b0 Author: Rob van der Linde <r...@catalyst.net.nz> Date: Mon Oct 2 18:32:29 2023 +1300 netcmd: tests: make check_run and related methods classmethod for consistency Before that only run_command was turned into a @classmethod, but not the other related methods which were left unchanged, this made it inconsistent. Some of these methods need to be called from setUpTestData so they really need to be @classmethod anyway. Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit b543874abc30e9c8dc042d70e29ab6598968bebd Author: Rob van der Linde <r...@catalyst.net.nz> Date: Mon Oct 2 18:27:39 2023 +1300 tests: minor indentation and whitespace fixes Signed-off-by: Rob van der Linde <r...@catalyst.net.nz> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> ----------------------------------------------------------------------- Summary of changes: python/samba/getopt.py | 244 +++++++++++++----- python/samba/netcmd/__init__.py | 62 ++--- python/samba/netcmd/dbcheck.py | 17 +- python/samba/netcmd/domain/auth/policy.py | 278 ++++++++++----------- python/samba/netcmd/domain/auth/silo.py | 53 ++-- python/samba/netcmd/domain/auth/silo_member.py | 44 ++-- python/samba/netcmd/domain/claim/claim_type.py | 59 ++--- python/samba/netcmd/domain/claim/value_type.py | 19 +- python/samba/netcmd/ntacl.py | 25 +- python/samba/netcmd/sites.py | 84 ++----- python/samba/netcmd/validators.py | 13 +- python/samba/tests/__init__.py | 35 +-- python/samba/tests/samba_tool/base.py | 17 +- .../samba/tests/samba_tool/domain_auth_policy.py | 146 +++++------ python/samba/tests/samba_tool/domain_auth_silo.py | 14 +- python/samba/tests/samba_tool/domain_claim.py | 16 +- source4/selftest/tests.py | 8 +- 17 files changed, 555 insertions(+), 579 deletions(-) Changeset truncated at 500 lines: diff --git a/python/samba/getopt.py b/python/samba/getopt.py index e9ff3de5b34..0935ed00d40 100644 --- a/python/samba/getopt.py +++ b/python/samba/getopt.py @@ -20,21 +20,181 @@ __docformat__ = "restructuredText" import optparse -from copy import copy import os +import sys +from abc import ABCMeta, abstractmethod +from copy import copy + from samba.credentials import ( Credentials, AUTO_USE_KERBEROS, DONT_USE_KERBEROS, MUST_USE_KERBEROS, ) -import sys from samba._glue import get_burnt_commandline -OptionError = optparse.OptionValueError + +def check_bytes(option, opt, value): + """Custom option type to allow the input of sizes using byte, kb, mb ... + + units, e.g. 2Gb, 4KiB ... + e.g. Option("--size", type="bytes", metavar="SIZE") + """ + + multipliers = {"B": 1, + "KB": 1024, + "MB": 1024 * 1024, + "GB": 1024 * 1024 * 1024} + + # strip out any spaces + v = value.replace(" ", "") + + # extract the numeric prefix + digits = "" + while v and v[0:1].isdigit() or v[0:1] == '.': + digits += v[0] + v = v[1:] + + try: + m = float(digits) + except ValueError: + msg = ("{0} option requires a numeric value, " + "with an optional unit suffix").format(opt) + raise optparse.OptionValueError(msg) + + # strip out the 'i' and convert to upper case so + # kib Kib kb KB are all equivalent + suffix = v.upper().replace("I", "") + try: + return m * multipliers[suffix] + except KeyError as k: + msg = ("{0} invalid suffix '{1}', " + "should be B, Kb, Mb or Gb").format(opt, v) + 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. + + Should be raised from the __call__ method of the Validator subclass. + """ + pass + + +class Validator(metaclass=ABCMeta): + """Base class for Validators used by SambaOption. + + Subclass this to make custom validators and implement __call__. + """ + + @abstractmethod + def __call__(self, field, value): + pass -class SambaOptions(optparse.OptionGroup): +class Option(optparse.Option): + ATTRS = optparse.Option.ATTRS + ["required", "validators"] + TYPES = optparse.Option.TYPES + ("bytes",) + TYPE_CHECKER = copy(optparse.Option.TYPE_CHECKER) + TYPE_CHECKER["bytes"] = check_bytes + + def run_validators(self, opt, value): + """Runs the list of validators on the current option.""" + validators = getattr(self, "validators") or [] + for validator in validators: + validator(opt, value) + + def convert_value(self, opt, value): + """Override convert_value to run validators just after. + + This can also be done in process() but there we would have to + replace the entire method. + """ + value = super().convert_value(opt, value) + self.run_validators(opt, value) + return value + + +class OptionParser(optparse.OptionParser): + """Samba OptionParser, adding support for required=True on Options.""" + + def __init__(self, + usage=None, + option_list=None, + option_class=Option, + version=None, + conflict_handler="error", + description=None, + formatter=None, + add_help_option=True, + prog=None, + epilog=None): + """ + Ensure that option_class defaults to the Samba one. + """ + super().__init__(usage, option_list, option_class, version, + 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 OptionGroup(optparse.OptionGroup): + """Samba OptionGroup base class. + + Provides a generic set_option method to be used as Option callback, + so that one doesn't need to be created for every available Option. + + Also overrides the add_option method, so it correctly initialises + the defaults on the OptionGroup. + """ + + def add_option(self, *args, **kwargs): + """Override add_option so it applies defaults during constructor.""" + opt = super().add_option(*args, **kwargs) + default = None if opt.default == optparse.NO_DEFAULT else opt.default + self.set_option(opt, opt.get_opt_string(), default, self.parser) + return opt + + def set_option(self, option, opt_str, arg, parser): + """Callback to set the attribute based on the Option dest name.""" + dest = option.dest or option._long_opts[0][2:].replace("-", "_") + setattr(self, dest, arg) + + +class SambaOptions(OptionGroup): """General Samba-related command line options.""" def __init__(self, parser): @@ -60,7 +220,7 @@ class SambaOptions(optparse.OptionGroup): sys.stderr.flush() from samba.param import LoadParm - optparse.OptionGroup.__init__(self, parser, "Samba Common Options") + super().__init__(parser, "Samba Common Options") self.add_option("-s", "--configfile", action="callback", type=str, metavar="FILE", help="Configuration file", callback=self._load_configfile) @@ -89,14 +249,16 @@ class SambaOptions(optparse.OptionGroup): try: self._lp.set('debug level', arg) except RuntimeError: - raise OptionError(f"invalid -d/--debug value: '{arg}'") + raise optparse.OptionValueError( + f"invalid -d/--debug value: '{arg}'") parser.values.debuglevel = arg def _set_realm(self, option, opt_str, arg, parser): try: self._lp.set('realm', arg) except RuntimeError: - raise OptionError(f"invalid --realm value: '{arg}'") + raise optparse.OptionValueError( + f"invalid --realm value: '{arg}'") self.realm = arg def _set_option(self, option, opt_str, arg, parser): @@ -125,15 +287,27 @@ class Samba3Options(SambaOptions): """General Samba-related command line options with an s3 param.""" def __init__(self, parser): - SambaOptions.__init__(self, parser) + super().__init__(parser) from samba.samba3 import param as s3param self._lp = s3param.get_context() -class VersionOptions(optparse.OptionGroup): +class HostOptions(OptionGroup): + """Command line options for connecting to target host or database.""" + + def __init__(self, parser): + super().__init__(parser, "Host Options") + + self.add_option("-H", "--URL", + help="LDB URL for database or target server", + type=str, metavar="URL", action="callback", + callback=self.set_option, dest="H") + + +class VersionOptions(OptionGroup): """Command line option for printing Samba version.""" def __init__(self, parser): - optparse.OptionGroup.__init__(self, parser, "Version Options") + super().__init__(parser, "Version Options") self.add_option("-V", "--version", action="callback", callback=self._display_version, help="Display version number") @@ -168,7 +342,7 @@ def parse_kerberos_arg(arg, opt_str): (opt_str, arg)) -class CredentialsOptions(optparse.OptionGroup): +class CredentialsOptions(OptionGroup): """Command line options for specifying credentials.""" def __init__(self, parser, special_name=None): @@ -181,7 +355,7 @@ class CredentialsOptions(optparse.OptionGroup): self.ask_for_password = True self.ipaddress = None self.machine_pass = False - optparse.OptionGroup.__init__(self, parser, self.section) + super().__init__(parser, self.section) self._add_option("--simple-bind-dn", metavar="DN", action="callback", callback=self._set_simple_bind_dn, type=str, help="DN to use for a simple bind") @@ -301,7 +475,7 @@ class CredentialsOptionsDouble(CredentialsOptions): """Command line options for specifying credentials of two servers.""" def __init__(self, parser): - CredentialsOptions.__init__(self, parser) + super().__init__(parser) self.no_pass2 = True self.add_option("--simple-bind-dn2", metavar="DN2", action="callback", callback=self._set_simple_bind_dn2, type=str, @@ -363,47 +537,3 @@ class CredentialsOptionsDouble(CredentialsOptions): if self.no_pass2: self.creds2.set_cmdline_callbacks() return self.creds2 - -# Custom option type to allow the input of sizes using byte, kb, mb ... -# units, e.g. 2Gb, 4KiB ... -# e.g. Option("--size", type="bytes", metavar="SIZE") -# -def check_bytes(option, opt, value): - - multipliers = { - "B" : 1, - "KB" : 1024, - "MB" : 1024 * 1024, - "GB" : 1024 * 1024 * 1024} - - # strip out any spaces - v = value.replace(" ", "") - - # extract the numeric prefix - digits = "" - while v and v[0:1].isdigit() or v[0:1] == '.': - digits += v[0] - v = v[1:] - - try: - m = float(digits) - except ValueError: - msg = ("{0} option requires a numeric value, " - "with an optional unit suffix").format(opt) - raise optparse.OptionValueError(msg) - - - # strip out the 'i' and convert to upper case so - # kib Kib kb KB are all equivalent - suffix = v.upper().replace("I", "") - try: - return m * multipliers[suffix] - except KeyError as k: - msg = ("{0} invalid suffix '{1}', " - "should be B, Kb, Mb or Gb").format(opt, v) - raise optparse.OptionValueError(msg) - -class SambaOption(optparse.Option): - TYPES = optparse.Option.TYPES + ("bytes",) - TYPE_CHECKER = copy(optparse.Option.TYPE_CHECKER) - TYPE_CHECKER["bytes"] = check_bytes diff --git a/python/samba/netcmd/__init__.py b/python/samba/netcmd/__init__.py index bb3736e2117..31541a98347 100644 --- a/python/samba/netcmd/__init__.py +++ b/python/samba/netcmd/__init__.py @@ -26,47 +26,16 @@ import samba from ldb import ERR_INVALID_CREDENTIALS, LdbError from samba import colour from samba.auth import system_session -from samba.getopt import SambaOption, OptionError +from samba.getopt import Option, OptionParser from samba.logger import get_samba_logger from samba.samdb import SamDB from .encoders import JSONEncoder -from .validators import ValidationError - - -class Option(SambaOption): - ATTRS = SambaOption.ATTRS + ["validators"] - SUPPRESS_HELP = optparse.SUPPRESS_HELP - - def run_validators(self, opt, value): - """Runs the list of validators on the current option. - - If the validator raises ValidationError, turn that into CommandError - which gives nicer output. - """ - validators = getattr(self, "validators") or [] - - for validator in validators: - try: - validator(opt, value) - except ValidationError as e: - raise CommandError(e) - - def convert_value(self, opt, value): - """Override convert_value to run validators just after. - - This can also be done in process() but there we would have to - replace the entire method. - """ - value = super().convert_value(opt, value) - self.run_validators(opt, value) - return value - - -# This help formatter does text wrapping and preserves newlines class PlainHelpFormatter(optparse.IndentedHelpFormatter): + """This help formatter does text wrapping and preserves newlines.""" + def format_description(self, description=""): desc_width = self.width - self.current_indent indent = " " * self.current_indent @@ -146,11 +115,11 @@ class Command(object): else: print(f"{err}{klass}: {msg} - {evalue}", file=self.errf) - def ldb_connect(self, ldap_url, sambaopts, credopts): + def ldb_connect(self, hostopts, sambaopts, credopts): """Helper to connect to Ldb database using command line opts.""" lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) - return SamDB(ldap_url, credentials=creds, + return SamDB(hostopts.H, credentials=creds, session_info=system_session(lp), lp=lp) def print_json(self, data): @@ -175,7 +144,7 @@ class Command(object): message = "uncaught exception" force_traceback = True - if isinstance(e, OptionError): + if isinstance(e, optparse.OptParseError): print(evalue, file=self.errf) self.usage() force_traceback = False @@ -211,11 +180,13 @@ class Command(object): traceback.print_tb(etraceback, file=self.errf) def _create_parser(self, prog=None, epilog=None): - parser = optparse.OptionParser( + parser = OptionParser( usage=self.synopsis, description=self.full_description, formatter=PlainHelpFormatter(), - prog=prog, epilog=epilog) + prog=prog, + epilog=epilog, + option_class=Option) parser.add_options(self.takes_options) optiongroups = {} for name in sorted(self.takes_optiongroups.keys()): @@ -241,12 +212,19 @@ class Command(object): def _run(self, *argv): parser, optiongroups = self._create_parser(self.command_name) - opts, args = parser.parse_args(list(argv)) + + # Handle possible validation errors raised by parser + try: + opts, args = parser.parse_args(list(argv)) + except Exception as e: + self.show_command_error(e) + return -1 + # Filter out options from option groups kwargs = dict(opts.__dict__) for option_group in parser.option_groups: for option in option_group.option_list: - if option.dest is not None: + if option.dest is not None and option.dest in kwargs: del kwargs[option.dest] kwargs.update(optiongroups) @@ -338,7 +316,7 @@ class SuperCommand(Command): sub = self.subcommands[a] return sub._resolve(sub_path, *sub_args, outf=outf, errf=errf) - elif a in [ '--help', 'help', None, '-h', '-V', '--version' ]: + elif a in ['--help', 'help', None, '-h', '-V', '--version']: # we pass these to the leaf node. if a == 'help': a = '--help' diff --git a/python/samba/netcmd/dbcheck.py b/python/samba/netcmd/dbcheck.py index 4d5c79ff11b..657881b5eea 100644 --- a/python/samba/netcmd/dbcheck.py +++ b/python/samba/netcmd/dbcheck.py @@ -16,18 +16,17 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -import ldb +import optparse import sys + +import ldb import samba.getopt as options +from samba import colour from samba.auth import system_session -from samba.samdb import SamDB -from samba.netcmd import ( - Command, - CommandError, - Option -) from samba.dbchecker import dbcheck -from samba import colour +from samba.samdb import SamDB + +from . import Command, CommandError, Option class cmd_dbcheck(Command): @@ -86,7 +85,7 @@ class cmd_dbcheck(Command): type=str, metavar="URL", dest="H"), Option("--selftest-check-expired-tombstones", dest="selftest_check_expired_tombstones", default=False, action="store_true", - help=Option.SUPPRESS_HELP), # This is only used by tests + help=optparse.SUPPRESS_HELP), # This is only used by tests ] def run(self, DN=None, H=None, verbose=False, fix=False, yes=False, diff --git a/python/samba/netcmd/domain/auth/policy.py b/python/samba/netcmd/domain/auth/policy.py index faf81cca616..6ee85602907 100644 --- a/python/samba/netcmd/domain/auth/policy.py +++ b/python/samba/netcmd/domain/auth/policy.py @@ -29,6 +29,75 @@ from samba.netcmd.domain.models.exceptions import ModelError from samba.netcmd.validators import Range +class UserOptions(options.OptionGroup): + """User options used by policy create and policy modify commands.""" + + def __init__(self, parser): -- Samba Shared Repository