ansible-core 2.19.4rc1__py3-none-any.whl → 2.20.0__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.

Files changed (215) hide show
  1. ansible/_internal/__init__.py +1 -4
  2. ansible/_internal/_ansiballz/_builder.py +1 -3
  3. ansible/_internal/_collection_proxy.py +7 -9
  4. ansible/_internal/_json/__init__.py +3 -4
  5. ansible/_internal/_templating/_engine.py +1 -1
  6. ansible/_internal/_templating/_jinja_plugins.py +1 -2
  7. ansible/_internal/_wrapt.py +105 -301
  8. ansible/cli/__init__.py +11 -10
  9. ansible/cli/adhoc.py +1 -2
  10. ansible/cli/arguments/option_helpers.py +1 -1
  11. ansible/cli/config.py +5 -6
  12. ansible/cli/doc.py +67 -67
  13. ansible/cli/galaxy.py +15 -24
  14. ansible/cli/inventory.py +0 -1
  15. ansible/cli/playbook.py +0 -1
  16. ansible/cli/pull.py +0 -1
  17. ansible/cli/scripts/ansible_connection_cli_stub.py +1 -1
  18. ansible/config/base.yml +1 -25
  19. ansible/config/manager.py +0 -2
  20. ansible/executor/play_iterator.py +42 -20
  21. ansible/executor/playbook_executor.py +0 -9
  22. ansible/executor/task_executor.py +26 -18
  23. ansible/executor/task_queue_manager.py +1 -3
  24. ansible/galaxy/api.py +33 -80
  25. ansible/galaxy/collection/__init__.py +11 -21
  26. ansible/galaxy/dependency_resolution/__init__.py +10 -9
  27. ansible/galaxy/dependency_resolution/dataclasses.py +86 -70
  28. ansible/galaxy/dependency_resolution/providers.py +54 -134
  29. ansible/galaxy/dependency_resolution/versioning.py +2 -4
  30. ansible/galaxy/role.py +1 -33
  31. ansible/inventory/manager.py +2 -3
  32. ansible/keyword_desc.yml +0 -3
  33. ansible/module_utils/_internal/_datatag/__init__.py +2 -10
  34. ansible/module_utils/_internal/_no_six.py +86 -0
  35. ansible/module_utils/_text.py +28 -8
  36. ansible/module_utils/ansible_release.py +2 -2
  37. ansible/module_utils/basic.py +26 -23
  38. ansible/module_utils/common/_collections_compat.py +11 -2
  39. ansible/module_utils/common/collections.py +8 -3
  40. ansible/module_utils/common/dict_transformations.py +1 -2
  41. ansible/module_utils/common/network.py +4 -2
  42. ansible/module_utils/common/parameters.py +32 -41
  43. ansible/module_utils/common/text/converters.py +109 -23
  44. ansible/module_utils/common/text/formatters.py +6 -2
  45. ansible/module_utils/common/validation.py +11 -9
  46. ansible/module_utils/connection.py +8 -3
  47. ansible/module_utils/facts/hardware/linux.py +23 -7
  48. ansible/module_utils/facts/hardware/netbsd.py +1 -1
  49. ansible/module_utils/facts/hardware/sunos.py +2 -1
  50. ansible/module_utils/facts/packages.py +6 -2
  51. ansible/module_utils/facts/system/distribution.py +2 -1
  52. ansible/module_utils/facts/system/env.py +6 -3
  53. ansible/module_utils/facts/system/local.py +3 -1
  54. ansible/module_utils/parsing/convert_bool.py +6 -2
  55. ansible/module_utils/service.py +2 -3
  56. ansible/module_utils/six/__init__.py +11 -6
  57. ansible/module_utils/yumdnf.py +0 -5
  58. ansible/modules/apt.py +18 -13
  59. ansible/modules/apt_repository.py +1 -1
  60. ansible/modules/assemble.py +5 -9
  61. ansible/modules/blockinfile.py +39 -23
  62. ansible/modules/cron.py +26 -35
  63. ansible/modules/deb822_repository.py +83 -12
  64. ansible/modules/dnf.py +3 -7
  65. ansible/modules/dnf5.py +4 -6
  66. ansible/modules/expect.py +0 -3
  67. ansible/modules/find.py +1 -2
  68. ansible/modules/get_url.py +1 -1
  69. ansible/modules/git.py +4 -5
  70. ansible/modules/include_vars.py +1 -1
  71. ansible/modules/known_hosts.py +7 -1
  72. ansible/modules/lineinfile.py +71 -63
  73. ansible/modules/package_facts.py +1 -1
  74. ansible/modules/pip.py +8 -2
  75. ansible/modules/replace.py +6 -6
  76. ansible/modules/service.py +3 -4
  77. ansible/modules/stat.py +20 -0
  78. ansible/modules/uri.py +9 -10
  79. ansible/modules/user.py +1 -2
  80. ansible/modules/wait_for.py +2 -2
  81. ansible/modules/wait_for_connection.py +2 -1
  82. ansible/modules/yum_repository.py +1 -16
  83. ansible/parsing/dataloader.py +24 -31
  84. ansible/parsing/vault/__init__.py +1 -2
  85. ansible/playbook/base.py +8 -56
  86. ansible/playbook/block.py +0 -60
  87. ansible/playbook/collectionsearch.py +1 -2
  88. ansible/playbook/handler.py +1 -7
  89. ansible/playbook/helpers.py +0 -7
  90. ansible/playbook/included_file.py +1 -1
  91. ansible/playbook/play.py +102 -36
  92. ansible/playbook/play_context.py +4 -0
  93. ansible/playbook/role/__init__.py +10 -65
  94. ansible/playbook/role/definition.py +3 -4
  95. ansible/playbook/role/include.py +2 -3
  96. ansible/playbook/role/metadata.py +1 -12
  97. ansible/playbook/role/requirement.py +1 -2
  98. ansible/playbook/role_include.py +1 -2
  99. ansible/playbook/taggable.py +16 -5
  100. ansible/playbook/task.py +11 -50
  101. ansible/plugins/action/__init__.py +20 -19
  102. ansible/plugins/action/add_host.py +1 -2
  103. ansible/plugins/action/fetch.py +3 -5
  104. ansible/plugins/action/group_by.py +1 -2
  105. ansible/plugins/action/include_vars.py +20 -22
  106. ansible/plugins/action/script.py +1 -3
  107. ansible/plugins/action/template.py +1 -2
  108. ansible/plugins/action/uri.py +4 -2
  109. ansible/plugins/cache/__init__.py +1 -0
  110. ansible/plugins/callback/__init__.py +13 -6
  111. ansible/plugins/connection/__init__.py +3 -7
  112. ansible/plugins/connection/local.py +2 -3
  113. ansible/plugins/connection/psrp.py +0 -2
  114. ansible/plugins/connection/ssh.py +2 -7
  115. ansible/plugins/connection/winrm.py +0 -2
  116. ansible/plugins/doc_fragments/result_format_callback.py +15 -0
  117. ansible/plugins/filter/core.py +4 -5
  118. ansible/plugins/filter/encryption.py +3 -27
  119. ansible/plugins/filter/mathstuff.py +1 -2
  120. ansible/plugins/filter/to_nice_yaml.yml +31 -3
  121. ansible/plugins/filter/to_yaml.yml +29 -12
  122. ansible/plugins/inventory/__init__.py +1 -2
  123. ansible/plugins/inventory/toml.py +3 -6
  124. ansible/plugins/inventory/yaml.py +1 -2
  125. ansible/plugins/loader.py +3 -4
  126. ansible/plugins/lookup/password.py +1 -2
  127. ansible/plugins/lookup/subelements.py +2 -3
  128. ansible/plugins/lookup/url.py +1 -1
  129. ansible/plugins/lookup/varnames.py +1 -2
  130. ansible/plugins/shell/__init__.py +9 -4
  131. ansible/plugins/shell/powershell.py +8 -24
  132. ansible/plugins/strategy/__init__.py +5 -2
  133. ansible/plugins/test/core.py +4 -1
  134. ansible/plugins/test/falsy.yml +1 -1
  135. ansible/plugins/test/regex.yml +18 -6
  136. ansible/plugins/test/truthy.yml +1 -1
  137. ansible/release.py +2 -2
  138. ansible/template/__init__.py +3 -7
  139. ansible/utils/collection_loader/_collection_config.py +5 -0
  140. ansible/utils/collection_loader/_collection_finder.py +11 -14
  141. ansible/utils/context_objects.py +7 -4
  142. ansible/utils/display.py +7 -6
  143. ansible/utils/encrypt.py +0 -5
  144. ansible/utils/helpers.py +6 -2
  145. ansible/utils/jsonrpc.py +7 -3
  146. ansible/utils/plugin_docs.py +49 -38
  147. ansible/utils/ssh_functions.py +0 -19
  148. ansible/utils/unsafe_proxy.py +7 -7
  149. ansible/vars/clean.py +2 -3
  150. ansible/vars/manager.py +28 -22
  151. ansible/vars/plugins.py +1 -31
  152. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/METADATA +4 -4
  153. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/RECORD +213 -214
  154. ansible_test/_data/completion/docker.txt +7 -7
  155. ansible_test/_data/completion/network.txt +0 -1
  156. ansible_test/_data/completion/remote.txt +4 -4
  157. ansible_test/_data/requirements/ansible-test.txt +1 -1
  158. ansible_test/_data/requirements/ansible.txt +1 -1
  159. ansible_test/_data/requirements/sanity.ansible-doc.txt +2 -2
  160. ansible_test/_data/requirements/sanity.changelog.txt +2 -2
  161. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  162. ansible_test/_data/requirements/sanity.import.txt +1 -1
  163. ansible_test/_data/requirements/sanity.integration-aliases.txt +1 -1
  164. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  165. ansible_test/_data/requirements/sanity.pylint.txt +6 -6
  166. ansible_test/_data/requirements/sanity.runtime-metadata.txt +1 -1
  167. ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
  168. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  169. ansible_test/_internal/cache.py +2 -5
  170. ansible_test/_internal/cli/compat.py +1 -1
  171. ansible_test/_internal/commands/coverage/combine.py +1 -3
  172. ansible_test/_internal/commands/integration/__init__.py +3 -7
  173. ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
  174. ansible_test/_internal/commands/integration/coverage.py +1 -3
  175. ansible_test/_internal/commands/integration/filters.py +5 -10
  176. ansible_test/_internal/commands/sanity/pylint.py +11 -0
  177. ansible_test/_internal/commands/sanity/validate_modules.py +1 -5
  178. ansible_test/_internal/commands/units/__init__.py +1 -13
  179. ansible_test/_internal/compat/packaging.py +2 -2
  180. ansible_test/_internal/compat/yaml.py +2 -2
  181. ansible_test/_internal/completion.py +2 -5
  182. ansible_test/_internal/config.py +2 -7
  183. ansible_test/_internal/coverage_util.py +1 -1
  184. ansible_test/_internal/delegation.py +2 -0
  185. ansible_test/_internal/docker_util.py +1 -1
  186. ansible_test/_internal/host_profiles.py +6 -11
  187. ansible_test/_internal/provider/__init__.py +2 -5
  188. ansible_test/_internal/provisioning.py +2 -5
  189. ansible_test/_internal/pypi_proxy.py +1 -1
  190. ansible_test/_internal/python_requirements.py +1 -1
  191. ansible_test/_internal/target.py +2 -6
  192. ansible_test/_internal/thread.py +1 -4
  193. ansible_test/_internal/util.py +9 -14
  194. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +14 -19
  195. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +48 -45
  196. ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +9 -7
  197. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +51 -37
  198. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +31 -18
  199. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +1 -2
  200. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +59 -71
  201. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -2
  202. ansible_test/_util/target/cli/ansible_test_cli_stub.py +4 -2
  203. ansible_test/_util/target/common/constants.py +2 -2
  204. ansible_test/_util/target/setup/bootstrap.sh +0 -6
  205. ansible/utils/py3compat.py +0 -27
  206. ansible_test/_data/pytest/config/legacy.ini +0 -4
  207. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/WHEEL +0 -0
  208. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/entry_points.txt +0 -0
  209. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/COPYING +0 -0
  210. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  211. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
  212. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  213. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  214. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  215. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/top_level.txt +0 -0
