diff --git a/changelogs/fragments/8415-cmd-runner-stack.yml b/changelogs/fragments/8415-cmd-runner-stack.yml new file mode 100644 index 0000000000..555683e057 --- /dev/null +++ b/changelogs/fragments/8415-cmd-runner-stack.yml @@ -0,0 +1,2 @@ +minor_changes: + - cmd_runner module utils - add decorator ``cmd_runner_fmt.stack`` (https://github.com/ansible-collections/community.general/pull/8415). diff --git a/plugins/module_utils/cmd_runner.py b/plugins/module_utils/cmd_runner.py index 2bf2b32e8c..aab654f76f 100644 --- a/plugins/module_utils/cmd_runner.py +++ b/plugins/module_utils/cmd_runner.py @@ -94,13 +94,23 @@ class _ArgFormat(object): self.ignore_none = ignore_none self.ignore_missing_value = ignore_missing_value - def __call__(self, value, ctx_ignore_none): + def __call__(self, value, ctx_ignore_none=True): ignore_none = self.ignore_none if self.ignore_none is not None else ctx_ignore_none if value is None and ignore_none: return [] f = self.func return [str(x) for x in f(value)] + def __str__(self): + return "".format( + self.func, + self.ignore_none, + self.ignore_missing_value, + ) + + def __repr__(self): + return str(self) + class _Format(object): @staticmethod @@ -184,6 +194,19 @@ class _Format(object): return func(**v) return wrapper + @staticmethod + def stack(fmt): + @wraps(fmt) + def wrapper(*args, **kwargs): + new_func = fmt(ignore_none=True, *args, **kwargs) + + def stacking(value): + stack = [new_func(v) for v in value if v] + stack = [x for args in stack for x in args] + return stack + return _ArgFormat(stacking, ignore_none=True) + return wrapper + class CmdRunner(object): """ diff --git a/tests/unit/plugins/module_utils/test_cmd_runner.py b/tests/unit/plugins/module_utils/test_cmd_runner.py index 6816afb34c..fcdffe7d2c 100644 --- a/tests/unit/plugins/module_utils/test_cmd_runner.py +++ b/tests/unit/plugins/module_utils/test_cmd_runner.py @@ -47,6 +47,9 @@ TC_FORMATS = dict( simple_fixed_false=(partial(cmd_runner_fmt.as_fixed, ["--always-here", "--forever"]), False, ["--always-here", "--forever"], None), simple_fixed_none=(partial(cmd_runner_fmt.as_fixed, ["--always-here", "--forever"]), None, ["--always-here", "--forever"], None), simple_fixed_str=(partial(cmd_runner_fmt.as_fixed, ["--always-here", "--forever"]), "something", ["--always-here", "--forever"], None), + stack_optval__str=(partial(cmd_runner_fmt.stack(cmd_runner_fmt.as_optval), "-t"), ["potatoes", "bananas"], ["-tpotatoes", "-tbananas"], None), + stack_opt_val__str=(partial(cmd_runner_fmt.stack(cmd_runner_fmt.as_opt_val), "-t"), ["potatoes", "bananas"], ["-t", "potatoes", "-t", "bananas"], None), + stack_opt_eq_val__int=(partial(cmd_runner_fmt.stack(cmd_runner_fmt.as_opt_eq_val), "--answer"), [42, 17], ["--answer=42", "--answer=17"], None), ) if tuple(version_info) >= (3, 1): from collections import OrderedDict @@ -67,7 +70,7 @@ TC_FORMATS_IDS = sorted(TC_FORMATS.keys()) def test_arg_format(func, value, expected, exception): fmt_func = func() try: - actual = fmt_func(value, ctx_ignore_none=True) + actual = fmt_func(value) print("formatted string = {0}".format(actual)) assert actual == expected, "actual = {0}".format(actual) except Exception as e: