Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/65870.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added extra_args functionality to pip.uninstall module function
39 changes: 39 additions & 0 deletions salt/modules/pip.py
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,7 @@ def uninstall(
cwd=None,
saltenv="base",
use_vt=False,
extra_args=None,
):
"""
Uninstall packages individually or from a pip requirements file
Expand Down Expand Up @@ -1100,6 +1101,26 @@ def uninstall(
use_vt
Use VT terminal emulation (see output while installing)

extra_args
Comment thread
twangboy marked this conversation as resolved.
pip keyword and positional arguments not yet implemented in salt

.. code-block:: yaml

salt '*' pip.install pandas extra_args="[{'--latest-pip-kwarg':'param'}, '--latest-pip-arg']"

Will be translated into the following pip command:

.. code-block:: bash

pip install pandas --latest-pip-kwarg param --latest-pip-arg

.. warning::

If unsupported options are passed here that are not supported in a
minion's version of pip, a `No such option error` will be thrown.

.. versionadded:: 3008.0

CLI Example:

.. code-block:: bash
Expand Down Expand Up @@ -1170,6 +1191,24 @@ def uninstall(
pass
cmd.extend(pkgs)

if extra_args:
# These are arguments from the latest version of pip that
# have not yet been implemented in salt
for arg in extra_args:
# It is a keyword argument
if isinstance(arg, dict):
# There will only ever be one item in this dictionary
key, val = arg.popitem()
# Don't allow any recursion into keyword arg definitions
# Don't allow multiple definitions of a keyword
if isinstance(val, (dict, list)):
raise TypeError(f"Too many levels in: {key}")
# This is a a normal one-to-one keyword argument
cmd.extend([key, val])
# It is a positional argument, append it to the list
else:
cmd.append(arg)

cmd_kwargs = dict(
python_shell=False, runas=user, cwd=cwd, saltenv=saltenv, use_vt=use_vt
)
Expand Down
46 changes: 46 additions & 0 deletions tests/pytests/unit/modules/test_pip.py
Original file line number Diff line number Diff line change
Expand Up @@ -1355,6 +1355,52 @@ def test_uninstall_timeout_argument_in_resulting_command(python_binary):
pytest.raises(ValueError, pip.uninstall, pkg, timeout="a")


def test_uninstall_extra_args_arguments_in_resulting_command(python_binary):
pkg = "pep8"
mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
with patch.dict(pip.__salt__, {"cmd.run_all": mock}):
pip.uninstall(
pkg, extra_args=[{"--latest-pip-kwarg": "param"}, "--latest-pip-arg"]
)
expected = [
*python_binary,
"uninstall",
"-y",
pkg,
"--latest-pip-kwarg",
"param",
"--latest-pip-arg",
]
mock.assert_called_with(
expected,
saltenv="base",
cwd=None,
runas=None,
use_vt=False,
python_shell=False,
)


def test_uninstall_extra_args_arguments_recursion_error():
pkg = "pep8"
mock = MagicMock(return_value={"retcode": 0, "stdout": ""})
with patch.dict(pip.__salt__, {"cmd.run_all": mock}):

pytest.raises(
TypeError,
lambda: pip.uninstall(
pkg, extra_args=[{"--latest-pip-kwarg": ["param1", "param2"]}]
),
)

pytest.raises(
TypeError,
lambda: pip.uninstall(
pkg, extra_args=[{"--latest-pip-kwarg": [{"--too-deep": dict()}]}]
),
)


def test_freeze_command(python_binary):
expected = [*python_binary, "freeze"]
eggs = [
Expand Down
Loading