@@ -139,8 +139,6 @@ class ActionModule(ActionBase):
139
139
  else:
140
140
  script_cmd = ' '.join([env_string, target_command])
141
141
 
142
- script_cmd = self._connection._shell.wrap_for_exec(script_cmd)
143
-
144
142
  exec_data = None
145
143
  # PowerShell runs the script in a special wrapper to enable things
146
144
  # like become and environment args
@@ -149,7 +147,7 @@ class ActionModule(ActionBase):
149
147
  pc = self._task
150
148
  exec_data = ps_manifest._create_powershell_wrapper(
151
149
  name=f"ansible.builtin.script.{pathlib.Path(source).stem}",
152
- module_data=to_bytes(script_cmd),
150
+ module_data=to_bytes(f"& {script_cmd}; exit $LASTEXITCODE"),
153
151
  module_path=source,
154
152
  module_args={},
155
153
  environment=env_dict,
@@ -23,7 +23,6 @@ from ansible.config.manager import ensure_type
23
23
  from ansible.errors import AnsibleError, AnsibleActionFail
24
24
  from ansible.module_utils.common.text.converters import to_bytes, to_text, to_native
25
25
  from ansible.module_utils.parsing.convert_bool import boolean
26
- from ansible.module_utils.six import string_types
27
26
  from ansible.plugins.action import ActionBase
28
27
  from ansible.template import trust_as_template
29
28
  from ansible._internal._templating import _template_vars
@@ -49,7 +48,7 @@ class ActionModule(ActionBase):
49
48
  'block_end_string', 'comment_start_string', 'comment_end_string'):
