ansible-core 2.19.2__py3-none-any.whl → 2.20.0b1__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 (202) 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/_display_utils.py +145 -0
  5. ansible/_internal/_json/__init__.py +3 -4
  6. ansible/_internal/_templating/_engine.py +1 -1
  7. ansible/_internal/_templating/_jinja_plugins.py +1 -2
  8. ansible/_internal/_wrapt.py +105 -301
  9. ansible/cli/__init__.py +11 -10
  10. ansible/cli/adhoc.py +1 -2
  11. ansible/cli/arguments/option_helpers.py +1 -1
  12. ansible/cli/config.py +5 -6
  13. ansible/cli/doc.py +67 -67
  14. ansible/cli/galaxy.py +15 -24
  15. ansible/cli/inventory.py +0 -1
  16. ansible/cli/playbook.py +0 -1
  17. ansible/cli/pull.py +0 -1
  18. ansible/cli/scripts/ansible_connection_cli_stub.py +1 -1
  19. ansible/config/base.yml +1 -25
  20. ansible/config/manager.py +0 -2
  21. ansible/executor/play_iterator.py +42 -20
  22. ansible/executor/playbook_executor.py +0 -9
  23. ansible/executor/powershell/async_watchdog.ps1 +24 -4
  24. ansible/executor/task_executor.py +32 -22
  25. ansible/executor/task_queue_manager.py +1 -3
  26. ansible/galaxy/api.py +33 -80
  27. ansible/galaxy/collection/__init__.py +4 -17
  28. ansible/galaxy/dependency_resolution/dataclasses.py +0 -10
  29. ansible/galaxy/dependency_resolution/providers.py +1 -2
  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 +27 -24
  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/urls.py +6 -2
  58. ansible/module_utils/yumdnf.py +0 -5
  59. ansible/modules/apt.py +18 -13
  60. ansible/modules/apt_repository.py +1 -1
  61. ansible/modules/assemble.py +5 -9
  62. ansible/modules/blockinfile.py +39 -23
  63. ansible/modules/cron.py +26 -35
  64. ansible/modules/deb822_repository.py +83 -12
  65. ansible/modules/dnf.py +3 -7
  66. ansible/modules/dnf5.py +4 -6
  67. ansible/modules/expect.py +0 -3
  68. ansible/modules/find.py +1 -2
  69. ansible/modules/get_url.py +1 -1
  70. ansible/modules/git.py +4 -5
  71. ansible/modules/include_vars.py +1 -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/mod_args.py +3 -0
  85. ansible/parsing/vault/__init__.py +1 -2
  86. ansible/playbook/base.py +8 -56
  87. ansible/playbook/block.py +0 -60
  88. ansible/playbook/collectionsearch.py +1 -2
  89. ansible/playbook/handler.py +1 -7
  90. ansible/playbook/helpers.py +0 -7
  91. ansible/playbook/included_file.py +1 -1
  92. ansible/playbook/play.py +103 -37
  93. ansible/playbook/play_context.py +4 -0
  94. ansible/playbook/role/__init__.py +10 -65
  95. ansible/playbook/role/definition.py +3 -4
  96. ansible/playbook/role/include.py +2 -3
  97. ansible/playbook/role/metadata.py +1 -12
  98. ansible/playbook/role/requirement.py +1 -2
  99. ansible/playbook/role_include.py +1 -2
  100. ansible/playbook/taggable.py +16 -5
  101. ansible/playbook/task.py +51 -55
  102. ansible/plugins/action/__init__.py +20 -19
  103. ansible/plugins/action/add_host.py +1 -2
  104. ansible/plugins/action/fetch.py +2 -4
  105. ansible/plugins/action/group_by.py +1 -2
  106. ansible/plugins/action/include_vars.py +20 -22
  107. ansible/plugins/action/script.py +1 -3
  108. ansible/plugins/action/template.py +1 -2
  109. ansible/plugins/action/uri.py +4 -2
  110. ansible/plugins/cache/__init__.py +1 -0
  111. ansible/plugins/callback/__init__.py +13 -6
  112. ansible/plugins/connection/__init__.py +3 -7
  113. ansible/plugins/connection/local.py +2 -3
  114. ansible/plugins/connection/psrp.py +0 -2
  115. ansible/plugins/connection/ssh.py +2 -7
  116. ansible/plugins/connection/winrm.py +0 -2
  117. ansible/plugins/doc_fragments/result_format_callback.py +15 -0
  118. ansible/plugins/filter/core.py +4 -5
  119. ansible/plugins/filter/encryption.py +3 -27
  120. ansible/plugins/filter/mathstuff.py +1 -2
  121. ansible/plugins/filter/to_nice_yaml.yml +31 -3
  122. ansible/plugins/filter/to_yaml.yml +29 -12
  123. ansible/plugins/inventory/__init__.py +1 -2
  124. ansible/plugins/inventory/script.py +2 -1
  125. ansible/plugins/inventory/toml.py +3 -6
  126. ansible/plugins/inventory/yaml.py +1 -2
  127. ansible/plugins/list.py +10 -3
  128. ansible/plugins/loader.py +6 -6
  129. ansible/plugins/lookup/password.py +1 -2
  130. ansible/plugins/lookup/subelements.py +2 -3
  131. ansible/plugins/lookup/url.py +1 -1
  132. ansible/plugins/lookup/varnames.py +1 -2
  133. ansible/plugins/shell/__init__.py +9 -4
  134. ansible/plugins/shell/powershell.py +8 -24
  135. ansible/plugins/strategy/__init__.py +6 -3
  136. ansible/plugins/test/core.py +4 -1
  137. ansible/plugins/test/regex.yml +18 -6
  138. ansible/release.py +2 -2
  139. ansible/template/__init__.py +3 -7
  140. ansible/utils/collection_loader/_collection_config.py +5 -0
  141. ansible/utils/collection_loader/_collection_finder.py +11 -14
  142. ansible/utils/context_objects.py +7 -4
  143. ansible/utils/display.py +28 -167
  144. ansible/utils/encrypt.py +0 -5
  145. ansible/utils/helpers.py +6 -2
  146. ansible/utils/jsonrpc.py +7 -3
  147. ansible/utils/plugin_docs.py +49 -38
  148. ansible/utils/ssh_functions.py +0 -19
  149. ansible/utils/unsafe_proxy.py +7 -7
  150. ansible/vars/clean.py +2 -3
  151. ansible/vars/manager.py +27 -20
  152. ansible/vars/plugins.py +1 -31
  153. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/METADATA +3 -3
  154. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/RECORD +200 -200
  155. ansible_test/_data/completion/docker.txt +7 -7
  156. ansible_test/_data/completion/network.txt +0 -1
  157. ansible_test/_data/completion/remote.txt +4 -4
  158. ansible_test/_data/requirements/ansible-test.txt +1 -1
  159. ansible_test/_data/requirements/sanity.changelog.txt +1 -1
  160. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  161. ansible_test/_data/requirements/sanity.pylint.txt +4 -4
  162. ansible_test/_internal/cache.py +2 -5
  163. ansible_test/_internal/cli/compat.py +1 -1
  164. ansible_test/_internal/commands/coverage/combine.py +1 -3
  165. ansible_test/_internal/commands/integration/__init__.py +3 -7
  166. ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
  167. ansible_test/_internal/commands/integration/coverage.py +1 -3
  168. ansible_test/_internal/commands/integration/filters.py +5 -10
  169. ansible_test/_internal/commands/sanity/validate_modules.py +1 -5
  170. ansible_test/_internal/commands/units/__init__.py +1 -13
  171. ansible_test/_internal/completion.py +2 -5
  172. ansible_test/_internal/config.py +2 -7
  173. ansible_test/_internal/coverage_util.py +1 -1
  174. ansible_test/_internal/delegation.py +2 -0
  175. ansible_test/_internal/docker_util.py +1 -1
  176. ansible_test/_internal/host_profiles.py +6 -11
  177. ansible_test/_internal/provider/__init__.py +2 -5
  178. ansible_test/_internal/provisioning.py +2 -5
  179. ansible_test/_internal/pypi_proxy.py +1 -1
  180. ansible_test/_internal/target.py +2 -6
  181. ansible_test/_internal/thread.py +1 -4
  182. ansible_test/_internal/util.py +9 -14
  183. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +14 -19
  184. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +30 -27
  185. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +31 -18
  186. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +1 -2
  187. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +59 -71
  188. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -2
  189. ansible_test/_util/target/cli/ansible_test_cli_stub.py +4 -2
  190. ansible_test/_util/target/common/constants.py +2 -2
  191. ansible_test/_util/target/setup/bootstrap.sh +0 -6
  192. ansible/utils/py3compat.py +0 -27
  193. ansible_test/_data/pytest/config/legacy.ini +0 -4
  194. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/WHEEL +0 -0
  195. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/entry_points.txt +0 -0
  196. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/COPYING +0 -0
  197. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  198. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
  199. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  200. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  201. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  202. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/top_level.txt +0 -0
