Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cumulative port 50049 & 50072 #55713

Merged
merged 9 commits into from Dec 20, 2019
7 changes: 5 additions & 2 deletions salt/states/module.py
Expand Up @@ -452,7 +452,7 @@ def _call_function(name, returner=None, **kwargs):

# func_args is initialized to a list of positional arguments that the function to be run accepts
func_args = argspec.args[:len(argspec.args or []) - len(argspec.defaults or [])]
arg_type, na_type, kw_type = [], {}, False
arg_type, kw_to_arg_type, na_type, kw_type = [], {}, {}, False
for funcset in reversed(kwargs.get('func_args') or []):
if not isinstance(funcset, dict):
# We are just receiving a list of args to the function to be run, so just append
Expand All @@ -463,13 +463,16 @@ def _call_function(name, returner=None, **kwargs):
# We are going to pass in a keyword argument. The trick here is to make certain
# that if we find that in the *args* list that we pass it there and not as a kwarg
if kwarg_key in func_args:
arg_type.append(funcset[kwarg_key])
kw_to_arg_type[kwarg_key] = funcset[kwarg_key]
continue
else:
# Otherwise, we're good and just go ahead and pass the keyword/value pair into
# the kwargs list to be run.
func_kw.update(funcset)
arg_type.reverse()
for arg in func_args:
if arg in kw_to_arg_type:
arg_type.append(kw_to_arg_type[arg])
_exp_prm = len(argspec.args or []) - len(argspec.defaults or [])
_passed_prm = len(arg_type)
missing = []
Expand Down
27 changes: 27 additions & 0 deletions tests/unit/states/test_module.py
Expand Up @@ -321,3 +321,30 @@ def test_module_run_missing_arg(self):
self.assertIn(comment, ret['comment'])
self.assertIn('world', ret['comment'])
self.assertIn('hello', ret['comment'])

def test_call_function_named_args(self):
'''
Test _call_function routine when params are named. Their position ordering should not matter.

:return:
'''
with patch.dict(module.__salt__,
{'testfunc': lambda a, b, c, *args, **kwargs: (a, b, c, args, kwargs)}, clear=True):
assert module._call_function('testfunc', func_args=[{'a': 1}, {'b': 2}, {'c': 3}]) == (1, 2, 3, (), {})
assert module._call_function('testfunc', func_args=[{'c': 3}, {'a': 1}, {'b': 2}]) == (1, 2, 3, (), {})

with patch.dict(module.__salt__,
{'testfunc': lambda c, a, b, *args, **kwargs: (a, b, c, args, kwargs)}, clear=True):
assert module._call_function('testfunc', func_args=[{'a': 1}, {'b': 2}, {'c': 3}]) == (1, 2, 3, (), {})
assert module._call_function('testfunc', func_args=[{'c': 3}, {'a': 1}, {'b': 2}]) == (1, 2, 3, (), {})

def test_call_function_ordered_args(self):
'''
Test _call_function routine when params are not named. Their position should matter.

:return:
'''
with patch.dict(module.__salt__,
{'testfunc': lambda a, b, c, *args, **kwargs: (a, b, c, args, kwargs)}, clear=True):
assert module._call_function('testfunc', func_args=[1, 2, 3]) == (1, 2, 3, (), {})
assert module._call_function('testfunc', func_args=[3, 1, 2]) == (3, 1, 2, (), {})