50
49
  if s_type in self._task.args:
51
50
  value = ensure_type(self._task.args[s_type], 'string')
52
- if value is not None and not isinstance(value, string_types):
51
+ if value is not None and not isinstance(value, str):
53
52
  raise AnsibleActionFail("%s is expected to be a string, but got %s instead" % (s_type, type(value)))
54
53
  self._task.args[s_type] = value
55
54
 
@@ -7,6 +7,7 @@ from __future__ import annotations
7
7
 
8
8
  import collections.abc as _c
9
9
  import os
10
+ from copy import deepcopy
10
11
 
11
12
  from ansible.errors import AnsibleActionFail
12
13
  from ansible.module_utils.parsing.convert_bool import boolean
@@ -53,7 +54,8 @@ class ActionModule(ActionBase):
53
54
  raise AnsibleActionFail(
54
55
  'body must be mapping, cannot be type %s' % body.__class__.__name__
55
56
  )
56
- for field, value in body.items():
57
+ new_body = deepcopy(body)
58
+ for field, value in new_body.items():
57
59
  if not isinstance(value, _c.MutableMapping):
58
60
  continue
59
61
  content = value.get('content')
@@ -70,7 +72,7 @@ class ActionModule(ActionBase):
70
72
  value['filename'] = tmp_src
71
73
  self._transfer_file(filename, tmp_src)
72
74
  self._fixup_perms2((self._connection._shell.tmpdir, tmp_src))
73
- kwargs['body'] = body
75
+ kwargs['body'] = new_body
74
76
 
75
77
  new_module_args = self._task.args | kwargs
76
78
 
@@ -162,6 +162,7 @@ class BaseFileCacheModule(BaseCacheModule):
162
162
  except OSError as ex:
163
163
  display.error_as_warning(f"Error in {self.plugin_name!r} cache plugin while trying to write to {tmpfile_path!r}.", exception=ex)
164
164
  try:
165
+ os.close(tmpfile_handle) # os.rename fails if handle is still open in WSL
165
166
  os.rename(tmpfile_path, cachefile)
166
167
  os.chmod(cachefile, mode=S_IRWU_RG_RO)
167
168
  except OSError as ex:
@@ -60,9 +60,6 @@ _YAML_BREAK_CHARS = '\n\x85\u2028\u2029' # NL, NEL, LS, PS
60
60
  _SPACE_BREAK_RE = re.compile(fr' +([{_YAML_BREAK_CHARS}])')
61
61
 
62
62
 
63
- _T_callable = t.TypeVar("_T_callable", bound=t.Callable)
64
-
65
-
66
63
  class _AnsibleCallbackDumper(_dumper.AnsibleDumper):
67
64
  def __init__(self, *args, lossy: bool = False, **kwargs):
68
65
  super().__init__(*args, **kwargs)
