From 93a60696adaf28a9d63b0675e6cc0c4a071f4c0e Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Sun, 27 Dec 2020 17:11:13 +0800 Subject: [PATCH] pybind/mgr/mgr_module: drop arg parameter from CLICommand constructor Signed-off-by: Kefu Chai --- src/pybind/mgr/mgr_module.py | 104 ++++++++++++----------------------- 1 file changed, 36 insertions(+), 68 deletions(-) diff --git a/src/pybind/mgr/mgr_module.py b/src/pybind/mgr/mgr_module.py index 85124d6d7183d..48c1f894c1b4d 100644 --- a/src/pybind/mgr/mgr_module.py +++ b/src/pybind/mgr/mgr_module.py @@ -300,59 +300,46 @@ class CRUSHMap(ceph_module.BasePyCRUSH): class CLICommand(object): COMMANDS = {} # type: Dict[str, CLICommand] - def __init__(self, prefix, args="", desc="", perm="rw"): + def __init__(self, prefix, desc="", perm="rw"): self.prefix = prefix - self.args_dict = {} self.desc = desc self.perm = perm self.func = None # type: Optional[Callable] - self.args = args - self.args_dict = self._parse_args(args) self.arg_spec = {} # type: Dict[str, Any] self.first_default = -1 KNOWN_ARGS = '_', 'self', 'mgr', 'inbuf', 'return' - @staticmethod - def _parse_args(args): - if not args: - return {} - args_dict = {} - for arg in args.split(" "): - arg_desc = arg.strip().split(",") - arg_d = {} - for kv in arg_desc: - k, v = kv.split("=") - if k != "name": - arg_d[k] = v - else: - args_dict[v] = arg_d - return args_dict - def __call__(self, func): self.func = func if not self.desc: self.desc = inspect.getdoc(func) - if not self.args_dict: - full_argspec = inspect.getfullargspec(func) - self.arg_spec = full_argspec.annotations - for arg in full_argspec.args: - assert arg in CLICommand.KNOWN_ARGS or arg in self.arg_spec, \ - f"'{arg}' is not annotated for {func}: {full_argspec}" - self.args = ' '.join(CephArgtype.to_argdesc(tp, dict(name=name)) - for name, tp in self.arg_spec) + full_argspec = inspect.getfullargspec(func) + self.arg_spec = full_argspec.annotations + self.first_default = len(self.arg_spec) + if full_argspec.defaults: + self.first_default -= len(full_argspec.defaults) + args = [] + for index, arg in enumerate(full_argspec.args): + if arg in CLICommand.KNOWN_ARGS: + continue + assert arg in self.arg_spec, \ + f"'{arg}' is not annotated for {f}: {full_argspec}" + has_default = index >= self.first_default + args.append(CephArgtype.to_argdesc(self.arg_spec[arg], + dict(name=arg), + has_default)) + self.args = ' '.join(CephArgtype.to_argdesc(tp, dict(name=name)) + for name, tp in self.arg_spec) self.COMMANDS[self.prefix] = self return self.func - def _is_arg_key(self, k): - return k in self.args_dict or k in self.arg_spec - def _get_arg_value(self, kwargs_switch, key, val): def start_kwargs(): if isinstance(val, str) and '=' in val: k, v = val.split('=', 1) - if self._is_arg_key(k): + if k in self.arg_spec: return True else: return False @@ -365,17 +352,6 @@ class CLICommand(object): k, v = key, val return kwargs_switch, k.replace('-', '_'), v - def _collect_args_by_argdesc(self, cmd_dict): - kwargs = {} - kwargs_switch = False - for a, d in self.args_dict.items(): - if 'req' in d and d['req'] == "false" and a not in cmd_dict: - continue - kwargs_switch, k, v = self._get_arg_value(kwargs_switch, - a, cmd_dict[a]) - kwargs[k] = v - return kwargs - def _collect_args_by_argspec(self, cmd_dict): kwargs = {} kwargs_switch = False @@ -393,10 +369,7 @@ class CLICommand(object): return kwargs def call(self, mgr, cmd_dict, inbuf): - if self.args_dict: - kwargs = self._collect_args_by_argdesc(cmd_dict) - else: - kwargs = self._collect_args_by_argspec(cmd_dict) + kwargs = self._collect_args_by_argspec(cmd_dict) if inbuf: kwargs['inbuf'] = inbuf assert self.func @@ -414,12 +387,12 @@ class CLICommand(object): return [cmd.dump_cmd() for cmd in cls.COMMANDS.values()] -def CLIReadCommand(prefix, args=""): - return CLICommand(prefix, args, "r") +def CLIReadCommand(prefix): + return CLICommand(prefix, "r") -def CLIWriteCommand(prefix, args=""): - return CLICommand(prefix, args, "w") +def CLIWriteCommand(prefix): + return CLICommand(prefix, "w") def CLICheckNonemptyFileInput(func): @@ -493,19 +466,21 @@ class Command(dict): self, prefix, handler, - args=None, perm="rw", - desc=None, poll=False, ): - super(Command, self).__init__( - cmd=prefix + (' ' + args if args else ''), - perm=perm, - poll=poll) + super().__init__(perm=perm, + poll=poll) self.prefix = prefix - self.args = args self.handler = handler - self['desc'] = inspect.getdoc(self.handler) + + @staticmethod + def returns_command_result(instance, f): + @functools.wraps(f) + def wrapper(mgr, *args, **kwargs): + retval, stdout, stderr = f(instance or mgr, *args, **kwargs) + return HandleCommandResult(retval, stdout, stderr) + return wrapper def register(self, instance=False): """ @@ -515,15 +490,8 @@ class Command(dict): It also uses HandleCommandResult helper to return a wrapped a tuple of 3 items. """ - return CLICommand( - prefix=self.prefix, - args=self.args, - desc=self['desc'], - perm=self['perm'] - )( - func=lambda mgr, *args, **kwargs: HandleCommandResult(*self.handler( - *((instance or mgr,) + args), **kwargs)) - ) + cmd = CLICommand(prefix=self.prefix, perm=self['perm']) + return cmd(self.returns_command_result(instance, self.handler)) class CPlusPlusHandler(logging.Handler): -- 2.39.5