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

pipx/pipx_info: add parameter global #8793

Merged
merged 13 commits into from
Aug 26, 2024
3 changes: 3 additions & 0 deletions changelogs/fragments/8793-pipx-global.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
minor_changes:
- pipx - added parameter ``global`` to module (https://github.com/ansible-collections/community.general/pull/8793).
- pipx_info - added parameter ``global`` to module (https://github.com/ansible-collections/community.general/pull/8793).
37 changes: 20 additions & 17 deletions plugins/module_utils/pipx.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,29 @@


def pipx_runner(module, command, **kwargs):
arg_formats = dict(
state=fmt.as_map(_state_map),
name=fmt.as_list(),
name_source=fmt.as_func(fmt.unpack_args(lambda n, s: [s] if s else [n])),
install_apps=fmt.as_bool("--include-apps"),
install_deps=fmt.as_bool("--include-deps"),
inject_packages=fmt.as_list(),
force=fmt.as_bool("--force"),
include_injected=fmt.as_bool("--include-injected"),
index_url=fmt.as_opt_val('--index-url'),
python=fmt.as_opt_val('--python'),
system_site_packages=fmt.as_bool("--system-site-packages"),
_list=fmt.as_fixed(['list', '--include-injected', '--json']),
editable=fmt.as_bool("--editable"),
pip_args=fmt.as_opt_eq_val('--pip-args'),
suffix=fmt.as_opt_val('--suffix'),
)
arg_formats["global"] = fmt.as_bool("--global")

runner = CmdRunner(
module,
command=command,
arg_formats=dict(
state=fmt.as_map(_state_map),
name=fmt.as_list(),
name_source=fmt.as_func(fmt.unpack_args(lambda n, s: [s] if s else [n])),
install_apps=fmt.as_bool("--include-apps"),
install_deps=fmt.as_bool("--include-deps"),
inject_packages=fmt.as_list(),
force=fmt.as_bool("--force"),
include_injected=fmt.as_bool("--include-injected"),
index_url=fmt.as_opt_val('--index-url'),
python=fmt.as_opt_val('--python'),
system_site_packages=fmt.as_bool("--system-site-packages"),
_list=fmt.as_fixed(['list', '--include-injected', '--json']),
editable=fmt.as_bool("--editable"),
pip_args=fmt.as_opt_eq_val('--pip-args'),
suffix=fmt.as_opt_val('--suffix'),
),
arg_formats=arg_formats,
environ_update={'USE_EMOJI': '0'},
check_rc=True,
**kwargs
Expand Down
75 changes: 43 additions & 32 deletions plugins/modules/pipx.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,19 @@
suffix:
description:
- Optional suffix for virtual environment and executable names.
- "B(Warning): C(pipx) documentation states this is an B(experimental) feature subject to change."
- "B(Warning:) C(pipx) documentation states this is an B(experimental) feature subject to change."
type: str
version_added: 9.3.0
global:
description:
- The module will pass the C(--global) argument to C(pipx), to execute actions in global scope.
- The C(--global) is only available in C(pipx>=1.6.0), so make sure to have a compatible version when using this option.
Moreover, a nasty bug with C(--global) was fixed in C(pipx==1.7.0), so it is strongly recommended you used that version or newer.
type: bool
russoz marked this conversation as resolved.
Show resolved Hide resolved
default: false
version_added: 9.4.0
notes:
- This module requires C(pipx) version 0.16.2.1 or above.
- This module requires C(pipx) version 0.16.2.1 or above. From community.general 11.0.0 onwards, the module will require C(pipx>=1.7.0).
russoz marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth to at some point move some documentation / common code (corresponding argspec) to a docs fragment + module utils.

- Please note that C(pipx) requires Python 3.6 or above.
- This module does not install the C(pipx) python package, however that can be easily done with the module M(ansible.builtin.pip).
- This module does not require C(pipx) to be in the shell C(PATH), but it must be loadable by Python as a module.
Expand Down Expand Up @@ -191,26 +199,29 @@ def _make_name(name, suffix):

class PipX(StateModuleHelper):
output_params = ['name', 'source', 'index_url', 'force', 'installdeps']
argument_spec = dict(
state=dict(type='str', default='install',
choices=['present', 'absent', 'install', 'uninstall', 'uninstall_all',
'inject', 'upgrade', 'upgrade_all', 'reinstall', 'reinstall_all', 'latest']),
name=dict(type='str'),
source=dict(type='str'),
install_apps=dict(type='bool', default=False),
install_deps=dict(type='bool', default=False),
inject_packages=dict(type='list', elements='str'),
force=dict(type='bool', default=False),
include_injected=dict(type='bool', default=False),
index_url=dict(type='str'),
python=dict(type='str'),
system_site_packages=dict(type='bool', default=False),
executable=dict(type='path'),
editable=dict(type='bool', default=False),
pip_args=dict(type='str'),
suffix=dict(type='str'),
)
argument_spec["global"] = dict(type='bool', default=False)

module = dict(
argument_spec=dict(
state=dict(type='str', default='install',
choices=['present', 'absent', 'install', 'uninstall', 'uninstall_all',
'inject', 'upgrade', 'upgrade_all', 'reinstall', 'reinstall_all', 'latest']),
name=dict(type='str'),
source=dict(type='str'),
install_apps=dict(type='bool', default=False),
install_deps=dict(type='bool', default=False),
inject_packages=dict(type='list', elements='str'),
force=dict(type='bool', default=False),
include_injected=dict(type='bool', default=False),
index_url=dict(type='str'),
python=dict(type='str'),
system_site_packages=dict(type='bool', default=False),
executable=dict(type='path'),
editable=dict(type='bool', default=False),
pip_args=dict(type='str'),
suffix=dict(type='str'),
),
argument_spec=argument_spec,
required_if=[
('state', 'present', ['name']),
('state', 'install', ['name']),
Expand Down Expand Up @@ -279,8 +290,8 @@ def _capture_results(self, ctx):
def state_install(self):
if not self.vars.application or self.vars.force:
self.changed = True
args = 'state index_url install_deps force python system_site_packages editable pip_args suffix name_source'
with self.runner(args, check_mode_skip=True) as ctx:
args_order = 'state global index_url install_deps force python system_site_packages editable pip_args suffix name_source'
with self.runner(args_order, check_mode_skip=True) as ctx:
ctx.run(name_source=[self.vars.name, self.vars.source])
self._capture_results(ctx)

Expand All @@ -293,14 +304,14 @@ def state_upgrade(self):
if self.vars.force:
self.changed = True

with self.runner('state include_injected index_url force editable pip_args name', check_mode_skip=True) as ctx:
with self.runner('state global include_injected index_url force editable pip_args name', check_mode_skip=True) as ctx:
ctx.run(name=name)
self._capture_results(ctx)

def state_uninstall(self):
if self.vars.application:
name = _make_name(self.vars.name, self.vars.suffix)
with self.runner('state name', check_mode_skip=True) as ctx:
with self.runner('state global name', check_mode_skip=True) as ctx:
ctx.run(name=name)
self._capture_results(ctx)

Expand All @@ -311,7 +322,7 @@ def state_reinstall(self):
if not self.vars.application:
self.do_raise("Trying to reinstall a non-existent application: {0}".format(name))
self.changed = True
with self.runner('state name python', check_mode_skip=True) as ctx:
with self.runner('state global name python', check_mode_skip=True) as ctx:
ctx.run(name=name)
self._capture_results(ctx)

Expand All @@ -321,32 +332,32 @@ def state_inject(self):
self.do_raise("Trying to inject packages into a non-existent application: {0}".format(name))
if self.vars.force:
self.changed = True
with self.runner('state index_url install_apps install_deps force editable pip_args name inject_packages', check_mode_skip=True) as ctx:
with self.runner('state global index_url install_apps install_deps force editable pip_args name inject_packages', check_mode_skip=True) as ctx:
ctx.run(name=name)
self._capture_results(ctx)

def state_uninstall_all(self):
with self.runner('state', check_mode_skip=True) as ctx:
with self.runner('state global', check_mode_skip=True) as ctx:
ctx.run()
self._capture_results(ctx)

def state_reinstall_all(self):
with self.runner('state python', check_mode_skip=True) as ctx:
with self.runner('state global python', check_mode_skip=True) as ctx:
ctx.run()
self._capture_results(ctx)

def state_upgrade_all(self):
if self.vars.force:
self.changed = True
with self.runner('state include_injected force', check_mode_skip=True) as ctx:
with self.runner('state global include_injected force', check_mode_skip=True) as ctx:
ctx.run()
self._capture_results(ctx)

def state_latest(self):
if not self.vars.application or self.vars.force:
self.changed = True
args = 'state index_url install_deps force python system_site_packages editable pip_args suffix name_source'
with self.runner(args, check_mode_skip=True) as ctx:
args_order = 'state index_url install_deps force python system_site_packages editable pip_args suffix name_source'
with self.runner(args_order, check_mode_skip=True) as ctx:
ctx.run(state='install', name_source=[self.vars.name, self.vars.source])
self._capture_results(ctx)

Expand Down
30 changes: 20 additions & 10 deletions plugins/modules/pipx_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,22 @@
If not specified, the module will use C(python -m pipx) to run the tool,
using the same Python interpreter as ansible itself.
type: path
global:
description:
- The module will pass the C(--global) argument to C(pipx), to execute actions in global scope.
- The C(--global) is only available in C(pipx>=1.6.0), so make sure to have a compatible version when using this option.
Moreover, a nasty bug with C(--global) was fixed in C(pipx==1.7.0), so it is strongly recommended you used that version or newer.
type: bool
russoz marked this conversation as resolved.
Show resolved Hide resolved
default: false
version_added: 9.3.0
notes:
- This module requires C(pipx) version 0.16.2.1 or above. From community.general 11.0.0 onwards, the module will require C(pipx>=1.7.0).
- Please note that C(pipx) requires Python 3.6 or above.
- This module does not install the C(pipx) python package, however that can be easily done with the module M(ansible.builtin.pip).
- This module does not require C(pipx) to be in the shell C(PATH), but it must be loadable by Python as a module.
- >
This module will honor C(pipx) environment variables such as but not limited to E(PIPX_HOME) and E(PIPX_BIN_DIR)
passed using the R(environment Ansible keyword, playbooks_environment).
- This module requires C(pipx) version 0.16.2.1 or above.
- Please note that C(pipx) requires Python 3.6 or above.
- See also the C(pipx) documentation at U(https://pypa.github.io/pipx/).
author:
- "Alexei Znamensky (@russoz)"
Expand Down Expand Up @@ -140,14 +148,16 @@

class PipXInfo(ModuleHelper):
output_params = ['name']
argument_spec = dict(
name=dict(type='str'),
include_deps=dict(type='bool', default=False),
include_injected=dict(type='bool', default=False),
include_raw=dict(type='bool', default=False),
executable=dict(type='path'),
)
argument_spec["global"] = dict(type='bool', default=False)
module = dict(
argument_spec=dict(
name=dict(type='str'),
include_deps=dict(type='bool', default=False),
include_injected=dict(type='bool', default=False),
include_raw=dict(type='bool', default=False),
executable=dict(type='path'),
),
argument_spec=argument_spec,
supports_check_mode=True,
)
use_old_vardict = False
Expand Down Expand Up @@ -195,7 +205,7 @@ def process_list(rc, out, err):

return results

with self.runner('_list', output_process=process_list) as ctx:
with self.runner('_list global', output_process=process_list) as ctx:
self.vars.application = ctx.run(_list=1)
self._capture_results(ctx)

Expand Down
Loading