@@ -293,7 +290,11 @@ class CallbackBase(AnsiblePlugin):
293
290
  )
294
291
 
295
292
  if not indent and any(indent_conditions):
296
- indent = 4
293
+ try:
294
+ indent = self.get_option('result_indentation')
295
+ except KeyError:
296
+ # Callback does not declare result_indentation nor extend result_format_callback
297
+ indent = 4
297
298
  if pretty_results is False:
298
299
  # pretty_results=False overrides any specified indentation
299
300
  indent = None
@@ -394,8 +395,14 @@ class CallbackBase(AnsiblePlugin):
394
395
  # Callback does not declare pretty_results nor extend result_format_callback
395
396
  pretty_results = None
396
397
 
398
+ try:
399
+ indent = self.get_option('result_indentation')
400
+ except KeyError:
401
+ # Callback does not declare result_indentation nor extend result_format_callback
402
+ indent = 4
403
+
397
404
  if result_format == 'json':
398
- return json.dumps(diff, sort_keys=True, indent=4, separators=(u',', u': ')) + u'\n'
405
+ return json.dumps(diff, sort_keys=True, indent=indent, separators=(u',', u': ')) + u'\n'
399
406
 
400
407
  if result_format == 'yaml':
401
408
  # None is a sentinel in this case that indicates default behavior
@@ -407,7 +414,7 @@ class CallbackBase(AnsiblePlugin):
407
414
  allow_unicode=True,
408
415
  Dumper=functools.partial(_AnsibleCallbackDumper, lossy=lossy),
409
416
  default_flow_style=False,
410
- indent=4,
417
+ indent=indent,
411
418
  # sort_keys=sort_keys # This requires PyYAML>=5.1
412
419
  ),
413
420
  ' '
@@ -6,7 +6,6 @@ from __future__ import annotations
6
6
 
7
7
  import collections.abc as c
8
8
  import fcntl
9
- import io
10
9
  import os
11
10
  import shlex
12
11
  import typing as t
@@ -16,7 +15,7 @@ from functools import wraps
16
15
 
17
16
  from ansible import constants as C
18
17
  from ansible.errors import AnsibleValueOmittedError
19
- from ansible.module_utils.common.text.converters import to_bytes, to_text
18
+ from ansible.module_utils.common.text.converters import to_text
20
19
  from ansible.playbook.play_context import PlayContext
21
20
  from ansible.plugins import AnsiblePlugin
22
21
  from ansible.plugins.become import BecomeBase
@@ -32,9 +31,6 @@ __all__ = ['ConnectionBase', 'ensure_connect']
32
31
 
33
32
  BUFSIZE = 65536
34
33
 
35
- P = t.ParamSpec('P')
36
- T = t.TypeVar('T')
37
-
38
34
 
39
35
  class ConnectionKwargs(t.TypedDict):
40
36
  task_uuid: str
@@ -42,7 +38,7 @@ class ConnectionKwargs(t.TypedDict):
42
38
  shell: t.NotRequired[ShellBase]
43
39
 
44
40
 