ansible/modules/uri.py CHANGED
@@ -438,13 +438,12 @@ import os
438
438
  import re
439
439
  import shutil
440
440
  import tempfile
441
+ from collections.abc import Mapping, Sequence
441
442
  from datetime import datetime, timezone
443
+ from urllib.parse import urlencode, urljoin
442
444
 
443
445
  from ansible.module_utils.basic import AnsibleModule, sanitize_keys
444
- from ansible.module_utils.six import binary_type, iteritems, string_types
445
- from ansible.module_utils.six.moves.urllib.parse import urlencode, urljoin
446
446
  from ansible.module_utils.common.text.converters import to_native, to_text
447
- from ansible.module_utils.six.moves.collections_abc import Mapping, Sequence
448
447
  from ansible.module_utils.urls import (
449
448
  fetch_url,
450
449
  get_response_filename,
@@ -479,7 +478,7 @@ def write_file(module, dest, content, resp):
479
478
  try:
480
479
  fd, tmpsrc = tempfile.mkstemp(dir=module.tmpdir)
481
480
  with os.fdopen(fd, 'wb') as f:
482
- if isinstance(content, binary_type):
481
+ if isinstance(content, bytes):
483
482
  f.write(content)
484
483
  else:
485
484
  shutil.copyfileobj(content, f)
@@ -521,14 +520,14 @@ def kv_list(data):
521
520
 
522
521
  def form_urlencoded(body):
523
522
  """ Convert data into a form-urlencoded string """
524
- if isinstance(body, string_types):
523
+ if isinstance(body, str):
525
524
  return body
526
525
 
527
526
  if isinstance(body, (Mapping, Sequence)):
528
527
  result = []
529
528
  # Turn a list of lists into a list of tuples that urlencode accepts
530
529
  for key, values in kv_list(body):
531
- if isinstance(values, string_types) or not isinstance(values, (Mapping, Sequence)):
530
+ if isinstance(values, str) or not isinstance(values, (Mapping, Sequence)):
532
531
  values = [values]
533
532
  for value in values:
534
533
  if value is not None:
@@ -641,12 +640,12 @@ def main():
641
640
 
642
641
  if body_format == 'json':
643
642
  # Encode the body unless its a string, then assume it is pre-formatted JSON
644
- if not isinstance(body, string_types):
643
+ if not isinstance(body, str):
645
644
  body = json.dumps(body)
646
645
  if 'content-type' not in [header.lower() for header in dict_headers]:
647
646
  dict_headers['Content-Type'] = 'application/json'
648
647
  elif body_format == 'form-urlencoded':
649
- if not isinstance(body, string_types):
648
+ if not isinstance(body, str):
650
649
  try:
651
650
  body = form_urlencoded(body)
652
651
  except ValueError as e:
@@ -747,7 +746,7 @@ def main():
747
746
  # In python3, the headers are title cased. Lowercase them to be
748
747
  # compatible with the python2 behaviour.
749
748
  uresp = {}
750
- for key, value in iteritems(resp):
749
+ for key, value in resp.items():
751
750
  ukey = key.replace("-", "_").lower()
752
751
  uresp[ukey] = value
753
752
 
@@ -755,7 +754,7 @@ def main():
755
754
  uresp['location'] = urljoin(url, uresp['location'])
756
755
 
757
756
  # Default content_encoding to try
758
- if isinstance(content, binary_type):
757
+ if isinstance(content, bytes):
759
758
  u_content = to_text(content, encoding=content_encoding)
760
759
  if maybe_json:
761
760
  try:
ansible/modules/user.py CHANGED
@@ -2504,11 +2504,10 @@ class DarwinUser(User):
2504
2504
  Please note that password must be cleartext.
2505
2505
  """
2506
2506
  # some documentation on how is stored passwords on OSX:
2507
- # http://blog.lostpassword.com/2012/07/cracking-mac-os-x-lion-accounts-passwords/
2508
2507
  # http://null-byte.wonderhowto.com/how-to/hack-mac-os-x-lion-passwords-0130036/
2509
2508
  # http://pastebin.com/RYqxi7Ca
2510
2509
  # on OSX 10.8+ hash is SALTED-SHA512-PBKDF2
2511
- # https://pythonhosted.org/passlib/lib/passlib.hash.pbkdf2_digest.html
2510
+ # https://passlib.readthedocs.io/en/stable/lib/passlib.hash.pbkdf2_digest.html
2512
2511
  # https://gist.github.com/nueh/8252572
2513
2512
  cmd = self._get_dscl()
2514
2513
  if self.password:
@@ -216,13 +216,13 @@ elapsed:
216
216
  type: int
217
217
  sample: 23
218
218
  match_groups:
219
- description: Tuple containing all the subgroups of the match as returned by U(https://docs.python.org/3/library/re.html#re.MatchObject.groups)
219
+ description: Tuple containing all the subgroups of the match as returned by U(https://docs.python.org/3/library/re.html#re.Match.groups)
220
220
  returned: always
221
221
  type: list
222
222
  sample: ['match 1', 'match 2']
223
223
  match_groupdict:
224
224
  description: Dictionary containing all the named subgroups of the match, keyed by the subgroup name,
225
- as returned by U(https://docs.python.org/3/library/re.html#re.MatchObject.groupdict)
225
+ as returned by U(https://docs.python.org/3/library/re.html#re.Match.groupdict)
226
226
  returned: always
227
227
  type: dict
228
228
  sample:
@@ -104,9 +104,10 @@ EXAMPLES = r"""
104
104
  - cmd.exe /c winrm.cmd quickconfig -quiet -force
105
105
  delegate_to: localhost
106
106
 
107
- - name: Wait for system to become reachable over WinRM
107
+ - name: Wait for system to become reachable over WinRM, polling every 10 seconds
108
108
  ansible.builtin.wait_for_connection:
109
109
  timeout: 900
110
+ sleep: 10
110
111
 
111
112
  - name: Gather facts for first time
112
113
  ansible.builtin.setup:
@@ -183,14 +183,6 @@ options:
183
183
  - This parameter is deprecated as it has no effect with dnf as an underlying package manager
184
184
  and will be removed in ansible-core 2.22.
185
185
  type: bool
186
- keepcache:
187
- description:
188
- - Either V(1) or V(0). Determines whether or not yum keeps the cache of
189
- headers and packages after successful installation.
190
- - This parameter is deprecated as it is only valid in the main configuration
191
- and will be removed in ansible-core 2.20.
192
- choices: ['0', '1']
193
- type: str
194
186
  metadata_expire:
195
187
  description:
196
188
  - Time (in seconds) after which the metadata will expire.
@@ -466,13 +458,7 @@ class YumRepo:
466
458
  for key, value in sorted(self.params.items()):
467
459
  if value is None:
468
460
  continue
469
- if key == 'keepcache':
470
- self.module.deprecate(
471
- "'keepcache' parameter is deprecated as it is only valid in "
472
- "the main configuration.",
473
- version='2.20'
474
- )
475
- elif key == 'async':
461
+ if key == 'async':
476
462
  self.module.deprecate(
477
463
  "'async' parameter is deprecated as it has been removed on systems supported by ansible-core",
478
464
  version='2.22',
@@ -557,7 +543,6 @@ def main():
557
543
  includepkgs=dict(type='list', elements='str'),
558
544
  ip_resolve=dict(choices=['4', '6', 'IPv4', 'IPv6', 'whatever']),
559
545
  keepalive=dict(type='bool'),
560
- keepcache=dict(choices=['0', '1']),
561
546
  metadata_expire=dict(),
562
547
  metadata_expire_filter=dict(
563
548
  choices=[
@@ -2,7 +2,6 @@
2
2
  # Copyright: (c) 2017, Ansible Project
3
3
  # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4
4
 
5
- from __future__ import annotations
6
5
  from __future__ import annotations
7
6
 
8
7
  import copy
@@ -19,7 +18,6 @@ from ansible._internal._errors import _error_utils
19
18
  from ansible.module_utils.basic import is_executable
20
19
  from ansible._internal._datatag._tags import Origin, TrustedAsTemplate, SourceWasEncrypted
21
20
  from ansible.module_utils._internal._datatag import AnsibleTagHelper
22
- from ansible.module_utils.six import binary_type, text_type
23
21
  from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
24
22
  from ansible.parsing.quoting import unquote
25
23
  from ansible.parsing.utils.yaml import from_yaml
@@ -32,7 +30,7 @@ display = Display()
32
30
 
33
31
  # Tries to determine if a path is inside a role, last dir must be 'tasks'
34
32
  # this is not perfect but people should really avoid 'tasks' dirs outside roles when using Ansible.
35
- RE_TASKS = re.compile(u'(?:^|%s)+tasks%s?$' % (os.path.sep, os.path.sep))
33
+ RE_TASKS = re.compile('(?:^|%s)+tasks%s?$' % (os.path.sep, os.path.sep))
36
34
 
37
35
 
38
36
  class DataLoader:
@@ -49,28 +47,27 @@ class DataLoader:
49
47
  Usage:
50
48
 
51
49
  dl = DataLoader()
52
- # optionally: dl.set_vault_secrets([('default', ansible.parsing.vault.PrompVaultSecret(...),)])
50
+ # optionally: dl.set_vault_secrets([('default', ansible.parsing.vault.PromptVaultSecret(...),)])
53
51
  ds = dl.load('...')
54
52
  ds = dl.load_from_file('/path/to/file')
55
53
  """
56
54
 
57
- def __init__(self):
55
+ def __init__(self) -> None:
58
56
 
59
- self._basedir = '.'
57
+ self._basedir: str = '.'
60
58
 
61
59
  # NOTE: not effective with forks as the main copy does not get updated.
62
60
  # avoids rereading files
63
- self._FILE_CACHE = dict()
61
+ self._FILE_CACHE: dict[str, object] = {}
64
62
 
65
63
  # NOTE: not thread safe, also issues with forks not returning data to main proc
66
64
  # so they need to be cleaned independently. See WorkerProcess for example.
67
65
  # used to keep track of temp files for cleaning
68
- self._tempfiles = set()
66
+ self._tempfiles: set[str] = set()
69
67
 
70
68
  # initialize the vault stuff with an empty password
71
69
  # TODO: replace with a ref to something that can get the password
72
70
  # a creds/auth provider
73
- self._vaults = {}
74
71
  self._vault = VaultLib()
75
72
  self.set_vault_secrets(None)
76
73
 
@@ -230,23 +227,19 @@ class DataLoader:
230
227
 
231
228
  def set_basedir(self, basedir: str) -> None:
232
229
  """ sets the base directory, used to find files when a relative path is given """
233
-
234
- if basedir is not None:
235
- self._basedir = to_text(basedir)
230
+ self._basedir = basedir
236
231
 
237
232
  def path_dwim(self, given: str) -> str:
238
233
  """
239
234
  make relative paths work like folks expect.
240
235
  """
241
236
 
242
- given = to_text(given, errors='surrogate_or_strict')
243
237
  given = unquote(given)
244
238
 
245
- if given.startswith(to_text(os.path.sep)) or given.startswith(u'~'):
239
+ if given.startswith(os.path.sep) or given.startswith('~'):
246
240
  path = given
247
241
  else:
248
- basedir = to_text(self._basedir, errors='surrogate_or_strict')
249
- path = os.path.join(basedir, given)
242
+ path = os.path.join(self._basedir, given)
250
243
 
251
244
  return unfrackpath(path, follow=False)
252
245
 
@@ -294,10 +287,9 @@ class DataLoader:
294
287
  """
295
288
 
296
289
  search = []
297
- source = to_text(source, errors='surrogate_or_strict')
298
290
 
299
291
  # I have full path, nothing else needs to be looked at
300
- if source.startswith(to_text(os.path.sep)) or source.startswith(u'~'):
292
+ if source.startswith(os.path.sep) or source.startswith('~'):
301
293
  search.append(unfrackpath(source, follow=False))
302
294
  else:
303
295
  # base role/play path + templates/files/vars + relative filename
@@ -364,7 +356,7 @@ class DataLoader:
364
356
  if os.path.exists(to_bytes(test_path, errors='surrogate_or_strict')):
365
357
  result = test_path
366
358
  else:
367
- display.debug(u'evaluation_path:\n\t%s' % '\n\t'.join(paths))
359
+ display.debug('evaluation_path:\n\t%s' % '\n\t'.join(paths))
368
360
  for path in paths:
369
361
  upath = unfrackpath(path, follow=False)
370
362
  b_upath = to_bytes(upath, errors='surrogate_or_strict')
@@ -385,9 +377,9 @@ class DataLoader:
385
377
  search.append(os.path.join(to_bytes(self.get_basedir(), errors='surrogate_or_strict'), b_dirname, b_source))
386
378
  search.append(os.path.join(to_bytes(self.get_basedir(), errors='surrogate_or_strict'), b_source))
387
379
 
388
- display.debug(u'search_path:\n\t%s' % to_text(b'\n\t'.join(search)))
380
+ display.debug('search_path:\n\t%s' % to_text(b'\n\t'.join(search)))
389
381
  for b_candidate in search:
390
- display.vvvvv(u'looking for "%s" at "%s"' % (source, to_text(b_candidate)))
382
+ display.vvvvv('looking for "%s" at "%s"' % (source, to_text(b_candidate)))
391
383
  if os.path.exists(b_candidate):
392
384
  result = to_text(b_candidate)
393
385
  break
@@ -418,11 +410,10 @@ class DataLoader:
418
410
  Temporary files are cleanup in the destructor
419
411
  """
420
412
 
421
- if not file_path or not isinstance(file_path, (binary_type, text_type)):
413
+ if not file_path or not isinstance(file_path, (bytes, str)):
422
414
  raise AnsibleParserError("Invalid filename: '%s'" % to_native(file_path))
423
415
 
424
- b_file_path = to_bytes(file_path, errors='surrogate_or_strict')
425
- if not self.path_exists(b_file_path) or not self.is_file(b_file_path):
416
+ if not self.path_exists(file_path) or not self.is_file(file_path):
426
417
  raise AnsibleFileNotFound(file_name=file_path)
427
418
 
428
419
  real_path = self.path_dwim(file_path)
@@ -480,7 +471,7 @@ class DataLoader:
480
471
  """
481
472
 
482
473
  b_path = to_bytes(os.path.join(path, name))
483
- found = []
474
+ found: list[str] = []
484
475
 
485
476
  if extensions is None:
486
477
  # Look for file with no extension first to find dir before file
@@ -489,27 +480,29 @@ class DataLoader:
489
480
  for ext in extensions:
490
481
 
491
482
  if '.' in ext:
492
- full_path = b_path + to_bytes(ext)
483
+ b_full_path = b_path + to_bytes(ext)
493
484
  elif ext:
494
- full_path = b'.'.join([b_path, to_bytes(ext)])
485
+ b_full_path = b'.'.join([b_path, to_bytes(ext)])
495
486
  else:
496
- full_path = b_path
487
+ b_full_path = b_path
488
+
489
+ full_path = to_text(b_full_path)
497
490
 
498
491
  if self.path_exists(full_path):
499
492
  if self.is_directory(full_path):
500
493
  if allow_dir:
501
- found.extend(self._get_dir_vars_files(to_text(full_path), extensions))
494
+ found.extend(self._get_dir_vars_files(full_path, extensions))
502
495
  else:
503
496
  continue
504
497
  else:
505
- found.append(to_text(full_path))
498
+ found.append(full_path)
506
499
  break
507
500
  return found
508
501
 
509
502
  def _get_dir_vars_files(self, path: str, extensions: list[str]) -> list[str]:
510
503
  found = []
511
504
  for spath in sorted(self.list_directory(path)):
512
- if not spath.startswith(u'.') and not spath.endswith(u'~'): # skip hidden and backups
505
+ if not spath.startswith('.') and not spath.endswith('~'): # skip hidden and backups
513
506
 
514
507
  ext = os.path.splitext(spath)[-1]
515
508
  full_spath = os.path.join(path, spath)
@@ -130,6 +130,7 @@ class ModuleArgsParser:
130
130
  # HACK: why are these not FieldAttributes on task with a post-validate to check usage?
131
131
  self._task_attrs.update(['local_action', 'static'])
132
132
  self._task_attrs = frozenset(self._task_attrs)
133
+ self._resolved_action = None
133
134
 
134
135
  def _split_module_string(self, module_string: str) -> tuple[str, str]:
135
136
  """
@@ -344,6 +345,8 @@ class ModuleArgsParser:
344
345
  raise e
345
346
 
346
347
  is_action_candidate = context.resolved and bool(context.redirect_list)
348
+ if is_action_candidate:
349
+ self._resolved_action = context.resolved_fqcn
347
350
 
348
351
  if is_action_candidate:
349
352
  # finding more than one module name is a problem
@@ -59,7 +59,6 @@ except ImportError:
59
59
 
60
60
  from ansible.errors import AnsibleError, AnsibleAssertionError
61
61
  from ansible import constants as C
62
- from ansible.module_utils.six import binary_type
63
62
  from ansible.module_utils.common.text.converters import to_bytes, to_text, to_native
64
63
  from ansible.utils.display import Display
65
64
  from ansible.utils.path import makedirs_safe, unfrackpath
@@ -1237,7 +1236,7 @@ class VaultAES256:
1237
1236
 
1238
1237
  It would be nice if there were a library for this but hey.
1239
1238
  """
1240
- if not (isinstance(b_a, binary_type) and isinstance(b_b, binary_type)):
1239
+ if not (isinstance(b_a, bytes) and isinstance(b_b, bytes)):
1241
1240
  raise TypeError('_is_equal can only be used to compare two byte strings')
1242
1241
 
1243
1242
  # http://codahale.com/a-lesson-in-timing-attacks/
ansible/playbook/base.py CHANGED
@@ -19,7 +19,6 @@ from ansible import context
19
19
  from ansible.errors import AnsibleError, AnsibleParserError, AnsibleAssertionError, AnsibleValueOmittedError, AnsibleFieldAttributeError
20
20
  from ansible.module_utils.datatag import native_type_name
21
21
  from ansible._internal._datatag._tags import Origin
22
- from ansible.module_utils.six import string_types
23
22
  from ansible.module_utils.parsing.convert_bool import boolean
24
23
  from ansible.module_utils.common.sentinel import Sentinel
25
24
  from ansible.module_utils.common.text.converters import to_text
@@ -37,7 +36,7 @@ display = Display()
37
36
  def _validate_action_group_metadata(action, found_group_metadata, fq_group_name):
38
37
  valid_metadata = {
39
38
  'extend_group': {
40
- 'types': (list, string_types,),
39
+ 'types': (list, str,),
41
40
  'errortype': 'list',
42
41
  },
43
42
  }
@@ -204,7 +203,7 @@ class FieldAttributeBase:
204
203
  value = self.set_to_context(attr.name)
205
204
 
206
205
  valid_values = frozenset(('always', 'on_failed', 'on_unreachable', 'on_skipped', 'never'))
207
- if value and isinstance(value, string_types) and value not in valid_values:
206
+ if value and isinstance(value, str) and value not in valid_values:
208
207
  raise AnsibleParserError("'%s' is not a valid value for debugger. Must be one of %s" % (value, ', '.join(valid_values)), obj=self.get_ds())
209
208
  return value
210
209
 
@@ -350,14 +349,14 @@ class FieldAttributeBase:
350
349
  found_group_metadata = False
351
350
  for action in action_group:
352
351
  # Everything should be a string except the metadata entry
353
- if not isinstance(action, string_types):
352
+ if not isinstance(action, str):
354
353
  _validate_action_group_metadata(action, found_group_metadata, fq_group_name)
355
354
 
356
355
  if isinstance(action['metadata'], dict):
357
356
  found_group_metadata = True
358
357
 
359
358
  include_groups = action['metadata'].get('extend_group', [])
360
- if isinstance(include_groups, string_types):
359
+ if isinstance(include_groups, str):
361
360
  include_groups = [include_groups]
362
361
  if not isinstance(include_groups, list):
363
362
  # Bad entries may be a warning above, but prevent tracebacks by setting it back to the acceptable type.
@@ -472,7 +471,7 @@ class FieldAttributeBase:
472
471
  elif attribute.isa == 'percent':
473
472
  # special value, which may be an integer or float
474
473
  # with an optional '%' at the end
475
- if isinstance(value, string_types) and '%' in value:
474
+ if isinstance(value, str) and '%' in value:
476
475
  value = value.replace('%', '')
477
476
  value = float(value)
478
477
  elif attribute.isa == 'list':
@@ -660,8 +659,8 @@ class FieldAttributeBase:
660
659
  attrs = {}
661
660
  for (name, attribute) in self.fattributes.items():
662
661
  attr = getattr(self, name)
663
- if attribute.isa == 'class' and hasattr(attr, 'serialize'):
664
- attrs[name] = attr.serialize()
662
+ if attribute.isa == 'class':
663
+ attrs[name] = attr.dump_attrs()
665
664
  else:
666
665
  attrs[name] = attr
667
666
  return attrs
@@ -675,60 +674,13 @@ class FieldAttributeBase:
675
674
  attribute = self.fattributes[attr]
676
675
  if attribute.isa == 'class' and isinstance(value, dict):
677
676
  obj = attribute.class_type()
678
- obj.deserialize(value)
677
+ obj.from_attrs(value)
679
678
  setattr(self, attr, obj)
680
679
  else:
681
680
  setattr(self, attr, value)
682
681
  else:
683
682
  setattr(self, attr, value) # overridden dump_attrs in derived types may dump attributes which are not field attributes
684
683
 
685
- # from_attrs is only used to create a finalized task
686
- # from attrs from the Worker/TaskExecutor
687
- # Those attrs are finalized and squashed in the TE
688
- # and controller side use needs to reflect that
689
- self._finalized = True
690
- self._squashed = True
691
-
692
- def serialize(self):
693
- """
694
- Serializes the object derived from the base object into
695
- a dictionary of values. This only serializes the field
696
- attributes for the object, so this may need to be overridden
697
- for any classes which wish to add additional items not stored
698
- as field attributes.
699
- """
700
-
701
- repr = self.dump_attrs()
702
-
703
- # serialize the uuid field
704
- repr['uuid'] = self._uuid
705
- repr['finalized'] = self._finalized
706
- repr['squashed'] = self._squashed
707
-
708
- return repr
709
-
710
- def deserialize(self, data):
711
- """
712
- Given a dictionary of values, load up the field attributes for
713
- this object. As with serialize(), if there are any non-field
714
- attribute data members, this method will need to be overridden
715
- and extended.
716
- """
717
-
718
- if not isinstance(data, dict):
719
- raise AnsibleAssertionError('data (%s) should be a dict but is a %s' % (data, type(data)))
720
-
721
- for (name, attribute) in self.fattributes.items():
722
- if name in data:
723
- setattr(self, name, data[name])
724
- else:
725
- self.set_to_context(name)
726
-
727
- # restore the UUID field
728
- setattr(self, '_uuid', data.get('uuid'))
729
- self._finalized = data.get('finalized', False)
730
- self._squashed = data.get('squashed', False)
731
-
732
684
 
733
685
  class Base(FieldAttributeBase):
734
686
 
ansible/playbook/block.py CHANGED
@@ -27,7 +27,6 @@ from ansible.playbook.collectionsearch import CollectionSearch
27
27
  from ansible.playbook.delegatable import Delegatable
28
28
  from ansible.playbook.helpers import load_list_of_tasks
29
29
  from ansible.playbook.notifiable import Notifiable
30
- from ansible.playbook.role import Role
31
30
  from ansible.playbook.taggable import Taggable
32
31
 
33
32
 
@@ -220,65 +219,6 @@ class Block(Base, Conditional, CollectionSearch, Taggable, Notifiable, Delegatab
220
219
  new_me.validate()
221
220
  return new_me
222
221
 
223
- def serialize(self):
224
- """
225
- Override of the default serialize method, since when we're serializing
226
- a task we don't want to include the attribute list of tasks.
227
- """
228
-
229
- data = dict()
230
- for attr in self.fattributes:
231
- if attr not in ('block', 'rescue', 'always'):
232
- data[attr] = getattr(self, attr)
233
-
234
- data['dep_chain'] = self.get_dep_chain()
235
-
236
- if self._role is not None:
237
- data['role'] = self._role.serialize()
238
- if self._parent is not None:
239
- data['parent'] = self._parent.copy(exclude_tasks=True).serialize()
240
- data['parent_type'] = self._parent.__class__.__name__
241
-
242
- return data
243
-
244
- def deserialize(self, data):
245
- """
246
- Override of the default deserialize method, to match the above overridden
247
- serialize method
248
- """
249
-
250
- # import is here to avoid import loops
251
- from ansible.playbook.task_include import TaskInclude
252
- from ansible.playbook.handler_task_include import HandlerTaskInclude
253
-
254
- # we don't want the full set of attributes (the task lists), as that
255
- # would lead to a serialize/deserialize loop
256
- for attr in self.fattributes:
257
- if attr in data and attr not in ('block', 'rescue', 'always'):
258
- setattr(self, attr, data.get(attr))
259
-
260
- self._dep_chain = data.get('dep_chain', None)
261
-
262
- # if there was a serialized role, unpack it too
263
- role_data = data.get('role')
264
- if role_data:
265
- r = Role()
266
- r.deserialize(role_data)
267
- self._role = r
268
-
269
- parent_data = data.get('parent')
270
- if parent_data:
271
- parent_type = data.get('parent_type')
272
- if parent_type == 'Block':
273
- p = Block()
274
- elif parent_type == 'TaskInclude':
275
- p = TaskInclude()
276
- elif parent_type == 'HandlerTaskInclude':
277
- p = HandlerTaskInclude()
278
- p.deserialize(parent_data)
279
- self._parent = p
280
- self._dep_chain = self._parent.get_dep_chain()
281
-
282
222
  def set_loader(self, loader):
283
223
  self._loader = loader
284
224
  if self._parent:
@@ -3,7 +3,6 @@
3
3
 
4
4
  from __future__ import annotations
5
5
 
6
- from ansible.module_utils.six import string_types
7
6
  from ansible.playbook.attribute import FieldAttribute
8
7
  from ansible.utils.collection_loader import AnsibleCollectionConfig
9
8
  from ansible.utils.display import Display
@@ -32,7 +31,7 @@ def _ensure_default_collection(collection_list=None):
32
31
  class CollectionSearch:
33
32
 
34
33
  # this needs to be populated before we can resolve tasks/roles/etc
35
- collections = FieldAttribute(isa='list', listof=string_types, priority=100, default=_ensure_default_collection, always_post_validate=True, static=True)
34
+ collections = FieldAttribute(isa='list', listof=(str,), priority=100, default=_ensure_default_collection, always_post_validate=True, static=True)
36
35
 
37
36
  def _load_collections(self, attr, ds):
38
37
  # We are always a mixin with Base, so we can validate this untemplated
@@ -20,12 +20,11 @@ from __future__ import annotations
20
20
  from ansible.errors import AnsibleAssertionError
21
21
  from ansible.playbook.attribute import NonInheritableFieldAttribute
22
22
  from ansible.playbook.task import Task
23
- from ansible.module_utils.six import string_types
24
23
 
25
24
 
26
25
  class Handler(Task):
27
26
 
28
- listen = NonInheritableFieldAttribute(isa='list', default=list, listof=string_types, static=True)
27
+ listen = NonInheritableFieldAttribute(isa='list', default=list, listof=(str,), static=True)
29
28
 
30
29
  def __init__(self, block=None, role=None, task_include=None):
31
30
  self.notified_hosts = []
@@ -72,8 +71,3 @@ class Handler(Task):
72
71
 
73
72
  def is_host_notified(self, host):
74
73
  return host in self.notified_hosts
75
-
76
- def serialize(self):
77
- result = super(Handler, self).serialize()
78
- result['is_handler'] = True
79
- return result
@@ -230,13 +230,6 @@ def load_list_of_tasks(ds, play, block=None, role=None, task_include=None, use_h
230
230
  variable_manager=variable_manager,
231
231
  )
232
232
 
233
- tags = ti_copy.tags[:]
234
-
235
- # now we extend the tags on each of the included blocks
236
- for b in included_blocks:
237
- b.tags = list(set(b.tags).union(tags))
238
- # FIXME - END
239
-
240
233
  # FIXME: handlers shouldn't need this special handling, but do
241
234
  # right now because they don't iterate blocks correctly
242
235
  if use_handlers:
@@ -203,7 +203,7 @@ class IncludedFile:
203
203
  for from_arg in new_task.FROM_ARGS:
204
204
  if from_arg in include_args:
205
205
  from_key = from_arg.removesuffix('_from')
206
- new_task._from_files[from_key] = include_args.pop(from_arg)
206
+ new_task._from_files[from_key] = include_args.get(from_arg)
207
207
 
208
208
  inc_file = IncludedFile(role_name, include_args, special_vars, new_task, is_role=True)
209
209