ansible-core 2.17.6__py3-none-any.whl → 2.17.7rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ansible-core might be problematic. Click here for more details.

@@ -139,6 +139,7 @@ class TaskExecutor:
139
139
  if 'unreachable' in item and item['unreachable']:
140
140
  item_ignore_unreachable = item.pop('_ansible_ignore_unreachable')
141
141
  if not res.get('unreachable'):
142
+ res['unreachable'] = True
142
143
  self._task.ignore_unreachable = item_ignore_unreachable
143
144
  elif self._task.ignore_unreachable and not item_ignore_unreachable:
144
145
  self._task.ignore_unreachable = item_ignore_unreachable
@@ -17,6 +17,6 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- __version__ = '2.17.6'
20
+ __version__ = '2.17.7rc1'
21
21
  __author__ = 'Ansible, Inc.'
22
22
  __codename__ = "Gallows Pole"
@@ -7,12 +7,6 @@ import os
7
7
  import stat
8
8
  import re
9
9
 
10
- try:
11
- import selinux # pylint: disable=unused-import
12
- HAVE_SELINUX = True
13
- except ImportError:
14
- HAVE_SELINUX = False
15
-
16
10
 
17
11
  FILE_ATTRIBUTES = {
18
12
  'A': 'noatime',
@@ -15,12 +15,11 @@ version_added: historical
15
15
  description:
16
16
  - The M(ansible.builtin.command) module takes the command name followed by a list of space-delimited arguments.
17
17
  - The given command will be executed on all selected nodes.
18
- - The command(s) will not be
19
- processed through the shell, so variables like C($HOSTNAME) and operations
20
- like C("*"), C("<"), C(">"), C("|"), C(";") and C("&") will not work.
18
+ - The command(s) will not be processed through the shell, so operations like C("*"), C("<"), C(">"), C("|"), C(";") and C("&") will not work.
19
+ Also, environment variables are resolved via Python, not shell, see O(expand_argument_vars) and are left unchanged if not matched.
21
20
  Use the M(ansible.builtin.shell) module if you need these features.
22
- - To create C(command) tasks that are easier to read than the ones using space-delimited
23
- arguments, pass parameters using the C(args) L(task keyword,https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html#task)
21
+ - To create C(command) tasks that are easier to read than the ones using space-delimited arguments,
22
+ pass parameters using the C(args) L(task keyword,https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html#task)
24
23
  or use O(cmd) parameter.
25
24
  - Either a free form command or O(cmd) parameter is required, see the examples.
26
25
  - For Windows targets, use the M(ansible.windows.win_command) module instead.
@@ -41,8 +40,8 @@ attributes:
41
40
  options:
42
41
  expand_argument_vars:
43
42
  description:
44
- - Expands the arguments that are variables, for example C($HOME) will be expanded before being passed to the
45
- command to run.
43
+ - Expands the arguments that are variables, for example C($HOME) will be expanded before being passed to the command to run.
44
+ - If a variable is not matched, it is left unchanged, unlike shell substitution which would remove it.
46
45
  - Set to V(false) to disable expansion and treat the value as a literal argument.
47
46
  type: bool
48
47
  default: true
ansible/modules/dnf5.py CHANGED
@@ -357,6 +357,21 @@ libdnf5 = None
357
357
 
358
358
  def is_installed(base, spec):
359
359
  settings = libdnf5.base.ResolveSpecSettings()
360
+ try:
361
+ settings.set_group_with_name(True)
362
+ # Disable checking whether SPEC is a binary -> `/usr/(s)bin/<SPEC>`,
363
+ # this prevents scenarios like the following:
364
+ # * the `sssd-common` package is installed and provides `/usr/sbin/sssd` binary
365
+ # * the `sssd` package is NOT installed
366
+ # * due to `set_with_binaries(True)` being default `is_installed(base, "sssd")` would "unexpectedly" return True
367
+ # If users wish to target the `sssd` binary they can by specifying the full path `name=/usr/sbin/sssd` explicitly
368
+ # due to settings.set_with_filenames(True) being default.
369
+ settings.set_with_binaries(False)
370
+ except AttributeError:
371
+ # dnf5 < 5.2.0.0
372
+ settings.group_with_name = True
373
+ settings.with_binaries = False
374
+
360
375
  installed_query = libdnf5.rpm.PackageQuery(base)
361
376
  installed_query.filter_installed()
362
377
  match, nevra = installed_query.resolve_pkg_spec(spec, settings, True)
@@ -621,9 +636,12 @@ class Dnf5Module(YumDnf):
621
636
  settings = libdnf5.base.GoalJobSettings()
622
637
  try:
623
638
  settings.set_group_with_name(True)
639
+ settings.set_with_binaries(False)
624
640
  except AttributeError:
625
641
  # dnf5 < 5.2.0.0
626
642
  settings.group_with_name = True
643
+ settings.with_binaries = False
644
+
627
645
  if self.bugfix or self.security:
628
646
  advisory_query = libdnf5.advisory.AdvisoryQuery(base)
629
647
  types = []
@@ -13,11 +13,14 @@ DOCUMENTATION = """
13
13
  _terms:
14
14
  description: List of Python regex patterns to search for in variable names.
15
15
  required: True
16
+ seealso:
17
+ - plugin_type: lookup
18
+ plugin: ansible.builtin.vars
16
19
  """
17
20
 
18
21
  EXAMPLES = """
19
22
  - name: List variables that start with qz_
20
- ansible.builtin.debug: msg="{{ lookup('ansible.builtin.varnames', '^qz_.+')}}"
23
+ ansible.builtin.debug: msg="{{ lookup('ansible.builtin.varnames', '^qz_.+') }}"
21
24
  vars:
22
25
  qz_1: hello
23
26
  qz_2: world
@@ -25,13 +28,16 @@ EXAMPLES = """
25
28
  qz_: "I won't show either"
26
29
 
27
30
  - name: Show all variables
28
- ansible.builtin.debug: msg="{{ lookup('ansible.builtin.varnames', '.+')}}"
31
+ ansible.builtin.debug: msg="{{ lookup('ansible.builtin.varnames', '.+') }}"
29
32
 
30
33
  - name: Show variables with 'hosts' in their names
31
- ansible.builtin.debug: msg="{{ lookup('ansible.builtin.varnames', 'hosts')}}"
34
+ ansible.builtin.debug: msg="{{ q('varnames', 'hosts') }}"
32
35
 
33
36
  - name: Find several related variables that end specific way
34
- ansible.builtin.debug: msg="{{ lookup('ansible.builtin.varnames', '.+_zone$', '.+_location$') }}"
37
+ ansible.builtin.debug: msg="{{ query('ansible.builtin.varnames', '.+_zone$', '.+_location$') }}"
38
+
39
+ - name: display values from variables found via varnames (note "*" is used to dereference the list to a 'list of arguments')
40
+ debug: msg="{{ lookup('vars', *lookup('varnames', 'ansible_play_.+')) }}"
35
41
 
36
42
  """
37
43
 
@@ -17,6 +17,10 @@ DOCUMENTATION = """
17
17
  description:
18
18
  - What to return if a variable is undefined.
19
19
  - If no default is set, it will result in an error if any of the variables is undefined.
20
+ seealso:
21
+ - plugin_type: lookup
22
+ plugin: ansible.builtin.varnames
23
+
20
24
  """
21
25
 
22
26
  EXAMPLES = """
@@ -27,20 +31,23 @@ EXAMPLES = """
27
31
  myvar: ename
28
32
 
29
33
  - name: Show default empty since i dont have 'variablnotename'
30
- ansible.builtin.debug: msg="{{ lookup('ansible.builtin.vars', 'variabl' + myvar, default='')}}"
34
+ ansible.builtin.debug: msg="{{ lookup('ansible.builtin.vars', 'variabl' + myvar, default='') }}"
31
35
  vars:
32
36
  variablename: hello
33
37
  myvar: notename
34
38
 
35
39
  - name: Produce an error since i dont have 'variablnotename'
36
- ansible.builtin.debug: msg="{{ lookup('ansible.builtin.vars', 'variabl' + myvar)}}"
40
+ ansible.builtin.debug: msg="{{ q('vars', 'variabl' + myvar) }}"
37
41
  ignore_errors: True
38
42
  vars:
39
43
  variablename: hello
40
44
  myvar: notename
41
45
 
42
46
  - name: find several related variables
43
- ansible.builtin.debug: msg="{{ lookup('ansible.builtin.vars', 'ansible_play_hosts', 'ansible_play_batch', 'ansible_play_hosts_all') }}"
47
+ ansible.builtin.debug: msg="{{ query('ansible.builtin.vars', 'ansible_play_hosts', 'ansible_play_batch', 'ansible_play_hosts_all') }}"
48
+
49
+ - name: show values from variables found via varnames (note "*" is used to dereference the list to a 'list of arguments')
50
+ debug: msg="{{ q('vars', *q('varnames', 'ansible_play_.+')) }}"
44
51
 
45
52
  - name: Access nested variables
46
53
  ansible.builtin.debug: msg="{{ lookup('ansible.builtin.vars', 'variabl' + myvar).sub_var }}"
ansible/release.py CHANGED
@@ -17,6 +17,6 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- __version__ = '2.17.6'
20
+ __version__ = '2.17.7rc1'
21
21
  __author__ = 'Ansible, Inc.'
22
22
  __codename__ = "Gallows Pole"
@@ -48,7 +48,7 @@ from ansible.module_utils.six import string_types
48
48
  from ansible.module_utils.common.text.converters import to_native, to_text, to_bytes
49
49
  from ansible.module_utils.common.collections import is_sequence
50
50
  from ansible.plugins.loader import filter_loader, lookup_loader, test_loader
51
- from ansible.template.native_helpers import ansible_native_concat, ansible_eval_concat, ansible_concat
51
+ from ansible.template.native_helpers import AnsibleUndefined, ansible_native_concat, ansible_eval_concat, ansible_concat
52
52
  from ansible.template.template import AnsibleJ2Template
53
53
  from ansible.template.vars import AnsibleJ2Vars
54
54
  from ansible.utils.display import Display
@@ -312,35 +312,6 @@ def _wrap_native_text(func):
312
312
  return functools.update_wrapper(wrapper, func)
313
313
 
314
314
 
315
- class AnsibleUndefined(StrictUndefined):
316
- '''
317
- A custom Undefined class, which returns further Undefined objects on access,
318
- rather than throwing an exception.
319
- '''
320
- def __getattr__(self, name):
321
- if name == '__UNSAFE__':
322
- # AnsibleUndefined should never be assumed to be unsafe
323
- # This prevents ``hasattr(val, '__UNSAFE__')`` from evaluating to ``True``
324
- raise AttributeError(name)
325
- # Return original Undefined object to preserve the first failure context
326
- return self
327
-
328
- def __getitem__(self, key):
329
- # Return original Undefined object to preserve the first failure context
330
- return self
331
-
332
- def __repr__(self):
333
- return 'AnsibleUndefined(hint={0!r}, obj={1!r}, name={2!r})'.format(
334
- self._undefined_hint,
335
- self._undefined_obj,
336
- self._undefined_name
337
- )
338
-
339
- def __contains__(self, item):
340
- # Return original Undefined object to preserve the first failure context
341
- return self
342
-
343
-
344
315
  class AnsibleContext(Context):
345
316
  '''
346
317
  A custom context, which intercepts resolve_or_missing() calls and sets a flag
@@ -5,13 +5,19 @@ from __future__ import annotations
5
5
 
6
6
 
7
7
  import ast
8
+ from collections.abc import Mapping
8
9
  from itertools import islice, chain
9
10
  from types import GeneratorType
10
11
 
12
+ from ansible.module_utils.common.collections import is_sequence
11
13
  from ansible.module_utils.common.text.converters import to_text
12
14
  from ansible.module_utils.six import string_types
13
15
  from ansible.parsing.yaml.objects import AnsibleVaultEncryptedUnicode
14
16
  from ansible.utils.native_jinja import NativeJinjaText
17
+ from ansible.utils.unsafe_proxy import wrap_var
18
+ import ansible.module_utils.compat.typing as t
19
+
20
+ from jinja2.runtime import StrictUndefined
15
21
 
16
22
 
17
23
  _JSON_MAP = {
@@ -28,6 +34,40 @@ class Json2Python(ast.NodeTransformer):
28
34
  return ast.Constant(value=_JSON_MAP[node.id])
29
35
 
30
36
 
37
+ def _is_unsafe(value: t.Any) -> bool:
38
+ """
39
+ Our helper function, which will also recursively check dict and
40
+ list entries due to the fact that they may be repr'd and contain
41
+ a key or value which contains jinja2 syntax and would otherwise
42
+ lose the AnsibleUnsafe value.
43
+ """
44
+ to_check = [value]
45
+ seen = set()
46
+
47
+ while True:
48
+ if not to_check:
49
+ break
50
+
51
+ val = to_check.pop(0)
52
+ val_id = id(val)
53
+
54
+ if val_id in seen:
55
+ continue
56
+ seen.add(val_id)
57
+
58
+ if isinstance(val, AnsibleUndefined):
59
+ continue
60
+ if isinstance(val, Mapping):
61
+ to_check.extend(val.keys())
62
+ to_check.extend(val.values())
63
+ elif is_sequence(val):
64
+ to_check.extend(val)
65
+ elif getattr(val, '__UNSAFE__', False):
66
+ return True
67
+
68
+ return False
69
+
70
+
31
71
  def ansible_eval_concat(nodes):
32
72
  """Return a string of concatenated compiled nodes. Throw an undefined error
33
73
  if any of the nodes is undefined.
@@ -43,17 +83,28 @@ def ansible_eval_concat(nodes):
43
83
  if not head:
44
84
  return ''
45
85
 
86
+ unsafe = False
87
+
46
88
  if len(head) == 1:
47
89
  out = head[0]
48
90
 
49
91
  if isinstance(out, NativeJinjaText):
50
92
  return out
51
93
 
94
+ unsafe = _is_unsafe(out)
52
95
  out = to_text(out)
53
96
  else:
54
97
  if isinstance(nodes, GeneratorType):
55
98
  nodes = chain(head, nodes)
56
- out = ''.join([to_text(v) for v in nodes])
99
+
100
+ out_values = []
101
+ for v in nodes:
102
+ if not unsafe and _is_unsafe(v):
103
+ unsafe = True
104
+
105
+ out_values.append(to_text(v))
106
+
107
+ out = ''.join(out_values)
57
108
 
58
109
  # if this looks like a dictionary, list or bool, convert it to such
59
110
  if out.startswith(('{', '[')) or out in ('True', 'False'):
@@ -68,6 +119,9 @@ def ansible_eval_concat(nodes):
68
119
  except (TypeError, ValueError, SyntaxError, MemoryError):
69
120
  pass
70
121
 
122
+ if unsafe:
123
+ out = wrap_var(out)
124
+
71
125
  return out
72
126
 
73
127
 
@@ -78,7 +132,19 @@ def ansible_concat(nodes):
78
132
 
79
133
  Used in Templar.template() when jinja2_native=False and convert_data=False.
80
134
  """
81
- return ''.join([to_text(v) for v in nodes])
135
+ unsafe = False
136
+ values = []
137
+ for v in nodes:
138
+ if not unsafe and _is_unsafe(v):
139
+ unsafe = True
140
+
141
+ values.append(to_text(v))
142
+
143
+ out = ''.join(values)
144
+ if unsafe:
145
+ out = wrap_var(out)
146
+
147
+ return out
82
148
 
83
149
 
84
150
  def ansible_native_concat(nodes):
@@ -95,6 +161,8 @@ def ansible_native_concat(nodes):
95
161
  if not head:
96
162
  return None
97
163
 
164
+ unsafe = False
165
+
98
166
  if len(head) == 1:
99
167
  out = head[0]
100
168
 
@@ -115,10 +183,21 @@ def ansible_native_concat(nodes):
115
183
  # short-circuit literal_eval for anything other than strings
116
184
  if not isinstance(out, string_types):
117
185
  return out
186
+
187
+ unsafe = _is_unsafe(out)
188
+
118
189
  else:
119
190
  if isinstance(nodes, GeneratorType):
120
191
  nodes = chain(head, nodes)
121
- out = ''.join([to_text(v) for v in nodes])
192
+
193
+ out_values = []
194
+ for v in nodes:
195
+ if not unsafe and _is_unsafe(v):
196
+ unsafe = True
197
+
198
+ out_values.append(to_text(v))
199
+
200
+ out = ''.join(out_values)
122
201
 
123
202
  try:
124
203
  evaled = ast.literal_eval(
@@ -128,10 +207,45 @@ def ansible_native_concat(nodes):
128
207
  ast.parse(out, mode='eval')
129
208
  )
130
209
  except (TypeError, ValueError, SyntaxError, MemoryError):
210
+ if unsafe:
211
+ out = wrap_var(out)
212
+
131
213
  return out
132
214
 
133
215
  if isinstance(evaled, string_types):
134
216
  quote = out[0]
135
- return f'{quote}{evaled}{quote}'
217
+ evaled = f'{quote}{evaled}{quote}'
218
+
219
+ if unsafe:
220
+ evaled = wrap_var(evaled)
136
221
 
137
222
  return evaled
223
+
224
+
225
+ class AnsibleUndefined(StrictUndefined):
226
+ """
227
+ A custom Undefined class, which returns further Undefined objects on access,
228
+ rather than throwing an exception.
229
+ """
230
+ def __getattr__(self, name):
231
+ if name == '__UNSAFE__':
232
+ # AnsibleUndefined should never be assumed to be unsafe
233
+ # This prevents ``hasattr(val, '__UNSAFE__')`` from evaluating to ``True``
234
+ raise AttributeError(name)
235
+ # Return original Undefined object to preserve the first failure context
236
+ return self
237
+
238
+ def __getitem__(self, key):
239
+ # Return original Undefined object to preserve the first failure context
240
+ return self
241
+
242
+ def __repr__(self):
243
+ return 'AnsibleUndefined(hint={0!r}, obj={1!r}, name={2!r})'.format(
244
+ self._undefined_hint,
245
+ self._undefined_obj,
246
+ self._undefined_name
247
+ )
248
+
249
+ def __contains__(self, item):
250
+ # Return original Undefined object to preserve the first failure context
251
+ return self
ansible/vars/hostvars.py CHANGED
@@ -92,10 +92,12 @@ class HostVars(Mapping):
92
92
  return self._find_host(host_name) is not None
93
93
 
94
94
  def __iter__(self):
95
- yield from self._inventory.hosts
95
+ # include implicit localhost only if it has variables set
96
+ yield from self._inventory.hosts | {'localhost': self._inventory.localhost} if self._inventory.localhost else {}
96
97
 
97
98
  def __len__(self):
98
- return len(self._inventory.hosts)
99
+ # include implicit localhost only if it has variables set
100
+ return len(self._inventory.hosts) + (1 if self._inventory.localhost else 0)
99
101
 
100
102
  def __repr__(self):
101
103
  out = {}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ansible-core
3
- Version: 2.17.6
3
+ Version: 2.17.7rc1
4
4
  Summary: Radically simple IT automation
5
5
  Home-page: https://ansible.com/
6
6
  Author: Ansible, Inc.
@@ -31,11 +31,11 @@ Classifier: Topic :: Utilities
31
31
  Requires-Python: >=3.10
32
32
  Description-Content-Type: text/markdown
33
33
  License-File: COPYING
34
- Requires-Dist: jinja2 >=3.0.0
35
- Requires-Dist: PyYAML >=5.1
34
+ Requires-Dist: jinja2>=3.0.0
35
+ Requires-Dist: PyYAML>=5.1
36
36
  Requires-Dist: cryptography
37
37
  Requires-Dist: packaging
38
- Requires-Dist: resolvelib <1.1.0,>=0.5.3
38
+ Requires-Dist: resolvelib<1.1.0,>=0.5.3
39
39
 
40
40
  [![PyPI version](https://img.shields.io/pypi/v/ansible-core.svg)](https://pypi.org/project/ansible-core)
41
41
  [![Docs badge](https://img.shields.io/badge/docs-latest-brightgreen.svg)](https://docs.ansible.com/ansible/latest/)
@@ -3,7 +3,7 @@ ansible/__main__.py,sha256=EnLcULXNtSXkuJ8igEHPPLBTZKAwqXv4PvMEhvzp2Oo,1430
3
3
  ansible/constants.py,sha256=vRwEcoynqtuKDPKsxKUY94XzrTSV3J0y1slb907DioU,9140
4
4
  ansible/context.py,sha256=oKYyfjfWpy8vDeProtqfnqSmuij_t75_5e5t0U_hQ1g,1933
5
5
  ansible/keyword_desc.yml,sha256=vE9joFgSeHR4Djl7Bd-HHVCrGByRCrTUmWYZ8LKPZKk,7412
6
- ansible/release.py,sha256=cFQqKKXYW-THaidS0mQ64kFSM_nnCmV40apnWC7JwSw,832
6
+ ansible/release.py,sha256=yWF7m4SKOzX1hLwK0_H6xis5PCFGeLYiuBFcb7paYcA,835
7
7
  ansible/_vendor/__init__.py,sha256=2QBeBwT7uG7M3Aw-pIdCpt6XPtHMCpbEKfACYKA7xIg,2033
8
8
  ansible/cli/__init__.py,sha256=fzgR82NIGBH3GujIMehhAaP4KYszn4uztuCaFYRUpGk,28718
9
9
  ansible/cli/adhoc.py,sha256=quJ9WzRzf3dz_dtDGmahNMffqyNVy1jzQCMo21YL5Qg,8194
@@ -37,7 +37,7 @@ ansible/executor/module_common.py,sha256=4pVfjMgCle9ttAZTeuwSx3Kdi0rljagyHC11i4V
37
37
  ansible/executor/play_iterator.py,sha256=mrGK7INCfE6L2Gt0X7S0hm0Srtw4T-PYwJVi77BAxls,31457
38
38
  ansible/executor/playbook_executor.py,sha256=S_dwBYqYTQtN32AMQXxQTOpVCczV4KJ8ezergt1nlmA,15014
39
39
  ansible/executor/stats.py,sha256=gcBhJQrZTgE95737d6lArJ3FpTlbAfVt6GMhEqs5ZPU,3180
40
- ansible/executor/task_executor.py,sha256=T1f5RrzIUULNpH2dYXftm47165FrtiwVR3hzxQEJBXc,60698
40
+ ansible/executor/task_executor.py,sha256=d3kh9ec_ylSoUvm53EV58orAnsXjuIO4Rq-jK908Q48,60756
41
41
  ansible/executor/task_queue_manager.py,sha256=wv19pq9LNHRABjvDYUZHQ9kmlO_ypA0r3aMaLnGxaCs,18640
42
42
  ansible/executor/task_result.py,sha256=pnLu-f0tYaDmDXSQftCBChSt_Zx5pW0GeLYLvEHuHkA,5695
43
43
  ansible/executor/discovery/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -140,7 +140,7 @@ ansible/inventory/host.py,sha256=PDb5OTplhfpUIvdHiP2BckUOB1gUl302N-3sW0_sTyg,503
140
140
  ansible/inventory/manager.py,sha256=45mHgZTAkQ3IjAtrgsNzJXvynC-HIEor-JJE-V3xXN4,29454
141
141
  ansible/module_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
142
142
  ansible/module_utils/_text.py,sha256=VkWgAnSNVCbTQqZgllUObBFsH3uM4EUW5srl1UR9t1g,544
143
- ansible/module_utils/ansible_release.py,sha256=cFQqKKXYW-THaidS0mQ64kFSM_nnCmV40apnWC7JwSw,832
143
+ ansible/module_utils/ansible_release.py,sha256=yWF7m4SKOzX1hLwK0_H6xis5PCFGeLYiuBFcb7paYcA,835
144
144
  ansible/module_utils/api.py,sha256=DWIuLW5gDWuyyDHLLgGnub42Qa8kagDdkf1xDeLAFl4,5784
145
145
  ansible/module_utils/basic.py,sha256=UcDamm_6bkL3HXxKvQcSUlzDOHkIlvd8AYGuqJNmZeI,86113
146
146
  ansible/module_utils/connection.py,sha256=q_BdUaST6E44ltHsWPOFOheXK9vKmzaJvP-eQOrOrmE,8394
@@ -157,7 +157,7 @@ ansible/module_utils/common/_utils.py,sha256=5SINLxr2UA0zSEzgHJRPQFkdpp6ADDcyH7q
157
157
  ansible/module_utils/common/arg_spec.py,sha256=QO0rSFt6cytrxt4BRzs6sIVAMBWnIbs5u2900Xr6xJw,12012
158
158
  ansible/module_utils/common/collections.py,sha256=dN4rLUosuj1PRoyWArOZ1vKF_HaZ8-aOVE8c7sLQlj4,3849
159
159
  ansible/module_utils/common/dict_transformations.py,sha256=hpkchhyZXriwWCuZtTiRoepoZMNnTk7RXqOVN3JWhuw,5525
160
- ansible/module_utils/common/file.py,sha256=-j34Sd4df-WdTvcbT_KUXyRFsi5y04V4S2QA_3bm9vc,3109
160
+ ansible/module_utils/common/file.py,sha256=m9SXBIia_7_U6hJmpT_w5F7Ixp07Wj6F0BiTS_6227M,2982
161
161
  ansible/module_utils/common/json.py,sha256=faAwpBjmchF8PqvgW_pOow1OyoKiRte4a0TtkAsUVjg,3220
162
162
  ansible/module_utils/common/locale.py,sha256=lLQU-CU4YfTVK8EknMb-PLKIAf5eAjD0ZwE4ARqkJRQ,2296
163
163
  ansible/module_utils/common/network.py,sha256=ffFrBriNPHFDslP54NRN3QaJADEWBG7eCgv5c7RcOHs,4226
@@ -283,14 +283,14 @@ ansible/modules/assert.py,sha256=ezlc6kKr0NyHMBRyhFjla44Wi9Y-l4WilbkRX7Dwftc,294
283
283
  ansible/modules/async_status.py,sha256=iuNMObp1piLIaoO-7ZiueUNitk-5CDW93l9iVPqd53I,4574
284
284
  ansible/modules/async_wrapper.py,sha256=OjA0E7lm8mvlxXA76-HVvjc_H1fHae0Euh25exY6gEc,11619
285
285
  ansible/modules/blockinfile.py,sha256=NX9wWeXSpMIlOpXBLrLuFgTTTvMYfODIYwjYNCK35vs,15507
286
- ansible/modules/command.py,sha256=t0VvOXUwlgO_5Jv7A0TcrG0O-jIlkfdwEJXsc_S5q8A,13961
286
+ ansible/modules/command.py,sha256=jMxri217oPwVjK57tFgyvrev2czyVfVxxlnBkf5GLsY,14154
287
287
  ansible/modules/copy.py,sha256=FE1jKP-VVBTrV_eX2td7FHNhEh-ed_KPGCyrAW1N_gA,32102
288
288
  ansible/modules/cron.py,sha256=beuuoj80saY3B7Gtj7wDYLdFuGnxc94iBczakBZhsKY,26198
289
289
  ansible/modules/deb822_repository.py,sha256=CWgVVSuq45dkHrozG2Yk229FdIdGfaFSmBFBQ3ymANs,15741
290
290
  ansible/modules/debconf.py,sha256=sL3QKn3fg6bnifY7J3mvbeF7aUoUx7t0H-RL-ByIm4k,9323
291
291
  ansible/modules/debug.py,sha256=jqFvwGzDkB5NlcxR8vXhHjaakv9Ib_GjGdT2GbKhMhE,2907
292
292
  ansible/modules/dnf.py,sha256=uuOAjuUen70MR2j3CwuVzy-NWJnGHoPukHyuo3Dtqvs,56095
293
- ansible/modules/dnf5.py,sha256=bbPlc-K-I0NZzCwn3Ke12FUcQu-A8H4S7_gmlxXDgZg,26793
293
+ ansible/modules/dnf5.py,sha256=1VggjlZ3eWkt9Egn6SPixKQm1x2jIo39A3oqFXrR8Ps,27691
294
294
  ansible/modules/dpkg_selections.py,sha256=rBH3A2lr6DB6qGlF3fF2716QU4jMSqC6EjikYffTtOI,2782
295
295
  ansible/modules/expect.py,sha256=J7IsU3OvBOeK8YtSWKkQKTfgmnWs2OSP_ntyj3UjmvM,9367
296
296
  ansible/modules/fail.py,sha256=95z8jFyVaizwwupSce04kj1wwnOmbM0ooUX7mXluoyU,1659
@@ -569,8 +569,8 @@ ansible/plugins/lookup/template.py,sha256=xFYWKY808hHPj7nJbaLM2mZro79p6TjpFXyAcR
569
569
  ansible/plugins/lookup/together.py,sha256=T4J2miqHTnrDP6-CrlJ3wgI0UgyZyYVRVrDTWx3olpY,2110
570
570
  ansible/plugins/lookup/unvault.py,sha256=5LU8Lf7Gx0yRh8z0u1giSXkd93pkSZ34ibkoQnHCsyw,2049
571
571
  ansible/plugins/lookup/url.py,sha256=8JFMlk9diqsboHr1ArYGudsapPBP995maJdzHlair74,9378
572
- ansible/plugins/lookup/varnames.py,sha256=h5ZAHOx8MlEvv466AirXCaGZ5DeH95evGb2he8_aKqA,2330
573
- ansible/plugins/lookup/vars.py,sha256=eXVZdwumdcp3ajaDX7JyIYeGvQ6L-HxHGfnob9Pnkg8,3424
572
+ ansible/plugins/lookup/varnames.py,sha256=4WKSH-u0ZnQD47r20c5OenaG6Vlamp6nweIZSFOJ0b8,2595
573
+ ansible/plugins/lookup/vars.py,sha256=W9at2j3xBk6z4IXfSutTEHqdzbiTI1B1tuYOLdd1BMQ,3672
574
574
  ansible/plugins/netconf/__init__.py,sha256=50w1g2rhUo6L-xtiMT20jbR8WyOnhwNSRd2IRNSjNX4,17094
575
575
  ansible/plugins/shell/__init__.py,sha256=rEwatHZ46LJuxMFANb6e__CTLkFWX6B0878eBaCXwqM,9286
576
576
  ansible/plugins/shell/cmd.py,sha256=kPCSKrJJFH5XTkmteEI3P1Da6WfPSXxDnV39VFpgD-A,2170
@@ -636,8 +636,8 @@ ansible/plugins/test/version.yml,sha256=2d55HZGIniPu53z6_bV4C26_1sqRAHJqCwesOU3m
636
636
  ansible/plugins/test/version_compare.yml,sha256=2d55HZGIniPu53z6_bV4C26_1sqRAHJqCwesOU3ma38,3283
637
637
  ansible/plugins/vars/__init__.py,sha256=D3YwVKABesBwag9e7GsLOxlRWqEO5NgfHDmYSq0z_1k,1331
638
638
  ansible/plugins/vars/host_group_vars.py,sha256=Qouyds_KOEuqaz4GlTYQnQUxXyTyyjFMj7maRnH8miU,6284
639
- ansible/template/__init__.py,sha256=_TjK5oSfTlC4sGqaOegaAyjVP_m2C9SmI2S2d690HLQ,40967
640
- ansible/template/native_helpers.py,sha256=XjaTCQFSq0X6xTVENviRKYRVqmgI7IXCx70DeZ0C7F4,4333
639
+ ansible/template/__init__.py,sha256=GIMeWbOdYFocq-4Ee9efpdAOiIIdjWhrTmlWEbPriwQ,39963
640
+ ansible/template/native_helpers.py,sha256=l-Jo2-ExemCheK-Yi-NRIUYkJyHqCGjRsW2ANTrqmuQ,7213
641
641
  ansible/template/template.py,sha256=47dvX9AqSKlp6-n2QRPrHyhI3bboVyOpQekmQYryUB4,1583
642
642
  ansible/template/vars.py,sha256=YUCVqNLS3wjYHACSei7f5uwZMZRBTwiyjGge09EP00E,2854
643
643
  ansible/utils/__init__.py,sha256=mRvbCJPA-_veSG5ka3v04G5vsarLVDeB3EWFsu6geSI,749
@@ -674,11 +674,11 @@ ansible/utils/collection_loader/_collection_meta.py,sha256=L8NWlDs5KBMASIKRGoFTN
674
674
  ansible/vars/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
675
675
  ansible/vars/clean.py,sha256=X2WMksJMWITQ9FsM-Fb_YxT_hAGDqJ3urSTJzYBEdAk,5999
676
676
  ansible/vars/fact_cache.py,sha256=M57vMhkQ2DrzvNaZkfaCmKQJUqP1Rn_A31_X-5YBfzQ,1903
677
- ansible/vars/hostvars.py,sha256=ggUQ5luCajjX7sEvFCHpIuB_stWPRb089cZ3I1v1Vmo,5070
677
+ ansible/vars/hostvars.py,sha256=o11xrzDVYn23renGbb3lx3R-nH9qOjLFju5IYJanDxg,5324
678
678
  ansible/vars/manager.py,sha256=ujVDQXWvy8BihIxGzBPX6fMeUl2AlclkwadKMo6VjSk,38583
679
679
  ansible/vars/plugins.py,sha256=RsRU9fiLcJwPIAyTYnmVZglsiEOMCIgQskflavE-XnE,4546
680
680
  ansible/vars/reserved.py,sha256=kZiQMPvaFin35006gLwDpX16w-9xlu6EaL4LSTKP40U,2531
681
- ansible_core-2.17.6.data/scripts/ansible-test,sha256=dyY2HtRZotRQO3b89HGXY_KnJgBvgsm4eLIe4B2LUoA,1637
681
+ ansible_core-2.17.7rc1.data/scripts/ansible-test,sha256=dyY2HtRZotRQO3b89HGXY_KnJgBvgsm4eLIe4B2LUoA,1637
682
682
  ansible_test/__init__.py,sha256=20VPOj11c6Ut1Av9RaurgwJvFhMqkWG3vAvcCbecNKw,66
683
683
  ansible_test/_data/ansible.cfg,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
684
684
  ansible_test/_data/coveragerc,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -767,7 +767,7 @@ ansible_test/_internal/target.py,sha256=Whtb_n0jn4zbiMmX7je5jewgzsRczfXRm_ndYtjT
767
767
  ansible_test/_internal/test.py,sha256=znQmGjKACqDU8T0EAPqcv2qyy0J7M2w4OmyYhwHLqT0,14515
768
768
  ansible_test/_internal/thread.py,sha256=WQoZ2q2ljmEkKHRDkIqwxW7eZbkCKDrG3YZfcaxHzHw,2596
769
769
  ansible_test/_internal/timeout.py,sha256=hT-LirImhAh1iCGIh8JpmECXsiGu6Zetw8BWl1iBIC8,4050
770
- ansible_test/_internal/util.py,sha256=NAeVlq-vOwwZzIaFOxnjsFwdibSp_9k1ay8YkChGCxU,37792
770
+ ansible_test/_internal/util.py,sha256=1_yTfH0t0dfa77EZvY1wnkQ6rgTdSRUQL9oCuRWrD00,37832
771
771
  ansible_test/_internal/util_common.py,sha256=W5mkR0sevcyMWsMPYcpxRN-b8It8N9g6PqkophHCI9U,17385
772
772
  ansible_test/_internal/venv.py,sha256=k7L9_Ocpsdwp4kQFLF59BVguymd2nqJ-bLHH1NlMET0,5521
773
773
  ansible_test/_internal/ci/__init__.py,sha256=QOaC_8_wUzqFEbsFCXYAnElWoUo6gB40CXvP9RJ-Iyo,7738
@@ -979,9 +979,9 @@ ansible_test/config/cloud-config-vultr.ini.template,sha256=XLKHk3lg_8ReQMdWfZzhh
979
979
  ansible_test/config/config.yml,sha256=wb3knoBmZewG3GWOMnRHoVPQWW4vPixKLPMNS6vJmTc,2620
980
980
  ansible_test/config/inventory.networking.template,sha256=bFNSk8zNQOaZ_twaflrY0XZ9mLwUbRLuNT0BdIFwvn4,1335
981
981
  ansible_test/config/inventory.winrm.template,sha256=1QU8W-GFLnYEw8yY9bVIvUAVvJYPM3hyoijf6-M7T00,1098
982
- ansible_core-2.17.6.dist-info/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
983
- ansible_core-2.17.6.dist-info/METADATA,sha256=DWTfv-JHWhjLB4x0_ShhqQ90LBbiKR-4dFQAz0a5CkU,6945
984
- ansible_core-2.17.6.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
985
- ansible_core-2.17.6.dist-info/entry_points.txt,sha256=0mpmsrIhODChxKl3eS-NcVQCaMetBn8KdPLtVxQgR64,453
986
- ansible_core-2.17.6.dist-info/top_level.txt,sha256=IFbRLjAvih1DYzJWg3_F6t4sCzEMxRO7TOMNs6GkYHo,21
987
- ansible_core-2.17.6.dist-info/RECORD,,
982
+ ansible_core-2.17.7rc1.dist-info/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
983
+ ansible_core-2.17.7rc1.dist-info/METADATA,sha256=kXRZtPJMtRU3PXbSIvzpwvsZO8asaOhHOC4AntnSM6c,6945
984
+ ansible_core-2.17.7rc1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
985
+ ansible_core-2.17.7rc1.dist-info/entry_points.txt,sha256=0mpmsrIhODChxKl3eS-NcVQCaMetBn8KdPLtVxQgR64,453
986
+ ansible_core-2.17.7rc1.dist-info/top_level.txt,sha256=IFbRLjAvih1DYzJWg3_F6t4sCzEMxRO7TOMNs6GkYHo,21
987
+ ansible_core-2.17.7rc1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -974,15 +974,15 @@ class HostConnectionError(ApplicationError):
974
974
  self._callback()
975
975
 
976
976
 
977
- def format_command_output(stdout: str, stderr: str) -> str:
977
+ def format_command_output(stdout: str | None, stderr: str | None) -> str:
978
978
  """Return a formatted string containing the given stdout and stderr (if any)."""
979
979
  message = ''
980
980
 
981
- if stderr := stderr.strip():
981
+ if stderr and (stderr := stderr.strip()):
982
982
  message += '>>> Standard Error\n'
983
983
  message += f'{stderr}{Display.clear}\n'
984
984
 
985
- if stdout := stdout.strip():
985
+ if stdout and (stdout := stdout.strip()):
986
986
  message += '>>> Standard Output\n'
987
987
  message += f'{stdout}{Display.clear}\n'
988
988