45
- def ensure_connect(
41
+ def ensure_connect[T, **P](
46
42
  func: c.Callable[t.Concatenate[ConnectionBase, P], T],
47
43
  ) -> c.Callable[t.Concatenate[ConnectionBase, P], T]:
48
44
  @wraps(func)
@@ -135,7 +131,7 @@ class ConnectionBase(AnsiblePlugin):
135
131
  pass
136
132
 
137
133
  @abstractmethod
138
- def _connect(self: T) -> T:
134
+ def _connect[T](self: T) -> T:
139
135
  """Connect to the host we've been initialized with"""
140
136
 
141
137
  @ensure_connect
@@ -47,7 +47,6 @@ import typing as t
47
47
 
48
48
  import ansible.constants as C
49
49
  from ansible.errors import AnsibleError, AnsibleFileNotFound, AnsibleConnectionFailure
50
- from ansible.module_utils.six import text_type, binary_type
51
50
  from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
52
51
  from ansible.plugins.connection import ConnectionBase
53
52
  from ansible.utils.display import Display
@@ -100,7 +99,7 @@ class Connection(ConnectionBase):
100
99
  display.vvv(u"EXEC {0}".format(to_text(cmd)), host=self._play_context.remote_addr)
101
100
  display.debug("opening command with Popen()")
102
101
 
103
- if isinstance(cmd, (text_type, binary_type)):
102
+ if isinstance(cmd, (str, bytes)):
104
103
  cmd = to_text(cmd)
105
104
  else:
106
105
  cmd = map(to_text, cmd)
@@ -119,7 +118,7 @@ class Connection(ConnectionBase):
119
118
 
120
119
  p = subprocess.Popen(
121
120
  cmd,
122
- shell=isinstance(cmd, (text_type, binary_type)),
121
+ shell=isinstance(cmd, (str, bytes)),
123
122
  executable=executable,
124
123
  cwd=self.cwd,
125
124
  stdin=stdin,
@@ -494,7 +494,6 @@ class Connection(ConnectionBase):
494
494
  def put_file(self, in_path: str, out_path: str) -> None:
495
495
  super(Connection, self).put_file(in_path, out_path)
496
496
 
497
- out_path = self._shell._unquote(out_path)
498
497
  display.vvv("PUT %s TO %s" % (in_path, out_path), host=self._psrp_host)
499
498
 
500
499
  script, in_data = _bootstrap_powershell_script('psrp_put_file.ps1', {
@@ -554,7 +553,6 @@ class Connection(ConnectionBase):
554
553
  display.vvv("FETCH %s TO %s" % (in_path, out_path),
555
554
  host=self._psrp_host)
556
555
 
557
- in_path = self._shell._unquote(in_path)
558
556
  out_path = out_path.replace('\\', '/')
559
557
  b_out_path = to_bytes(out_path, errors='surrogate_or_strict')
560
558
 
@@ -34,8 +34,6 @@ DOCUMENTATION = """
34
34
  - name: inventory_hostname
35
35
  - name: ansible_host
36
36
  - name: ansible_ssh_host
37
- - name: delegated_vars['ansible_host']
38
- - name: delegated_vars['ansible_ssh_host']
39
37
  host_key_checking:
40
38
  description: Determines if SSH should reject or not a connection after checking host keys.
41
39
  default: True
@@ -443,7 +441,6 @@ from ansible.errors import (
443
441
  AnsibleError,
444
442
  AnsibleFileNotFound,
445
443
  )
446
- from ansible.module_utils.six import text_type, binary_type
447
444
  from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
448
445
  from ansible.plugins.connection import ConnectionBase, BUFSIZE
449
446
  from ansible.plugins.shell.powershell import _replace_stderr_clixml
@@ -461,8 +458,6 @@ else:
461
458
 
462
459
  display = Display()
463
460
 
464
- P = t.ParamSpec('P')
465
-
466
461
  # error messages that indicate 255 return code is not from ssh itself.
467
462
  b_NOT_SSH_ERRORS = (b'Traceback (most recent call last):', # Python-2.6 when there's an exception
468
463
  # while invoking a script via -m
@@ -549,7 +544,7 @@ def _handle_error(
549
544
  display.vvv(msg, host=host)
550
545
 
551
546
 
552
- def _ssh_retry(
547
+ def _ssh_retry[**P](
553
548
  func: c.Callable[t.Concatenate[Connection, P], tuple[int, bytes, bytes]],
554
549
  ) -> c.Callable[t.Concatenate[Connection, P], tuple[int, bytes, bytes]]:
555
550
  """
@@ -1126,7 +1121,7 @@ class Connection(ConnectionBase):
1126
1121
 
1127
1122
  p = None
1128
1123
 
1129
- if isinstance(cmd, (text_type, binary_type)):
1124
+ if isinstance(cmd, (str, bytes)):
1130
1125
  cmd = to_bytes(cmd)
1131
1126
  else:
1132
1127
  cmd = list(map(to_bytes, cmd))
@@ -768,7 +768,6 @@ class Connection(ConnectionBase):
768
768
 
769
769
  def put_file(self, in_path: str, out_path: str) -> None:
770
770
  super(Connection, self).put_file(in_path, out_path)
771
- out_path = self._shell._unquote(out_path)
772
771
  display.vvv('PUT "%s" TO "%s"' % (in_path, out_path), host=self._winrm_host)
773
772
  if not os.path.exists(to_bytes(in_path, errors='surrogate_or_strict')):
774
773
  raise AnsibleFileNotFound('file or module does not exist: "%s"' % to_native(in_path))
@@ -806,7 +805,6 @@ class Connection(ConnectionBase):
806
805
 
807
806
  def fetch_file(self, in_path: str, out_path: str) -> None:
808
807
  super(Connection, self).fetch_file(in_path, out_path)
809
- in_path = self._shell._unquote(in_path)
810
808
  out_path = out_path.replace('\\', '/')
811
809
  # consistent with other connection plugins, we assume the caller has created the target dir
812
810
  display.vvv('FETCH "%s" TO "%s"' % (in_path, out_path), host=self._winrm_host)
@@ -26,6 +26,21 @@ class ModuleDocFragment(object):
26
26
  - json
27
27
  - yaml
28
28
  version_added: '2.13'
29
+ result_indentation:
30
+ name: Indentation of the result
31
+ description:
32
+ - Allows to configure indentation for YAML and verbose/pretty JSON.
33
+ - Please note that for O(result_format=yaml), only values between 2 and 9 will be handled as expected by PyYAML.
34
+ If indentation is set to 1, or to 10 or larger, the first level of indentation will be used,
35
+ but all further indentations will be by 2 spaces.
36
+ type: int
37
+ default: 4
38
+ env:
39
+ - name: ANSIBLE_CALLBACK_RESULT_INDENTATION
40
+ ini:
41
+ - key: callback_result_indentation
42
+ section: defaults
43
+ version_added: '2.20'
29
44
  pretty_results:
30
45
  name: Configure output for readability
31
46
  description:
@@ -29,7 +29,6 @@ from ansible._internal._templating import _lazy_containers
29
29
  from ansible.errors import AnsibleFilterError, AnsibleTypeError, AnsibleTemplatePluginError
30
30
  from ansible.module_utils.datatag import native_type_name
31
31
  from ansible.module_utils.common.json import get_encoder, get_decoder
32
- from ansible.module_utils.six import string_types, integer_types, text_type
33
32
  from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
34
33
  from ansible.module_utils.common.collections import is_sequence
35
34
  from ansible.parsing.yaml.dumper import AnsibleDumper
@@ -279,7 +278,7 @@ def rand(environment, end, start=None, step=None, seed=None):
279
278
  r = SystemRandom()
280
279
  else:
281
280
  r = Random(seed)
282
- if isinstance(end, integer_types):
281
+ if isinstance(end, int):
283
282
  if not start:
284
283
  start = 0
285
284
  if not step:
@@ -556,7 +555,7 @@ def subelements(obj, subelements, skip_missing=False):
556
555
 
557
556
  if isinstance(subelements, list):
558
557
  subelement_list = subelements[:]
559
- elif isinstance(subelements, string_types):
558
+ elif isinstance(subelements, str):
560
559
  subelement_list = subelements.split('.')
561
560
  else:
562
561
  raise AnsibleTypeError('subelements must be a list or a string')
@@ -618,7 +617,7 @@ def list_of_dict_key_value_elements_to_dict(mylist, key_name='key', value_name='
618
617
  def path_join(paths):
619
618
  """ takes a sequence or a string, and return a concatenation
620
619
  of the different members """
621
- if isinstance(paths, string_types):
620
+ if isinstance(paths, str):
622
621
  return os.path.join(paths)
623
622
  if is_sequence(paths):
624
623
  return os.path.join(*paths)
@@ -810,7 +809,7 @@ class FilterModule(object):
810
809
  'dict2items': dict_to_list_of_dict_key_value_elements,
811
810
  'items2dict': list_of_dict_key_value_elements_to_dict,
812
811
  'subelements': subelements,
813
- 'split': partial(unicode_wrap, text_type.split),
812
+ 'split': partial(unicode_wrap, str.split),
814
813
  # FDI038 - replace this with a standard type compat shim
815
814
  'groupby': _cleansed_groupby,
816
815
 
@@ -13,25 +13,13 @@ from ansible.utils.display import Display
13
13
  display = Display()
14
14
 
15
15
 
16
- def do_vault(data, secret, salt=None, vault_id='filter_default', wrap_object=False, vaultid=None):
16
+ def do_vault(data, secret, salt=None, vault_id='filter_default', wrap_object=False):
17
17
  if not isinstance(secret, (str, bytes)):
18
18
  raise TypeError(f"Secret passed is required to be a string, instead we got {type(secret)}.")
19
19
 
20
20
  if not isinstance(data, (str, bytes)):
21
21
  raise TypeError(f"Can only vault strings, instead we got {type(data)}.")
22
22
 
23
- if vaultid is not None:
24
- display.deprecated(
25
- msg="Use of undocumented `vaultid`.",
26
- version="2.20",
27
- help_text="Use `vault_id` instead.",
28
- )
29
-
30
- if vault_id == 'filter_default':
31
- vault_id = vaultid
32
- else:
33
- display.warning("Ignoring vaultid as vault_id is already set.")
34
-
35
23
  vs = VaultSecret(to_bytes(secret))
36
24
  vl = VaultLib()
37
25
  try:
@@ -48,11 +36,11 @@ def do_vault(data, secret, salt=None, vault_id='filter_default', wrap_object=Fal
48
36
 
49
37
 
50
38
  @_template.accept_args_markers
51
- def do_unvault(vault, secret, vault_id='filter_default', vaultid=None):
39
+ def do_unvault(vault, secret, vault_id='filter_default'):
52
40
  if isinstance(vault, VaultExceptionMarker):
53
41
  vault = vault._disarm()
54
42
 
55
- if (first_marker := _template.get_first_marker_arg((vault, secret, vault_id, vaultid), {})) is not None:
43
+ if (first_marker := _template.get_first_marker_arg((vault, secret, vault_id), {})) is not None:
56
44
  return first_marker
57
45
 
58
46
  if not isinstance(secret, (str, bytes)):
@@ -61,18 +49,6 @@ def do_unvault(vault, secret, vault_id='filter_default', vaultid=None):
61
49
  if not isinstance(vault, (str, bytes)):
62
50
  raise TypeError(f"Vault should be in the form of a string, instead we got {type(vault)}.")
63
51
 
64
- if vaultid is not None:
65
- display.deprecated(
66
- msg="Use of undocumented `vaultid`.",
67
- version="2.20",
68
- help_text="Use `vault_id` instead.",
69
- )
70
-
71
- if vault_id == 'filter_default':
72
- vault_id = vaultid
73
- else:
74
- display.warning("Ignoring vaultid as vault_id is already set.")
75
-
76
52
  vs = VaultSecret(to_bytes(secret))
77
53
  vl = VaultLib([(vault_id, vs)])
78
54
 
@@ -29,7 +29,6 @@ from jinja2.filters import pass_environment
29
29
 
30
30
  from ansible.errors import AnsibleError
31
31
  from ansible.module_utils.common.text import formatters
32
- from ansible.module_utils.six import binary_type, text_type
33
32
  from ansible.utils.display import Display
34
33
 
35
34
  try:
@@ -180,7 +179,7 @@ def rekey_on_member(data, key, duplicates='error'):
180
179
 
181
180
  if isinstance(data, Mapping):
182
181
  iterate_over = data.values()
183
- elif isinstance(data, Iterable) and not isinstance(data, (text_type, binary_type)):
182
+ elif isinstance(data, Iterable) and not isinstance(data, (str, bytes)):
184
183
  iterate_over = data
185
184
  else:
186
185
  raise AnsibleError("Type is not a valid list, set, or dict")
@@ -1,5 +1,5 @@
1
1
  DOCUMENTATION:
2
- name: to_yaml
2
+ name: to_nice_yaml
3
3
  author: core team
4
4
  version_added: 'historical'
5
5
  short_description: Convert variable to YAML string
@@ -20,10 +20,38 @@ DOCUMENTATION:
20
20
  description: Affects sorting of dictionary keys.
21
21
  default: True
22
22
  type: bool
23
- #default_style=None, canonical=None, width=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, version=None, tags=None
23
+ default_style:
24
+ description:
25
+ - Indicates the style of the scalar.
26
+ choices:
27
+ - ''
28
+ - "'"
29
+ - '"'
30
+ - '|'
31
+ - '>'
32
+ type: string
33
+ canonical:
34
+ description:
35
+ - If set to V(True), export tag type to the output.
36
+ type: bool
37
+ width:
38
+ description: Set the preferred line width.
39
+ type: int
40
+ line_break:
41
+ description: Specify the line break.
42
+ type: string
43
+ encoding:
44
+ description: Specify the output encoding.
45
+ type: string
46
+ explicit_start:
47
+ description: If set to V(True), adds an explicit start using "---".
48
+ type: bool
49
+ explicit_end:
50
+ description: If set to V(True), adds an explicit end using "...".
51
+ type: bool
24
52
  notes:
25
53
  - More options may be available, see L(PyYAML documentation, https://pyyaml.org/wiki/PyYAMLDocumentation) for details.
26
- - 'These parameters to C(yaml.dump) will be ignored, as they are overridden internally: I(default_flow_style)'
54
+ - 'These parameters to C(yaml.dump) will be ignored, as they are overridden internally: I(default_flow_style), I(allow_unicode).'
27
55
 
28
56
  EXAMPLES: |
29
57
  # dump variable in a template to create a YAML document
@@ -20,21 +20,38 @@ DOCUMENTATION:
20
20
  description: Affects sorting of dictionary keys.
21
21
  default: True
22
22
  type: bool
23
+ default_style:
24
+ description:
25
+ - Indicates the style of the scalar.
26
+ choices:
27
+ - ''
28
+ - "'"
29
+ - '"'
30
+ - '|'
31
+ - '>'
32
+ type: string
33
+ canonical:
34
+ description:
35
+ - If set to V(True), export tag type to the output.
36
+ type: bool
37
+ width:
38
+ description: Set the preferred line width.
39
+ type: integer
40
+ line_break:
41
+ description: Specify the line break.
42
+ type: string
43
+ encoding:
44
+ description: Specify the output encoding.
45
+ type: string
46
+ explicit_start:
47
+ description: If set to V(True), adds an explicit start using "---".
48
+ type: bool
49
+ explicit_end:
50
+ description: If set to V(True), adds an explicit end using "...".
51
+ type: bool
23
52
  notes:
24
53
  - More options may be available, see L(PyYAML documentation, https://pyyaml.org/wiki/PyYAMLDocumentation) for details.
25
54
 
26
- # TODO: find docs for these
27
- #default_flow_style
28
- #default_style
29
- #canonical=None,
30
- #width=None,
31
- #line_break=None,
32
- #encoding=None,
33
- #explicit_start=None,
34
- #explicit_end=None,
35
- #version=None,
36
- #tags=None
37
-
38
55
  EXAMPLES: |
39
56
  # dump variable in a template to create a YAML document
40
57
  {{ github_workflow | to_yaml }}
@@ -34,7 +34,6 @@ from ansible.parsing.dataloader import DataLoader
34
34
  from ansible.plugins import AnsiblePlugin, _ConfigurablePlugin
35
35
  from ansible.plugins.cache import CachePluginAdjudicator
36
36
  from ansible.module_utils.common.text.converters import to_bytes, to_native
37
- from ansible.module_utils.six import string_types
38
37
  from ansible.utils.display import Display
39
38
  from ansible.utils.vars import combine_vars, load_extra_vars
40
39
 
@@ -439,7 +438,7 @@ class Constructable(_BaseInventoryPlugin):
439
438
  new_raw_group_names = []
440
439
  if use_default:
441
440
  new_raw_group_names.append(default_value_name)
442
- elif isinstance(key, string_types):
441
+ elif isinstance(key, str):
443
442
  new_raw_group_names.append(key)
444
443
  elif isinstance(key, list):
445
444
  for name in key:
@@ -89,8 +89,6 @@ import tomllib
89
89
  from collections.abc import MutableMapping, MutableSequence
90
90
 
91
91
  from ansible.errors import AnsibleFileNotFound, AnsibleParserError
92
- from ansible.module_utils.common.text.converters import to_bytes, to_native
93
- from ansible.module_utils.six import string_types
94
92
  from ansible.plugins.inventory import BaseFileInventoryPlugin
95
93
  from ansible.utils.display import Display
96
94
 
@@ -147,11 +145,10 @@ class InventoryModule(BaseFileInventoryPlugin):
147
145
  )
148
146
 
149
147
  def _load_file(self, file_name):
150
- if not file_name or not isinstance(file_name, string_types):
151
- raise AnsibleParserError("Invalid filename: '%s'" % to_native(file_name))
148
+ if not file_name or not isinstance(file_name, str):
149
+ raise AnsibleParserError("Invalid filename: '%s'" % file_name)
152
150
 
153
- b_file_name = to_bytes(self.loader.path_dwim(file_name))
154
- if not self.loader.path_exists(b_file_name):
151
+ if not self.loader.path_exists(file_name):
155
152
  raise AnsibleFileNotFound("Unable to retrieve file contents", file_name=file_name)
156
153
 
157
154
  try:
@@ -70,7 +70,6 @@ import os
70
70
  from collections.abc import MutableMapping
71
71
 
72
72
  from ansible.errors import AnsibleError, AnsibleParserError
73
- from ansible.module_utils.six import string_types
74
73
  from ansible.module_utils.common.text.converters import to_native, to_text
75
74
  from ansible.plugins.inventory import BaseFileInventoryPlugin
76
75
 
@@ -136,7 +135,7 @@ class InventoryModule(BaseFileInventoryPlugin):
136
135
  for section in ['vars', 'children', 'hosts']:
137
136
  if section in group_data:
138
137
  # convert strings to dicts as these are allowed
139
- if isinstance(group_data[section], string_types):
138
+ if isinstance(group_data[section], str):
140
139
  group_data[section] = {group_data[section]: None}
141
140
 
142
141
  if not isinstance(group_data[section], (MutableMapping, NoneType)): # type: ignore[misc]
ansible/plugins/loader.py CHANGED
@@ -27,7 +27,6 @@ from ansible import _internal, constants as C
27
27
  from ansible.errors import AnsibleError, AnsiblePluginCircularRedirect, AnsiblePluginRemovedError, AnsibleCollectionUnsupportedVersionError
28
28
  from ansible.module_utils.common.text.converters import to_bytes, to_text, to_native
29
29
  from ansible.module_utils.datatag import deprecator_from_collection_name
30
- from ansible.module_utils.six import string_types
31
30
  from ansible.parsing.yaml.loader import AnsibleLoader
32
31
  from ansible._internal._yaml._loader import AnsibleInstrumentedLoader
33
32
  from ansible.plugins import get_plugin_class, MODULE_CACHE, PATH_CACHE, PLUGIN_PATH_CACHE, AnsibleJinja2Plugin
@@ -97,7 +96,7 @@ def get_shell_plugin(shell_type=None, executable=None):
97
96
 
98
97
  # mostly for backwards compat
99
98
  if executable:
100
- if isinstance(executable, string_types):
99
+ if isinstance(executable, str):
101
100
  shell_filename = os.path.basename(executable)
102
101
  try:
103
102
  shell = shell_loader.get(shell_filename)
@@ -518,7 +517,7 @@ class PluginLoader:
518
517
  # filename, cn = find_plugin_docfile( name, type_name, self, [os.path.dirname(path)], C.YAML_DOC_EXTENSIONS)
519
518
 
520
519
  if dstring:
521
- add_fragments(dstring, path, fragment_loader=fragment_loader, is_module=(type_name == 'module'))
520
+ add_fragments(dstring, path, fragment_loader=fragment_loader, is_module=(type_name == 'module'), section='DOCUMENTATION')
522
521
 
523
522
  if 'options' in dstring and isinstance(dstring['options'], dict):
524
523
  C.config.initialize_plugin_configuration_definitions(type_name, name, dstring['options'])
@@ -1675,7 +1674,7 @@ def _configure_collection_loader(prefix_collections_path=None):
1675
1674
 
1676
1675
  # insert the internal ansible._protomatter collection up front
1677
1676
  paths = [os.path.dirname(_internal.__file__)] + list(prefix_collections_path) + C.COLLECTIONS_PATHS
1678
- finder = _AnsibleCollectionFinder(paths, C.COLLECTIONS_SCAN_SYS_PATH)
1677
+ finder = _AnsibleCollectionFinder(paths, C.COLLECTIONS_SCAN_SYS_PATH, internal_collections=paths[0])
1679
1678
  finder._install()
1680
1679
 
1681
1680
  # this should succeed now
@@ -134,7 +134,6 @@ import hashlib
134
134
 
135
135
  from ansible.errors import AnsibleError, AnsibleAssertionError
136
136
  from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
137
- from ansible.module_utils.six import string_types
138
137
  from ansible.parsing.splitter import parse_kv
139
138
  from ansible.plugins.lookup import LookupBase
140
139
  from ansible.utils.encrypt import BaseHash, do_encrypt, random_password, random_salt
@@ -335,7 +334,7 @@ class LookupModule(LookupBase):
335
334
 
336
335
  # chars still might need more
337
336
  chars = params.get('chars', self.get_option('chars'))
338
- if chars and isinstance(chars, string_types):
337
+ if chars and isinstance(chars, str):
339
338
  tmp_chars = []
340
339
  if u',,' in chars:
341
340
  tmp_chars.append(u',')
@@ -83,7 +83,6 @@ _list:
83
83
  """
84
84
 
85
85
  from ansible.errors import AnsibleError
86
- from ansible.module_utils.six import string_types
87
86
  from ansible.module_utils.parsing.convert_bool import boolean
88
87
  from ansible.plugins.lookup import LookupBase
89
88
 
@@ -104,7 +103,7 @@ class LookupModule(LookupBase):
104
103
  _raise_terms_error()
105
104
 
106
105
  # first term should be a list (or dict), second a string holding the subkey
107
- if not isinstance(terms[0], (list, dict)) or not isinstance(terms[1], string_types):
106
+ if not isinstance(terms[0], (list, dict)) or not isinstance(terms[1], str):
108
107
  _raise_terms_error("first a dict or a list, second a string pointing to the subkey")
109
108
  subelements = terms[1].split(".")
110
109
 
@@ -122,7 +121,7 @@ class LookupModule(LookupBase):
122
121
  flags = {}
123
122
  if len(terms) == 3:
124
123
  flags = terms[2]
125
- if not isinstance(flags, dict) and not all(isinstance(key, string_types) and key in FLAGS for key in flags):
124
+ if not isinstance(flags, dict) and not all(isinstance(key, str) and key in FLAGS for key in flags):
126
125
  _raise_terms_error("the optional third item must be a dict with flags %s" % FLAGS)
127
126
 
128
127
  # build_items
@@ -164,7 +164,7 @@ options:
164
164
  description:
165
165
  - SSL/TLS Ciphers to use for the request
166
166
  - 'When a list is provided, all ciphers are joined in order with C(:)'
167
- - See the L(OpenSSL Cipher List Format,https://www.openssl.org/docs/manmaster/man1/openssl-ciphers.html#CIPHER-LIST-FORMAT)
167
+ - See the L(OpenSSL Cipher List Format,https://docs.openssl.org/master/man1/openssl-ciphers/#cipher-list-format)
168
168
  for more details.
169
169
  - The available ciphers is dependent on the Python and OpenSSL/LibreSSL versions
170
170
  type: list