ansible-core 2.18.7rc1__py3-none-any.whl → 2.19.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 (757) hide show
  1. ansible/_internal/__init__.py +53 -0
  2. ansible/_internal/_ansiballz/__init__.py +0 -0
  3. ansible/_internal/_ansiballz/_builder.py +101 -0
  4. ansible/_internal/_ansiballz/_wrapper.py +262 -0
  5. ansible/_internal/_collection_proxy.py +47 -0
  6. ansible/_internal/_datatag/__init__.py +0 -0
  7. ansible/_internal/_datatag/_tags.py +130 -0
  8. ansible/_internal/_datatag/_utils.py +19 -0
  9. ansible/_internal/_datatag/_wrappers.py +33 -0
  10. ansible/_internal/_errors/__init__.py +0 -0
  11. ansible/_internal/_errors/_alarm_timeout.py +66 -0
  12. ansible/_internal/_errors/_captured.py +123 -0
  13. ansible/_internal/_errors/_error_factory.py +89 -0
  14. ansible/_internal/_errors/_error_utils.py +240 -0
  15. ansible/_internal/_errors/_handler.py +91 -0
  16. ansible/_internal/_errors/_task_timeout.py +28 -0
  17. ansible/_internal/_event_formatting.py +127 -0
  18. ansible/_internal/_json/__init__.py +214 -0
  19. ansible/_internal/_json/_legacy_encoder.py +34 -0
  20. ansible/_internal/_json/_profiles/__init__.py +0 -0
  21. ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
  22. ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
  23. ansible/_internal/_json/_profiles/_legacy.py +189 -0
  24. ansible/_internal/_locking.py +21 -0
  25. ansible/_internal/_plugins/__init__.py +0 -0
  26. ansible/_internal/_plugins/_cache.py +57 -0
  27. ansible/_internal/_ssh/__init__.py +0 -0
  28. ansible/_internal/_ssh/_agent_launch.py +91 -0
  29. ansible/_internal/_ssh/_ssh_agent.py +619 -0
  30. ansible/_internal/_task.py +78 -0
  31. ansible/_internal/_templating/__init__.py +12 -0
  32. ansible/_internal/_templating/_access.py +86 -0
  33. ansible/_internal/_templating/_chain_templar.py +63 -0
  34. ansible/_internal/_templating/_datatag.py +95 -0
  35. ansible/_internal/_templating/_engine.py +592 -0
  36. ansible/_internal/_templating/_errors.py +28 -0
  37. ansible/_internal/_templating/_jinja_bits.py +1106 -0
  38. ansible/_internal/_templating/_jinja_common.py +323 -0
  39. ansible/_internal/_templating/_jinja_patches.py +44 -0
  40. ansible/_internal/_templating/_jinja_plugins.py +375 -0
  41. ansible/_internal/_templating/_lazy_containers.py +633 -0
  42. ansible/_internal/_templating/_marker_behaviors.py +103 -0
  43. ansible/_internal/_templating/_template_vars.py +72 -0
  44. ansible/_internal/_templating/_transform.py +70 -0
  45. ansible/_internal/_templating/_utils.py +108 -0
  46. ansible/_internal/_testing.py +26 -0
  47. ansible/_internal/_wrapt.py +1052 -0
  48. ansible/_internal/_yaml/__init__.py +0 -0
  49. ansible/_internal/_yaml/_constructor.py +240 -0
  50. ansible/_internal/_yaml/_dumper.py +70 -0
  51. ansible/_internal/_yaml/_errors.py +166 -0
  52. ansible/_internal/_yaml/_loader.py +66 -0
  53. ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
  54. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
  55. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
  56. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +27 -0
  57. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
  58. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
  59. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
  60. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
  61. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
  62. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
  63. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
  64. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
  65. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
  66. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
  67. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
  68. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
  69. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
  70. ansible/cli/__init__.py +93 -104
  71. ansible/cli/_ssh_askpass.py +54 -0
  72. ansible/cli/adhoc.py +20 -10
  73. ansible/cli/arguments/option_helpers.py +163 -10
  74. ansible/cli/config.py +43 -68
  75. ansible/cli/console.py +13 -11
  76. ansible/cli/doc.py +134 -77
  77. ansible/cli/galaxy.py +27 -20
  78. ansible/cli/inventory.py +28 -28
  79. ansible/cli/playbook.py +4 -12
  80. ansible/cli/pull.py +6 -3
  81. ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
  82. ansible/cli/vault.py +12 -11
  83. ansible/compat/__init__.py +2 -2
  84. ansible/compat/importlib_resources.py +9 -12
  85. ansible/config/base.yml +218 -133
  86. ansible/config/manager.py +220 -159
  87. ansible/constants.py +2 -65
  88. ansible/errors/__init__.py +350 -256
  89. ansible/executor/interpreter_discovery.py +28 -149
  90. ansible/executor/module_common.py +480 -514
  91. ansible/executor/play_iterator.py +22 -27
  92. ansible/executor/playbook_executor.py +11 -11
  93. ansible/executor/powershell/async_watchdog.ps1 +97 -102
  94. ansible/executor/powershell/async_wrapper.ps1 +204 -153
  95. ansible/executor/powershell/become_wrapper.ps1 +107 -144
  96. ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
  97. ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
  98. ansible/executor/powershell/exec_wrapper.ps1 +675 -196
  99. ansible/executor/powershell/module_manifest.py +469 -265
  100. ansible/executor/powershell/module_wrapper.ps1 +195 -186
  101. ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
  102. ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
  103. ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
  104. ansible/executor/powershell/psrp_put_file.ps1 +122 -0
  105. ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
  106. ansible/executor/powershell/winrm_put_file.ps1 +36 -0
  107. ansible/executor/process/worker.py +139 -149
  108. ansible/executor/stats.py +5 -5
  109. ansible/executor/task_executor.py +270 -297
  110. ansible/executor/task_queue_manager.py +135 -137
  111. ansible/executor/task_result.py +182 -79
  112. ansible/galaxy/__init__.py +2 -2
  113. ansible/galaxy/api.py +26 -25
  114. ansible/galaxy/collection/__init__.py +6 -14
  115. ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
  116. ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
  117. ansible/galaxy/dependency_resolution/providers.py +4 -4
  118. ansible/galaxy/dependency_resolution/reporters.py +81 -0
  119. ansible/galaxy/role.py +6 -10
  120. ansible/galaxy/token.py +28 -21
  121. ansible/inventory/data.py +47 -57
  122. ansible/inventory/group.py +50 -73
  123. ansible/inventory/helpers.py +9 -0
  124. ansible/inventory/host.py +37 -54
  125. ansible/inventory/manager.py +79 -34
  126. ansible/keyword_desc.yml +1 -1
  127. ansible/module_utils/_internal/__init__.py +55 -0
  128. ansible/module_utils/_internal/_ambient_context.py +58 -0
  129. ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
  130. ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
  131. ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
  132. ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
  133. ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
  134. ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
  135. ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
  136. ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
  137. ansible/module_utils/_internal/_dataclass_validation.py +217 -0
  138. ansible/module_utils/_internal/_datatag/__init__.py +961 -0
  139. ansible/module_utils/_internal/_datatag/_tags.py +16 -0
  140. ansible/module_utils/_internal/_debugging.py +31 -0
  141. ansible/module_utils/_internal/_deprecator.py +157 -0
  142. ansible/module_utils/_internal/_errors.py +101 -0
  143. ansible/module_utils/_internal/_event_utils.py +61 -0
  144. ansible/module_utils/_internal/_json/__init__.py +63 -0
  145. ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
  146. ansible/module_utils/_internal/_json/_profiles/__init__.py +428 -0
  147. ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
  148. ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
  149. ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -0
  150. ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
  151. ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
  152. ansible/module_utils/_internal/_json/_profiles/_tagless.py +52 -0
  153. ansible/module_utils/_internal/_messages.py +130 -0
  154. ansible/module_utils/_internal/_patches/__init__.py +66 -0
  155. ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -0
  156. ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
  157. ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
  158. ansible/module_utils/_internal/_plugin_info.py +38 -0
  159. ansible/module_utils/_internal/_stack.py +22 -0
  160. ansible/module_utils/_internal/_testing.py +0 -0
  161. ansible/module_utils/_internal/_text_utils.py +6 -0
  162. ansible/module_utils/_internal/_traceback.py +92 -0
  163. ansible/module_utils/_internal/_validation.py +14 -0
  164. ansible/module_utils/ansible_release.py +2 -2
  165. ansible/module_utils/api.py +1 -2
  166. ansible/module_utils/basic.py +303 -202
  167. ansible/module_utils/common/_utils.py +24 -28
  168. ansible/module_utils/common/arg_spec.py +8 -3
  169. ansible/module_utils/common/collections.py +7 -2
  170. ansible/module_utils/common/dict_transformations.py +2 -2
  171. ansible/module_utils/common/file.py +2 -2
  172. ansible/module_utils/common/json.py +90 -84
  173. ansible/module_utils/common/locale.py +2 -2
  174. ansible/module_utils/common/parameters.py +27 -24
  175. ansible/module_utils/common/process.py +2 -3
  176. ansible/module_utils/common/respawn.py +11 -33
  177. ansible/module_utils/common/sentinel.py +66 -0
  178. ansible/module_utils/common/sys_info.py +8 -8
  179. ansible/module_utils/common/text/converters.py +16 -37
  180. ansible/module_utils/common/validation.py +35 -24
  181. ansible/module_utils/common/warnings.py +143 -25
  182. ansible/module_utils/common/yaml.py +29 -3
  183. ansible/module_utils/compat/datetime.py +33 -21
  184. ansible/module_utils/compat/paramiko.py +21 -10
  185. ansible/module_utils/compat/typing.py +6 -5
  186. ansible/module_utils/connection.py +10 -13
  187. ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
  188. ansible/module_utils/csharp/Ansible.Become.cs +1 -0
  189. ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
  190. ansible/module_utils/csharp/Ansible._Async.cs +517 -0
  191. ansible/module_utils/datatag.py +49 -0
  192. ansible/module_utils/distro/__init__.py +2 -2
  193. ansible/module_utils/facts/ansible_collector.py +4 -5
  194. ansible/module_utils/facts/collector.py +13 -14
  195. ansible/module_utils/facts/compat.py +4 -4
  196. ansible/module_utils/facts/default_collectors.py +1 -1
  197. ansible/module_utils/facts/hardware/aix.py +34 -0
  198. ansible/module_utils/facts/hardware/base.py +2 -2
  199. ansible/module_utils/facts/hardware/darwin.py +1 -3
  200. ansible/module_utils/facts/hardware/freebsd.py +2 -2
  201. ansible/module_utils/facts/hardware/linux.py +5 -5
  202. ansible/module_utils/facts/namespace.py +1 -1
  203. ansible/module_utils/facts/network/base.py +1 -1
  204. ansible/module_utils/facts/network/fc_wwn.py +1 -2
  205. ansible/module_utils/facts/network/iscsi.py +1 -2
  206. ansible/module_utils/facts/network/nvme.py +1 -2
  207. ansible/module_utils/facts/other/facter.py +2 -3
  208. ansible/module_utils/facts/other/ohai.py +2 -3
  209. ansible/module_utils/facts/sysctl.py +4 -6
  210. ansible/module_utils/facts/system/apparmor.py +1 -2
  211. ansible/module_utils/facts/system/caps.py +3 -3
  212. ansible/module_utils/facts/system/chroot.py +1 -2
  213. ansible/module_utils/facts/system/cmdline.py +1 -2
  214. ansible/module_utils/facts/system/date_time.py +5 -3
  215. ansible/module_utils/facts/system/distribution.py +27 -13
  216. ansible/module_utils/facts/system/dns.py +1 -1
  217. ansible/module_utils/facts/system/env.py +1 -2
  218. ansible/module_utils/facts/system/fips.py +7 -20
  219. ansible/module_utils/facts/system/loadavg.py +1 -2
  220. ansible/module_utils/facts/system/local.py +2 -3
  221. ansible/module_utils/facts/system/lsb.py +1 -2
  222. ansible/module_utils/facts/system/pkg_mgr.py +1 -2
  223. ansible/module_utils/facts/system/platform.py +1 -2
  224. ansible/module_utils/facts/system/python.py +1 -2
  225. ansible/module_utils/facts/system/selinux.py +1 -1
  226. ansible/module_utils/facts/system/service_mgr.py +1 -2
  227. ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
  228. ansible/module_utils/facts/system/systemd.py +1 -1
  229. ansible/module_utils/facts/system/user.py +1 -2
  230. ansible/module_utils/facts/utils.py +3 -3
  231. ansible/module_utils/facts/virtual/base.py +1 -1
  232. ansible/module_utils/facts/virtual/linux.py +3 -3
  233. ansible/module_utils/facts/virtual/sunos.py +3 -15
  234. ansible/module_utils/facts/virtual/sysctl.py +3 -16
  235. ansible/module_utils/json_utils.py +2 -2
  236. ansible/module_utils/parsing/convert_bool.py +7 -1
  237. ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
  238. ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
  239. ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
  240. ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
  241. ansible/module_utils/service.py +21 -31
  242. ansible/module_utils/splitter.py +7 -7
  243. ansible/module_utils/testing.py +31 -0
  244. ansible/module_utils/urls.py +64 -35
  245. ansible/modules/add_host.py +4 -4
  246. ansible/modules/apt.py +69 -49
  247. ansible/modules/apt_key.py +19 -12
  248. ansible/modules/apt_repository.py +32 -51
  249. ansible/modules/assemble.py +16 -14
  250. ansible/modules/assert.py +4 -4
  251. ansible/modules/async_status.py +24 -24
  252. ansible/modules/async_wrapper.py +20 -25
  253. ansible/modules/blockinfile.py +6 -7
  254. ansible/modules/command.py +13 -20
  255. ansible/modules/copy.py +60 -147
  256. ansible/modules/cron.py +24 -21
  257. ansible/modules/deb822_repository.py +8 -9
  258. ansible/modules/debconf.py +5 -5
  259. ansible/modules/debug.py +4 -4
  260. ansible/modules/dnf.py +8 -8
  261. ansible/modules/dnf5.py +39 -13
  262. ansible/modules/dpkg_selections.py +4 -4
  263. ansible/modules/expect.py +13 -15
  264. ansible/modules/fail.py +4 -4
  265. ansible/modules/fetch.py +4 -4
  266. ansible/modules/file.py +184 -144
  267. ansible/modules/find.py +22 -20
  268. ansible/modules/gather_facts.py +3 -3
  269. ansible/modules/get_url.py +77 -54
  270. ansible/modules/getent.py +7 -9
  271. ansible/modules/git.py +38 -38
  272. ansible/modules/group.py +6 -6
  273. ansible/modules/group_by.py +4 -4
  274. ansible/modules/hostname.py +15 -32
  275. ansible/modules/import_playbook.py +6 -6
  276. ansible/modules/import_role.py +6 -6
  277. ansible/modules/import_tasks.py +6 -6
  278. ansible/modules/include_role.py +6 -6
  279. ansible/modules/include_tasks.py +6 -6
  280. ansible/modules/include_vars.py +6 -6
  281. ansible/modules/iptables.py +86 -73
  282. ansible/modules/known_hosts.py +22 -24
  283. ansible/modules/lineinfile.py +5 -5
  284. ansible/modules/meta.py +4 -4
  285. ansible/modules/mount_facts.py +2 -2
  286. ansible/modules/package.py +10 -4
  287. ansible/modules/package_facts.py +22 -10
  288. ansible/modules/pause.py +6 -6
  289. ansible/modules/ping.py +6 -6
  290. ansible/modules/pip.py +21 -26
  291. ansible/modules/raw.py +6 -6
  292. ansible/modules/reboot.py +6 -6
  293. ansible/modules/replace.py +10 -14
  294. ansible/modules/rpm_key.py +7 -8
  295. ansible/modules/script.py +4 -4
  296. ansible/modules/service.py +10 -17
  297. ansible/modules/service_facts.py +87 -10
  298. ansible/modules/set_fact.py +5 -5
  299. ansible/modules/set_stats.py +4 -4
  300. ansible/modules/setup.py +2 -2
  301. ansible/modules/shell.py +6 -6
  302. ansible/modules/slurp.py +16 -19
  303. ansible/modules/stat.py +15 -31
  304. ansible/modules/subversion.py +15 -15
  305. ansible/modules/systemd.py +7 -7
  306. ansible/modules/systemd_service.py +7 -7
  307. ansible/modules/sysvinit.py +9 -9
  308. ansible/modules/tempfile.py +5 -6
  309. ansible/modules/template.py +6 -6
  310. ansible/modules/unarchive.py +38 -17
  311. ansible/modules/uri.py +33 -26
  312. ansible/modules/user.py +45 -32
  313. ansible/modules/validate_argument_spec.py +10 -7
  314. ansible/modules/wait_for.py +70 -60
  315. ansible/modules/wait_for_connection.py +6 -6
  316. ansible/modules/yum_repository.py +10 -9
  317. ansible/parsing/ajson.py +17 -37
  318. ansible/parsing/dataloader.py +99 -54
  319. ansible/parsing/mod_args.py +62 -60
  320. ansible/parsing/plugin_docs.py +21 -86
  321. ansible/parsing/quoting.py +1 -1
  322. ansible/parsing/splitter.py +27 -12
  323. ansible/parsing/utils/addresses.py +24 -24
  324. ansible/parsing/utils/jsonify.py +5 -1
  325. ansible/parsing/utils/yaml.py +32 -61
  326. ansible/parsing/vault/__init__.py +327 -99
  327. ansible/parsing/yaml/__init__.py +0 -18
  328. ansible/parsing/yaml/dumper.py +6 -120
  329. ansible/parsing/yaml/loader.py +6 -39
  330. ansible/parsing/yaml/objects.py +43 -335
  331. ansible/playbook/__init__.py +1 -1
  332. ansible/playbook/attribute.py +8 -3
  333. ansible/playbook/base.py +187 -134
  334. ansible/playbook/block.py +26 -24
  335. ansible/playbook/collectionsearch.py +1 -15
  336. ansible/playbook/conditional.py +3 -77
  337. ansible/playbook/handler.py +8 -2
  338. ansible/playbook/helpers.py +41 -53
  339. ansible/playbook/included_file.py +32 -26
  340. ansible/playbook/loop_control.py +2 -2
  341. ansible/playbook/play.py +85 -44
  342. ansible/playbook/play_context.py +14 -17
  343. ansible/playbook/playbook_include.py +27 -62
  344. ansible/playbook/role/__init__.py +64 -49
  345. ansible/playbook/role/definition.py +15 -17
  346. ansible/playbook/role/include.py +2 -4
  347. ansible/playbook/role/metadata.py +10 -11
  348. ansible/playbook/role_include.py +3 -3
  349. ansible/playbook/taggable.py +28 -12
  350. ansible/playbook/task.py +192 -121
  351. ansible/playbook/task_include.py +5 -5
  352. ansible/plugins/__init__.py +58 -26
  353. ansible/plugins/action/__init__.py +188 -186
  354. ansible/plugins/action/add_host.py +2 -2
  355. ansible/plugins/action/assemble.py +11 -18
  356. ansible/plugins/action/assert.py +55 -67
  357. ansible/plugins/action/async_status.py +7 -2
  358. ansible/plugins/action/copy.py +14 -17
  359. ansible/plugins/action/debug.py +37 -31
  360. ansible/plugins/action/dnf.py +3 -4
  361. ansible/plugins/action/fail.py +1 -1
  362. ansible/plugins/action/fetch.py +7 -8
  363. ansible/plugins/action/gather_facts.py +13 -14
  364. ansible/plugins/action/group_by.py +1 -1
  365. ansible/plugins/action/include_vars.py +10 -11
  366. ansible/plugins/action/package.py +8 -14
  367. ansible/plugins/action/pause.py +2 -2
  368. ansible/plugins/action/script.py +27 -38
  369. ansible/plugins/action/service.py +9 -18
  370. ansible/plugins/action/set_fact.py +3 -12
  371. ansible/plugins/action/set_stats.py +3 -8
  372. ansible/plugins/action/template.py +47 -67
  373. ansible/plugins/action/unarchive.py +6 -16
  374. ansible/plugins/action/uri.py +9 -20
  375. ansible/plugins/action/validate_argument_spec.py +5 -5
  376. ansible/plugins/action/wait_for_connection.py +1 -1
  377. ansible/plugins/become/__init__.py +31 -8
  378. ansible/plugins/become/runas.py +71 -0
  379. ansible/plugins/become/su.py +13 -8
  380. ansible/plugins/become/sudo.py +19 -0
  381. ansible/plugins/cache/__init__.py +52 -63
  382. ansible/plugins/cache/base.py +8 -0
  383. ansible/plugins/cache/jsonfile.py +10 -16
  384. ansible/plugins/cache/memory.py +6 -12
  385. ansible/plugins/callback/__init__.py +294 -201
  386. ansible/plugins/callback/default.py +99 -95
  387. ansible/plugins/callback/junit.py +44 -43
  388. ansible/plugins/callback/minimal.py +28 -25
  389. ansible/plugins/callback/oneline.py +34 -21
  390. ansible/plugins/callback/tree.py +27 -16
  391. ansible/plugins/connection/__init__.py +47 -34
  392. ansible/plugins/connection/local.py +156 -60
  393. ansible/plugins/connection/paramiko_ssh.py +34 -24
  394. ansible/plugins/connection/psrp.py +76 -165
  395. ansible/plugins/connection/ssh.py +326 -86
  396. ansible/plugins/connection/winrm.py +62 -141
  397. ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
  398. ansible/plugins/doc_fragments/action_core.py +6 -6
  399. ansible/plugins/doc_fragments/backup.py +2 -2
  400. ansible/plugins/doc_fragments/checksum_common.py +27 -0
  401. ansible/plugins/doc_fragments/constructed.py +8 -4
  402. ansible/plugins/doc_fragments/decrypt.py +2 -2
  403. ansible/plugins/doc_fragments/default_callback.py +2 -2
  404. ansible/plugins/doc_fragments/files.py +2 -2
  405. ansible/plugins/doc_fragments/inventory_cache.py +2 -2
  406. ansible/plugins/doc_fragments/result_format_callback.py +2 -2
  407. ansible/plugins/doc_fragments/return_common.py +2 -2
  408. ansible/plugins/doc_fragments/template_common.py +4 -4
  409. ansible/plugins/doc_fragments/url.py +17 -1
  410. ansible/plugins/doc_fragments/url_windows.py +2 -2
  411. ansible/plugins/doc_fragments/validate.py +2 -2
  412. ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
  413. ansible/plugins/filter/__init__.py +6 -2
  414. ansible/plugins/filter/b64decode.yml +22 -0
  415. ansible/plugins/filter/b64encode.yml +22 -0
  416. ansible/plugins/filter/bool.yml +11 -4
  417. ansible/plugins/filter/core.py +245 -120
  418. ansible/plugins/filter/encryption.py +42 -34
  419. ansible/plugins/filter/flatten.yml +3 -2
  420. ansible/plugins/filter/human_to_bytes.yml +1 -1
  421. ansible/plugins/filter/mathstuff.py +30 -37
  422. ansible/plugins/filter/password_hash.yml +8 -0
  423. ansible/plugins/filter/pow.yml +1 -1
  424. ansible/plugins/filter/regex_search.yml +1 -4
  425. ansible/plugins/filter/root.yml +1 -1
  426. ansible/plugins/filter/split.yml +1 -1
  427. ansible/plugins/filter/strftime.yml +3 -3
  428. ansible/plugins/filter/to_nice_yaml.yml +0 -4
  429. ansible/plugins/filter/to_uuid.yml +1 -1
  430. ansible/plugins/filter/to_yaml.yml +0 -4
  431. ansible/plugins/filter/unvault.yml +1 -1
  432. ansible/plugins/filter/urls.py +1 -1
  433. ansible/plugins/filter/urlsplit.py +8 -9
  434. ansible/plugins/filter/vault.yml +14 -9
  435. ansible/plugins/filter/win_basename.yml +6 -1
  436. ansible/plugins/filter/win_dirname.yml +5 -0
  437. ansible/plugins/inventory/__init__.py +107 -86
  438. ansible/plugins/inventory/advanced_host_list.py +7 -5
  439. ansible/plugins/inventory/auto.py +11 -4
  440. ansible/plugins/inventory/constructed.py +21 -24
  441. ansible/plugins/inventory/generator.py +16 -11
  442. ansible/plugins/inventory/host_list.py +7 -5
  443. ansible/plugins/inventory/ini.py +78 -44
  444. ansible/plugins/inventory/script.py +190 -120
  445. ansible/plugins/inventory/toml.py +16 -126
  446. ansible/plugins/inventory/yaml.py +10 -8
  447. ansible/plugins/list.py +72 -19
  448. ansible/plugins/loader.py +383 -198
  449. ansible/plugins/lookup/__init__.py +21 -4
  450. ansible/plugins/lookup/config.py +21 -35
  451. ansible/plugins/lookup/csvfile.py +19 -73
  452. ansible/plugins/lookup/dict.py +1 -6
  453. ansible/plugins/lookup/env.py +12 -9
  454. ansible/plugins/lookup/file.py +5 -8
  455. ansible/plugins/lookup/first_found.py +87 -55
  456. ansible/plugins/lookup/indexed_items.py +1 -10
  457. ansible/plugins/lookup/ini.py +14 -13
  458. ansible/plugins/lookup/items.py +1 -1
  459. ansible/plugins/lookup/lines.py +8 -1
  460. ansible/plugins/lookup/list.py +1 -1
  461. ansible/plugins/lookup/nested.py +2 -18
  462. ansible/plugins/lookup/password.py +5 -5
  463. ansible/plugins/lookup/pipe.py +5 -7
  464. ansible/plugins/lookup/sequence.py +18 -8
  465. ansible/plugins/lookup/subelements.py +1 -4
  466. ansible/plugins/lookup/template.py +47 -36
  467. ansible/plugins/lookup/together.py +0 -12
  468. ansible/plugins/lookup/unvault.py +1 -5
  469. ansible/plugins/lookup/url.py +4 -10
  470. ansible/plugins/lookup/vars.py +16 -24
  471. ansible/plugins/shell/__init__.py +58 -4
  472. ansible/plugins/shell/cmd.py +2 -2
  473. ansible/plugins/shell/powershell.py +106 -31
  474. ansible/plugins/shell/sh.py +13 -7
  475. ansible/plugins/strategy/__init__.py +168 -193
  476. ansible/plugins/strategy/debug.py +2 -2
  477. ansible/plugins/strategy/free.py +16 -31
  478. ansible/plugins/strategy/host_pinned.py +2 -2
  479. ansible/plugins/strategy/linear.py +41 -41
  480. ansible/plugins/terminal/__init__.py +4 -4
  481. ansible/plugins/test/__init__.py +7 -2
  482. ansible/plugins/test/core.py +75 -35
  483. ansible/plugins/test/files.py +1 -1
  484. ansible/plugins/test/finished.yml +1 -1
  485. ansible/plugins/test/mathstuff.py +3 -3
  486. ansible/plugins/test/uri.py +5 -8
  487. ansible/plugins/vars/host_group_vars.py +7 -14
  488. ansible/release.py +2 -2
  489. ansible/template/__init__.py +353 -943
  490. ansible/utils/__init__.py +0 -18
  491. ansible/utils/collection_loader/__init__.py +54 -5
  492. ansible/utils/collection_loader/_collection_config.py +5 -6
  493. ansible/utils/collection_loader/_collection_finder.py +82 -96
  494. ansible/utils/collection_loader/_collection_meta.py +15 -8
  495. ansible/utils/display.py +485 -73
  496. ansible/utils/encrypt.py +27 -19
  497. ansible/utils/fqcn.py +2 -2
  498. ansible/utils/galaxy.py +2 -2
  499. ansible/utils/hashing.py +8 -10
  500. ansible/utils/helpers.py +2 -2
  501. ansible/utils/listify.py +10 -8
  502. ansible/utils/lock.py +2 -2
  503. ansible/utils/path.py +10 -12
  504. ansible/utils/plugin_docs.py +16 -14
  505. ansible/utils/py3compat.py +2 -7
  506. ansible/utils/sentinel.py +4 -62
  507. ansible/utils/singleton.py +2 -0
  508. ansible/utils/ssh_functions.py +6 -2
  509. ansible/utils/unsafe_proxy.py +23 -332
  510. ansible/utils/vars.py +55 -8
  511. ansible/utils/version.py +2 -2
  512. ansible/vars/clean.py +5 -5
  513. ansible/vars/hostvars.py +60 -90
  514. ansible/vars/manager.py +220 -285
  515. ansible/vars/plugins.py +4 -4
  516. ansible/vars/reserved.py +13 -12
  517. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
  518. ansible_core-2.19.0.dist-info/RECORD +1097 -0
  519. ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
  520. ansible_test/_data/completion/docker.txt +7 -7
  521. ansible_test/_data/completion/remote.txt +6 -6
  522. ansible_test/_data/completion/windows.txt +1 -0
  523. ansible_test/_data/requirements/ansible.txt +2 -2
  524. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  525. ansible_test/_data/requirements/sanity.changelog.txt +2 -2
  526. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  527. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  528. ansible_test/_data/requirements/sanity.pylint.txt +5 -5
  529. ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
  530. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  531. ansible_test/_data/requirements/units.txt +1 -0
  532. ansible_test/_internal/__init__.py +6 -0
  533. ansible_test/_internal/ansible_util.py +3 -1
  534. ansible_test/_internal/become.py +1 -0
  535. ansible_test/_internal/bootstrap.py +1 -0
  536. ansible_test/_internal/cache.py +1 -0
  537. ansible_test/_internal/cgroup.py +1 -0
  538. ansible_test/_internal/ci/__init__.py +1 -0
  539. ansible_test/_internal/ci/azp.py +1 -0
  540. ansible_test/_internal/ci/local.py +1 -0
  541. ansible_test/_internal/classification/__init__.py +1 -0
  542. ansible_test/_internal/classification/common.py +1 -0
  543. ansible_test/_internal/classification/csharp.py +1 -0
  544. ansible_test/_internal/classification/powershell.py +1 -0
  545. ansible_test/_internal/classification/python.py +1 -0
  546. ansible_test/_internal/cli/__init__.py +1 -0
  547. ansible_test/_internal/cli/actions.py +1 -0
  548. ansible_test/_internal/cli/argparsing/__init__.py +1 -0
  549. ansible_test/_internal/cli/argparsing/actions.py +1 -0
  550. ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
  551. ansible_test/_internal/cli/argparsing/parsers.py +1 -0
  552. ansible_test/_internal/cli/commands/__init__.py +11 -5
  553. ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
  554. ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
  555. ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
  556. ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
  557. ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
  558. ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
  559. ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
  560. ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
  561. ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
  562. ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
  563. ansible_test/_internal/cli/commands/coverage/html.py +1 -0
  564. ansible_test/_internal/cli/commands/coverage/report.py +1 -0
  565. ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
  566. ansible_test/_internal/cli/commands/env.py +1 -0
  567. ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
  568. ansible_test/_internal/cli/commands/integration/network.py +1 -0
  569. ansible_test/_internal/cli/commands/integration/posix.py +1 -0
  570. ansible_test/_internal/cli/commands/integration/windows.py +1 -0
  571. ansible_test/_internal/cli/commands/sanity.py +9 -0
  572. ansible_test/_internal/cli/commands/shell.py +1 -0
  573. ansible_test/_internal/cli/commands/units.py +1 -0
  574. ansible_test/_internal/cli/compat.py +1 -0
  575. ansible_test/_internal/cli/completers.py +1 -0
  576. ansible_test/_internal/cli/converters.py +1 -0
  577. ansible_test/_internal/cli/environments.py +52 -5
  578. ansible_test/_internal/cli/epilog.py +1 -0
  579. ansible_test/_internal/cli/parsers/__init__.py +1 -0
  580. ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
  581. ansible_test/_internal/cli/parsers/helpers.py +1 -0
  582. ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
  583. ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
  584. ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
  585. ansible_test/_internal/commands/__init__.py +1 -0
  586. ansible_test/_internal/commands/coverage/__init__.py +3 -2
  587. ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
  588. ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
  589. ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
  590. ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
  591. ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
  592. ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
  593. ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
  594. ansible_test/_internal/commands/coverage/combine.py +2 -1
  595. ansible_test/_internal/commands/coverage/erase.py +1 -0
  596. ansible_test/_internal/commands/coverage/html.py +1 -0
  597. ansible_test/_internal/commands/coverage/report.py +1 -0
  598. ansible_test/_internal/commands/coverage/xml.py +1 -0
  599. ansible_test/_internal/commands/env/__init__.py +2 -0
  600. ansible_test/_internal/commands/integration/__init__.py +22 -5
  601. ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
  602. ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
  603. ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
  604. ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
  605. ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
  606. ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
  607. ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
  608. ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
  609. ansible_test/_internal/commands/integration/cloud/httptester.py +3 -2
  610. ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
  611. ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
  612. ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
  613. ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
  614. ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
  615. ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
  616. ansible_test/_internal/commands/integration/coverage.py +8 -2
  617. ansible_test/_internal/commands/integration/filters.py +1 -0
  618. ansible_test/_internal/commands/integration/network.py +1 -0
  619. ansible_test/_internal/commands/integration/posix.py +1 -0
  620. ansible_test/_internal/commands/integration/windows.py +1 -0
  621. ansible_test/_internal/commands/sanity/__init__.py +19 -2
  622. ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
  623. ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
  624. ansible_test/_internal/commands/sanity/compile.py +1 -0
  625. ansible_test/_internal/commands/sanity/ignores.py +1 -0
  626. ansible_test/_internal/commands/sanity/import.py +1 -0
  627. ansible_test/_internal/commands/sanity/integration_aliases.py +12 -0
  628. ansible_test/_internal/commands/sanity/pep8.py +1 -0
  629. ansible_test/_internal/commands/sanity/pslint.py +1 -0
  630. ansible_test/_internal/commands/sanity/pylint.py +25 -26
  631. ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
  632. ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
  633. ansible_test/_internal/commands/sanity/yamllint.py +1 -0
  634. ansible_test/_internal/commands/shell/__init__.py +44 -4
  635. ansible_test/_internal/commands/units/__init__.py +5 -1
  636. ansible_test/_internal/compat/__init__.py +1 -0
  637. ansible_test/_internal/compat/packaging.py +1 -0
  638. ansible_test/_internal/compat/yaml.py +1 -0
  639. ansible_test/_internal/completion.py +1 -0
  640. ansible_test/_internal/config.py +23 -13
  641. ansible_test/_internal/connections.py +1 -0
  642. ansible_test/_internal/constants.py +1 -0
  643. ansible_test/_internal/containers.py +1 -0
  644. ansible_test/_internal/content_config.py +1 -0
  645. ansible_test/_internal/core_ci.py +1 -0
  646. ansible_test/_internal/coverage_util.py +11 -10
  647. ansible_test/_internal/data.py +1 -0
  648. ansible_test/_internal/debugging.py +166 -0
  649. ansible_test/_internal/delegation.py +22 -13
  650. ansible_test/_internal/dev/__init__.py +1 -0
  651. ansible_test/_internal/dev/container_probe.py +1 -0
  652. ansible_test/_internal/diff.py +3 -2
  653. ansible_test/_internal/docker_util.py +2 -1
  654. ansible_test/_internal/encoding.py +1 -0
  655. ansible_test/_internal/executor.py +1 -0
  656. ansible_test/_internal/git.py +1 -0
  657. ansible_test/_internal/host_configs.py +1 -0
  658. ansible_test/_internal/host_profiles.py +260 -16
  659. ansible_test/_internal/http.py +1 -0
  660. ansible_test/_internal/init.py +1 -0
  661. ansible_test/_internal/inventory.py +39 -3
  662. ansible_test/_internal/io.py +1 -0
  663. ansible_test/_internal/metadata.py +95 -4
  664. ansible_test/_internal/payload.py +1 -0
  665. ansible_test/_internal/processes.py +80 -0
  666. ansible_test/_internal/provider/__init__.py +1 -0
  667. ansible_test/_internal/provider/layout/__init__.py +1 -0
  668. ansible_test/_internal/provider/layout/ansible.py +1 -0
  669. ansible_test/_internal/provider/layout/collection.py +1 -0
  670. ansible_test/_internal/provider/layout/unsupported.py +1 -0
  671. ansible_test/_internal/provider/source/__init__.py +1 -0
  672. ansible_test/_internal/provider/source/git.py +1 -0
  673. ansible_test/_internal/provider/source/installed.py +1 -0
  674. ansible_test/_internal/provider/source/unsupported.py +1 -0
  675. ansible_test/_internal/provider/source/unversioned.py +1 -0
  676. ansible_test/_internal/provisioning.py +11 -4
  677. ansible_test/_internal/pypi_proxy.py +6 -5
  678. ansible_test/_internal/python_requirements.py +28 -0
  679. ansible_test/_internal/ssh.py +2 -5
  680. ansible_test/_internal/target.py +9 -0
  681. ansible_test/_internal/test.py +3 -2
  682. ansible_test/_internal/thread.py +3 -1
  683. ansible_test/_internal/timeout.py +2 -1
  684. ansible_test/_internal/util.py +41 -12
  685. ansible_test/_internal/util_common.py +18 -5
  686. ansible_test/_internal/venv.py +1 -0
  687. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
  688. ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
  689. ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
  690. ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
  691. ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
  692. ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
  693. ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
  694. ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
  695. ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
  696. ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
  697. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
  698. ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
  699. ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
  700. ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
  701. ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
  702. ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
  703. ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
  704. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +8 -5
  705. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
  706. ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
  707. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
  708. ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
  709. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
  710. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
  711. ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
  712. ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
  713. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
  714. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
  715. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
  716. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
  717. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
  718. ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
  719. ansible_test/_util/controller/tools/collection_detail.py +1 -0
  720. ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
  721. ansible_test/_util/target/injector/python.py +8 -0
  722. ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
  723. ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
  724. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
  725. ansible_test/_util/target/sanity/compile/compile.py +1 -0
  726. ansible_test/_util/target/sanity/import/importer.py +15 -16
  727. ansible_test/_util/target/setup/bootstrap.sh +9 -20
  728. ansible_test/_util/target/setup/probe_cgroups.py +1 -0
  729. ansible_test/_util/target/setup/quiet_pip.py +1 -0
  730. ansible_test/_util/target/setup/requirements.py +38 -36
  731. ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
  732. ansible_test/_util/target/tools/yamlcheck.py +2 -1
  733. ansible/compat/selectors.py +0 -32
  734. ansible/errors/yaml_strings.py +0 -138
  735. ansible/executor/action_write_locks.py +0 -44
  736. ansible/executor/discovery/python_target.py +0 -47
  737. ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
  738. ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
  739. ansible/module_utils/compat/importlib.py +0 -26
  740. ansible/module_utils/compat/selectors.py +0 -32
  741. ansible/module_utils/pycompat24.py +0 -73
  742. ansible/parsing/yaml/constructor.py +0 -178
  743. ansible/template/native_helpers.py +0 -251
  744. ansible/template/template.py +0 -43
  745. ansible/template/vars.py +0 -77
  746. ansible/utils/native_jinja.py +0 -11
  747. ansible/vars/fact_cache.py +0 -71
  748. ansible_core-2.18.7rc1.dist-info/RECORD +0 -992
  749. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
  750. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
  751. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
  752. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
  753. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  754. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  755. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  756. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  757. {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,961 @@
1
+ from __future__ import annotations
2
+
3
+ import abc
4
+ import collections.abc as c
5
+ import copy
6
+ import dataclasses
7
+ import datetime
8
+ import enum
9
+ import inspect
10
+ import sys
11
+
12
+ from itertools import chain
13
+
14
+ # deprecated: description='typing.Self exists in Python 3.11+' python_version='3.10'
15
+ from ansible.module_utils.compat import typing as t
16
+
17
+ from ansible.module_utils._internal import _dataclass_validation
18
+ from ansible.module_utils._internal._patches import _sys_intern_patch, _socket_patch
19
+
20
+ _sys_intern_patch.SysInternPatch.patch()
21
+ _socket_patch.GetAddrInfoPatch.patch() # DTFIX-FUTURE: consider replacing this with a socket import shim that installs the patch
22
+
23
+ if sys.version_info >= (3, 10):
24
+ # Using slots for reduced memory usage and improved performance.
25
+ _tag_dataclass_kwargs = dict(frozen=True, repr=False, kw_only=True, slots=True)
26
+ else:
27
+ # deprecated: description='always use dataclass slots and keyword-only args' python_version='3.9'
28
+ _tag_dataclass_kwargs = dict(frozen=True, repr=False)
29
+
30
+ _T = t.TypeVar('_T')
31
+ _TAnsibleSerializable = t.TypeVar('_TAnsibleSerializable', bound='AnsibleSerializable')
32
+ _TAnsibleDatatagBase = t.TypeVar('_TAnsibleDatatagBase', bound='AnsibleDatatagBase')
33
+ _TAnsibleTaggedObject = t.TypeVar('_TAnsibleTaggedObject', bound='AnsibleTaggedObject')
34
+
35
+ _NO_INSTANCE_STORAGE = t.cast(t.Tuple[str], tuple())
36
+ _ANSIBLE_TAGGED_OBJECT_SLOTS = tuple(('_ansible_tags_mapping',))
37
+
38
+ # shared empty frozenset for default values
39
+ _empty_frozenset: t.FrozenSet = frozenset()
40
+
41
+ # Technical Notes
42
+ #
43
+ # Tagged values compare (and thus hash) the same as their base types, so a value that differs only by its tags will appear identical to non-tag-aware code.
44
+ # This will affect storage and update of tagged values in dictionary keys, sets, etc. While tagged values can be used as keys in hashable collections,
45
+ # updating a key usually requires removal and re-addition.
46
+
47
+
48
+ class AnsibleTagHelper:
49
+ """Utility methods for working with Ansible data tags."""
50
+
51
+ @staticmethod
52
+ def untag(value: _T, *tag_types: t.Type[AnsibleDatatagBase]) -> _T:
53
+ """
54
+ If tags matching any of `tag_types` are present on `value`, return a copy with those tags removed.
55
+ If no `tag_types` are specified and the object has tags, return a copy with all tags removed.
56
+ Otherwise, the original `value` is returned.
57
+ """
58
+ tag_set = AnsibleTagHelper.tags(value)
59
+
60
+ if not tag_set:
61
+ return value
62
+
63
+ if tag_types:
64
+ tags_mapping = _AnsibleTagsMapping((type(tag), tag) for tag in tag_set if type(tag) not in tag_types) # pylint: disable=unidiomatic-typecheck
65
+
66
+ if len(tags_mapping) == len(tag_set):
67
+ return value # if no tags were removed, return the original instance
68
+ else:
69
+ tags_mapping = None
70
+
71
+ if not tags_mapping:
72
+ if t.cast(AnsibleTaggedObject, value)._empty_tags_as_native:
73
+ return t.cast(AnsibleTaggedObject, value)._native_copy()
74
+
75
+ tags_mapping = _EMPTY_INTERNAL_TAGS_MAPPING
76
+
77
+ tagged_type = AnsibleTaggedObject._get_tagged_type(type(value))
78
+
79
+ return t.cast(_T, tagged_type._instance_factory(value, tags_mapping))
80
+
81
+ @staticmethod
82
+ def tags(value: t.Any) -> t.FrozenSet[AnsibleDatatagBase]:
83
+ tags = _try_get_internal_tags_mapping(value)
84
+
85
+ if tags is _EMPTY_INTERNAL_TAGS_MAPPING:
86
+ return _empty_frozenset
87
+
88
+ return frozenset(tags.values())
89
+
90
+ @staticmethod
91
+ def tag_types(value: t.Any) -> t.FrozenSet[t.Type[AnsibleDatatagBase]]:
92
+ tags = _try_get_internal_tags_mapping(value)
93
+
94
+ if tags is _EMPTY_INTERNAL_TAGS_MAPPING:
95
+ return _empty_frozenset
96
+
97
+ return frozenset(tags)
98
+
99
+ @staticmethod
100
+ def base_type(type_or_value: t.Any, /) -> type:
101
+ """Return the friendly type of the given type or value. If the type is an AnsibleTaggedObject, the native type will be used."""
102
+ if isinstance(type_or_value, type):
103
+ the_type = type_or_value
104
+ else:
105
+ the_type = type(type_or_value)
106
+
107
+ if issubclass(the_type, AnsibleTaggedObject):
108
+ the_type = type_or_value._native_type
109
+
110
+ # DTFIX-FUTURE: provide a knob to optionally report the real type for debugging purposes
111
+ return the_type
112
+
113
+ @staticmethod
114
+ def as_native_type(value: _T) -> _T:
115
+ """
116
+ Returns an untagged native data type matching the input value, or the original input if the value was not a tagged type.
117
+ Containers are not recursively processed.
118
+ """
119
+ if isinstance(value, AnsibleTaggedObject):
120
+ value = value._native_copy()
121
+
122
+ return value
123
+
124
+ @staticmethod
125
+ @t.overload
126
+ def tag_copy(src: t.Any, value: _T) -> _T: ... # pragma: nocover
127
+
128
+ @staticmethod
129
+ @t.overload
130
+ def tag_copy(src: t.Any, value: t.Any, *, value_type: type[_T]) -> _T: ... # pragma: nocover
131
+
132
+ @staticmethod
133
+ @t.overload
134
+ def tag_copy(src: t.Any, value: _T, *, value_type: None = None) -> _T: ... # pragma: nocover
135
+
136
+ @staticmethod
137
+ def tag_copy(src: t.Any, value: _T, *, value_type: t.Optional[type] = None) -> _T:
138
+ """Return a copy of `value`, with tags copied from `src`, overwriting any existing tags of the same types."""
139
+ src_tags = AnsibleTagHelper.tags(src)
140
+ value_tags = [(tag, tag._get_tag_to_propagate(src, value, value_type=value_type)) for tag in src_tags]
141
+ tags = [tag[1] for tag in value_tags if tag[1] is not None]
142
+ tag_types_to_remove = [type(tag[0]) for tag in value_tags if tag[1] is None]
143
+
144
+ if tag_types_to_remove:
145
+ value = AnsibleTagHelper.untag(value, *tag_types_to_remove)
146
+
147
+ return AnsibleTagHelper.tag(value, tags, value_type=value_type)
148
+
149
+ @staticmethod
150
+ @t.overload
151
+ def tag(value: _T, tags: t.Union[AnsibleDatatagBase, t.Iterable[AnsibleDatatagBase]]) -> _T: ... # pragma: nocover
152
+
153
+ @staticmethod
154
+ @t.overload
155
+ def tag(value: t.Any, tags: t.Union[AnsibleDatatagBase, t.Iterable[AnsibleDatatagBase]], *, value_type: type[_T]) -> _T: ... # pragma: nocover
156
+
157
+ @staticmethod
158
+ @t.overload
159
+ def tag(value: _T, tags: t.Union[AnsibleDatatagBase, t.Iterable[AnsibleDatatagBase]], *, value_type: None = None) -> _T: ... # pragma: nocover
160
+
161
+ @staticmethod
162
+ def tag(value: _T, tags: t.Union[AnsibleDatatagBase, t.Iterable[AnsibleDatatagBase]], *, value_type: t.Optional[type] = None) -> _T:
163
+ """
164
+ Return a copy of `value`, with `tags` applied, overwriting any existing tags of the same types.
165
+ If `value` is an ignored type, or `tags` is empty, the original `value` will be returned.
166
+ If `value` is not taggable, a `NotTaggableError` exception will be raised.
167
+ If `value_type` was given, that type will be returned instead.
168
+ """
169
+ if value_type is None:
170
+ value_type_specified = False
171
+ value_type = type(value)
172
+ else:
173
+ value_type_specified = True
174
+
175
+ # if no tags to apply, just return what we got
176
+ # NB: this only works because the untaggable types are singletons (and thus direct type comparison works)
177
+ if not tags or value_type in _untaggable_types:
178
+ if value_type_specified:
179
+ return value_type(value)
180
+
181
+ return value
182
+
183
+ tag_list: list[AnsibleDatatagBase]
184
+
185
+ # noinspection PyProtectedMember
186
+ if type(tags) in _known_tag_types:
187
+ tag_list = [tags] # type: ignore[list-item]
188
+ else:
189
+ tag_list = list(tags) # type: ignore[arg-type]
190
+
191
+ for idx, tag in enumerate(tag_list):
192
+ # noinspection PyProtectedMember
193
+ if type(tag) not in _known_tag_types:
194
+ # noinspection PyProtectedMember
195
+ raise TypeError(f'tags[{idx}] of type {type(tag)} is not one of {_known_tag_types}')
196
+
197
+ existing_internal_tags_mapping = _try_get_internal_tags_mapping(value)
198
+
199
+ if existing_internal_tags_mapping is not _EMPTY_INTERNAL_TAGS_MAPPING:
200
+ # include the existing tags first so new tags of the same type will overwrite
201
+ tag_list = list(chain(existing_internal_tags_mapping.values(), tag_list))
202
+
203
+ tags_mapping = _AnsibleTagsMapping((type(tag), tag) for tag in tag_list)
204
+ tagged_type = AnsibleTaggedObject._get_tagged_type(value_type)
205
+
206
+ return t.cast(_T, tagged_type._instance_factory(value, tags_mapping))
207
+
208
+ @staticmethod
209
+ def try_tag(value: _T, tags: t.Union[AnsibleDatatagBase, t.Iterable[AnsibleDatatagBase]]) -> _T:
210
+ """
211
+ Return a copy of `value`, with `tags` applied, overwriting any existing tags of the same types.
212
+ If `value` is not taggable or `tags` is empty, the original `value` will be returned.
213
+ """
214
+ try:
215
+ return AnsibleTagHelper.tag(value, tags)
216
+ except NotTaggableError:
217
+ return value
218
+
219
+
220
+ class AnsibleSerializable:
221
+ __slots__ = _NO_INSTANCE_STORAGE
222
+
223
+ _known_type_map: t.ClassVar[t.Dict[str, t.Type['AnsibleSerializable']]] = {}
224
+ _TYPE_KEY: t.ClassVar[str] = '__ansible_type'
225
+
226
+ _type_key: t.ClassVar[str]
227
+
228
+ def __init_subclass__(cls, **kwargs) -> None:
229
+ # this is needed to call __init__subclass__ on mixins for derived types
230
+ super().__init_subclass__(**kwargs)
231
+
232
+ cls._type_key = cls.__name__
233
+
234
+ # DTFIX-FUTURE: is there a better way to exclude non-abstract types which are base classes?
235
+ if not inspect.isabstract(cls) and not cls.__name__.endswith('Base') and cls.__name__ != 'AnsibleTaggedObject':
236
+ AnsibleSerializable._known_type_map[cls._type_key] = cls
237
+
238
+ @classmethod
239
+ @abc.abstractmethod
240
+ def _from_dict(cls: t.Type[_TAnsibleSerializable], d: t.Dict[str, t.Any]) -> object:
241
+ """Return an instance of this type, created from the given dictionary."""
242
+
243
+ @abc.abstractmethod
244
+ def _as_dict(self) -> t.Dict[str, t.Any]:
245
+ """
246
+ Return a serialized version of this instance as a dictionary.
247
+ This operation is *NOT* recursive - the returned dictionary may still include custom types.
248
+ It is the responsibility of the caller to handle recursion of the returned dict.
249
+ """
250
+
251
+ def _serialize(self) -> t.Dict[str, t.Any]:
252
+ value = self._as_dict()
253
+ value.update({AnsibleSerializable._TYPE_KEY: self._type_key})
254
+
255
+ return value
256
+
257
+ @staticmethod
258
+ def _deserialize(data: t.Dict[str, t.Any]) -> object:
259
+ """Deserialize an object from the supplied data dict, which will be mutated if it contains a type key."""
260
+ type_name = data.pop(AnsibleSerializable._TYPE_KEY, ...) # common usage assumes `data` is an intermediate dict provided by a deserializer
261
+
262
+ if type_name is ...:
263
+ return None
264
+
265
+ type_value = AnsibleSerializable._known_type_map.get(type_name)
266
+
267
+ if not type_value:
268
+ raise ValueError(f'An unknown {AnsibleSerializable._TYPE_KEY!r} value {type_name!r} was encountered during deserialization.')
269
+
270
+ return type_value._from_dict(data)
271
+
272
+ def _repr(self, name: str) -> str:
273
+ args = self._as_dict()
274
+ arg_string = ', '.join((f'{k}={v!r}' for k, v in args.items()))
275
+ return f'{name}({arg_string})'
276
+
277
+
278
+ class AnsibleSerializableEnum(AnsibleSerializable, enum.Enum):
279
+ """Base class for serializable enumerations."""
280
+
281
+ def _as_dict(self) -> t.Dict[str, t.Any]:
282
+ return dict(value=self.value)
283
+
284
+ @classmethod
285
+ def _from_dict(cls, d: t.Dict[str, t.Any]) -> t.Self:
286
+ return cls(d['value'].lower())
287
+
288
+ def __str__(self) -> str:
289
+ return self.value
290
+
291
+ def __repr__(self) -> str:
292
+ return f'<{self.__class__.__name__}.{self.name}>'
293
+
294
+ @staticmethod
295
+ def _generate_next_value_(name, start, count, last_values):
296
+ return name.lower()
297
+
298
+
299
+ class AnsibleSerializableWrapper(AnsibleSerializable, t.Generic[_T], metaclass=abc.ABCMeta):
300
+ __slots__ = ('_value',)
301
+
302
+ _wrapped_types: t.ClassVar[dict[type, type[AnsibleSerializable]]] = {}
303
+ _wrapped_type: t.ClassVar[type] = type(None)
304
+
305
+ def __init__(self, value: _T) -> None:
306
+ self._value: _T = value
307
+
308
+ def __init_subclass__(cls, **kwargs):
309
+ super().__init_subclass__(**kwargs)
310
+
311
+ cls._wrapped_type = t.get_args(cls.__orig_bases__[0])[0]
312
+ cls._wrapped_types[cls._wrapped_type] = cls
313
+
314
+
315
+ class AnsibleSerializableDate(AnsibleSerializableWrapper[datetime.date]):
316
+ __slots__ = _NO_INSTANCE_STORAGE
317
+
318
+ @classmethod
319
+ def _from_dict(cls: t.Type[_TAnsibleSerializable], d: t.Dict[str, t.Any]) -> datetime.date:
320
+ return datetime.date.fromisoformat(d['iso8601'])
321
+
322
+ def _as_dict(self) -> t.Dict[str, t.Any]:
323
+ return dict(
324
+ iso8601=self._value.isoformat(),
325
+ )
326
+
327
+
328
+ class AnsibleSerializableTime(AnsibleSerializableWrapper[datetime.time]):
329
+ __slots__ = _NO_INSTANCE_STORAGE
330
+
331
+ @classmethod
332
+ def _from_dict(cls: t.Type[_TAnsibleSerializable], d: t.Dict[str, t.Any]) -> datetime.time:
333
+ value = datetime.time.fromisoformat(d['iso8601'])
334
+ value.replace(fold=d['fold'])
335
+
336
+ return value
337
+
338
+ def _as_dict(self) -> t.Dict[str, t.Any]:
339
+ return dict(
340
+ iso8601=self._value.isoformat(),
341
+ fold=self._value.fold,
342
+ )
343
+
344
+
345
+ class AnsibleSerializableDateTime(AnsibleSerializableWrapper[datetime.datetime]):
346
+ __slots__ = _NO_INSTANCE_STORAGE
347
+
348
+ @classmethod
349
+ def _from_dict(cls: t.Type[_TAnsibleSerializable], d: t.Dict[str, t.Any]) -> datetime.datetime:
350
+ value = datetime.datetime.fromisoformat(d['iso8601'])
351
+ value.replace(fold=d['fold'])
352
+
353
+ return value
354
+
355
+ def _as_dict(self) -> t.Dict[str, t.Any]:
356
+ return dict(
357
+ iso8601=self._value.isoformat(),
358
+ fold=self._value.fold,
359
+ )
360
+
361
+
362
+ @dataclasses.dataclass(**_tag_dataclass_kwargs)
363
+ class AnsibleSerializableDataclass(AnsibleSerializable, metaclass=abc.ABCMeta):
364
+ _validation_allow_subclasses = True
365
+ _validation_auto_enabled = True
366
+
367
+ def _as_dict(self) -> t.Dict[str, t.Any]:
368
+ # omit None values when None is the field default
369
+ # DTFIX-FUTURE: this implementation means we can never change the default on fields which have None for their default
370
+ # other defaults can be changed -- but there's no way to override this behavior either way for other default types
371
+ # it's a trip hazard to have the default logic here, rather than per field (or not at all)
372
+ # consider either removing the filtering or requiring it to be explicitly set per field using dataclass metadata
373
+ fields = ((field, getattr(self, field.name)) for field in dataclasses.fields(self))
374
+ return {field.name: value for field, value in fields if value is not None or field.default is not None}
375
+
376
+ @classmethod
377
+ def _from_dict(cls, d: t.Dict[str, t.Any]) -> t.Self:
378
+ # DTFIX-FUTURE: optimize this to avoid the dataclasses fields metadata and get_origin stuff at runtime
379
+ type_hints = t.get_type_hints(cls)
380
+ mutated_dict: dict[str, t.Any] | None = None
381
+
382
+ for field in dataclasses.fields(cls):
383
+ if t.get_origin(type_hints[field.name]) is tuple: # NOTE: only supports bare tuples, not optional or inside a union
384
+ if type(field_value := d.get(field.name)) is list: # pylint: disable=unidiomatic-typecheck
385
+ if mutated_dict is None:
386
+ mutated_dict = d.copy()
387
+
388
+ mutated_dict[field.name] = tuple(field_value)
389
+
390
+ return cls(**(mutated_dict or d))
391
+
392
+ def __init_subclass__(cls, **kwargs) -> None:
393
+ super(AnsibleSerializableDataclass, cls).__init_subclass__(**kwargs) # cannot use super() without arguments when using slots
394
+
395
+ if cls._validation_auto_enabled:
396
+ try:
397
+ _dataclass_validation.inject_post_init_validation(cls, cls._validation_allow_subclasses) # code gen a real __post_init__ method
398
+ except Exception as ex:
399
+ raise Exception(f'Validation code generation failed on {cls}.') from ex
400
+
401
+
402
+ class Tripwire:
403
+ """Marker mixin for types that should raise an error when encountered."""
404
+
405
+ __slots__ = _NO_INSTANCE_STORAGE
406
+
407
+ def trip(self) -> t.NoReturn:
408
+ """Derived types should implement a failure behavior."""
409
+ raise NotImplementedError()
410
+
411
+
412
+ @dataclasses.dataclass(**_tag_dataclass_kwargs)
413
+ class AnsibleDatatagBase(AnsibleSerializableDataclass, metaclass=abc.ABCMeta):
414
+ """
415
+ Base class for data tagging tag types.
416
+ New tag types need to be considered very carefully; e.g.: which serialization/runtime contexts they're allowed in, fallback behavior, propagation.
417
+ """
418
+
419
+ _validation_allow_subclasses = False
420
+
421
+ def __init_subclass__(cls, **kwargs) -> None:
422
+ # NOTE: This method is called twice when the datatag type is a dataclass.
423
+ super(AnsibleDatatagBase, cls).__init_subclass__(**kwargs) # cannot use super() without arguments when using slots
424
+
425
+ # DTFIX-FUTURE: "freeze" this after module init has completed to discourage custom external tag subclasses
426
+
427
+ # DTFIX-FUTURE: is there a better way to exclude non-abstract types which are base classes?
428
+ if not inspect.isabstract(cls) and not cls.__name__.endswith('Base'):
429
+ existing = _known_tag_type_map.get(cls.__name__)
430
+
431
+ if existing:
432
+ # When the datatag type is a dataclass, the first instance will be the non-dataclass type.
433
+ # It must be removed from the known tag types before adding the dataclass version.
434
+ _known_tag_types.remove(existing)
435
+
436
+ _known_tag_type_map[cls.__name__] = cls
437
+ _known_tag_types.add(cls)
438
+
439
+ @classmethod
440
+ def is_tagged_on(cls, value: t.Any) -> bool:
441
+ return cls in _try_get_internal_tags_mapping(value)
442
+
443
+ @classmethod
444
+ def first_tagged_on(cls, *values: t.Any) -> t.Any | None:
445
+ """Return the first value which is tagged with this type, or None if no match is found."""
446
+ for value in values:
447
+ if cls.is_tagged_on(value):
448
+ return value
449
+
450
+ return None
451
+
452
+ @classmethod
453
+ def get_tag(cls, value: t.Any) -> t.Optional[t.Self]:
454
+ return _try_get_internal_tags_mapping(value).get(cls)
455
+
456
+ @classmethod
457
+ def get_required_tag(cls, value: t.Any) -> t.Self:
458
+ if (tag := cls.get_tag(value)) is None:
459
+ # DTFIX-FUTURE: we really should have a way to use AnsibleError with obj in module_utils when it's controller-side
460
+ raise ValueError(f'The type {type(value).__name__!r} is not tagged with {cls.__name__!r}.')
461
+
462
+ return tag
463
+
464
+ @classmethod
465
+ def untag(cls, value: _T) -> _T:
466
+ """
467
+ If this tag type is present on `value`, return a copy with that tag removed.
468
+ Otherwise, the original `value` is returned.
469
+ """
470
+ return AnsibleTagHelper.untag(value, cls)
471
+
472
+ def tag(self, value: _T) -> _T:
473
+ """
474
+ Return a copy of `value` with this tag applied, overwriting any existing tag of the same type.
475
+ If `value` is an ignored type, the original `value` will be returned.
476
+ If `value` is not taggable, a `NotTaggableError` exception will be raised.
477
+ """
478
+ return AnsibleTagHelper.tag(value, self)
479
+
480
+ def try_tag(self, value: _T) -> _T:
481
+ """
482
+ Return a copy of `value` with this tag applied, overwriting any existing tag of the same type.
483
+ If `value` is not taggable, the original `value` will be returned.
484
+ """
485
+ return AnsibleTagHelper.try_tag(value, self)
486
+
487
+ def _get_tag_to_propagate(self, src: t.Any, value: object, *, value_type: t.Optional[type] = None) -> t.Self | None:
488
+ """
489
+ Called by `AnsibleTagHelper.tag_copy` during tag propagation.
490
+ Returns an instance of this tag appropriate for propagation to `value`, or `None` if the tag should not be propagated.
491
+ Derived implementations may consult the arguments relayed from `tag_copy` to determine if and how the tag should be propagated.
492
+ """
493
+ return self
494
+
495
+ def __repr__(self) -> str:
496
+ return AnsibleSerializable._repr(self, self.__class__.__name__)
497
+
498
+
499
+ # used by the datatag Ansible/Jinja test plugin to find tags by name
500
+ _known_tag_type_map: t.Dict[str, t.Type[AnsibleDatatagBase]] = {}
501
+ _known_tag_types: t.Set[t.Type[AnsibleDatatagBase]] = set()
502
+
503
+ if sys.version_info >= (3, 9):
504
+ # Include the key and value types in the type hints on Python 3.9 and later.
505
+ # Earlier versions do not support subscriptable dict.
506
+ # deprecated: description='always use subscriptable dict' python_version='3.8'
507
+ class _AnsibleTagsMapping(dict[type[_TAnsibleDatatagBase], _TAnsibleDatatagBase]):
508
+ __slots__ = _NO_INSTANCE_STORAGE
509
+
510
+ else:
511
+
512
+ class _AnsibleTagsMapping(dict):
513
+ __slots__ = _NO_INSTANCE_STORAGE
514
+
515
+
516
+ class _EmptyROInternalTagsMapping(dict):
517
+ """
518
+ Optimizes empty tag mapping by using a shared singleton read-only dict.
519
+ Since mappingproxy is not pickle-able and causes other problems, we had to roll our own.
520
+ """
521
+
522
+ def __new__(cls):
523
+ try:
524
+ # noinspection PyUnresolvedReferences
525
+ return cls._instance
526
+ except AttributeError:
527
+ cls._instance = dict.__new__(cls)
528
+
529
+ # noinspection PyUnresolvedReferences
530
+ return cls._instance
531
+
532
+ def __setitem__(self, key, value):
533
+ raise NotImplementedError()
534
+
535
+ def setdefault(self, __key, __default=None):
536
+ raise NotImplementedError()
537
+
538
+ def update(self, __m, **kwargs):
539
+ raise NotImplementedError()
540
+
541
+
542
+ _EMPTY_INTERNAL_TAGS_MAPPING = t.cast(_AnsibleTagsMapping, _EmptyROInternalTagsMapping())
543
+ """
544
+ An empty read-only mapping of tags.
545
+ Also used as a sentinel to cheaply determine that a type is not tagged by using a reference equality check.
546
+ """
547
+
548
+
549
+ class CollectionWithMro(c.Collection, t.Protocol):
550
+ """Used to represent a Collection with __mro__ in a TypeGuard for tools that don't include __mro__ in Collection."""
551
+
552
+ __mro__: tuple[type, ...]
553
+
554
+
555
+ def is_non_scalar_collection_type(value: type) -> t.TypeGuard[type[CollectionWithMro]]:
556
+ """Returns True if the value is a non-scalar collection type, otherwise returns False."""
557
+ return issubclass(value, c.Collection) and not issubclass(value, str) and not issubclass(value, bytes)
558
+
559
+
560
+ def _try_get_internal_tags_mapping(value: t.Any) -> _AnsibleTagsMapping:
561
+ """Return the internal tag mapping of the given value, or a sentinel value if it is not tagged."""
562
+ # noinspection PyBroadException
563
+ try:
564
+ # noinspection PyProtectedMember
565
+ tags = value._ansible_tags_mapping
566
+ except Exception:
567
+ # try/except is a cheap way to determine if this is a tagged object without using isinstance
568
+ # handling Exception accounts for types that may raise something other than AttributeError
569
+ return _EMPTY_INTERNAL_TAGS_MAPPING
570
+
571
+ # handle cases where the instance always returns something, such as Marker or MagicMock
572
+ if type(tags) is not _AnsibleTagsMapping: # pylint: disable=unidiomatic-typecheck
573
+ return _EMPTY_INTERNAL_TAGS_MAPPING
574
+
575
+ return tags
576
+
577
+
578
+ class NotTaggableError(TypeError):
579
+ def __init__(self, value):
580
+ super(NotTaggableError, self).__init__('{} is not taggable'.format(value))
581
+
582
+
583
+ @dataclasses.dataclass(**_tag_dataclass_kwargs)
584
+ class AnsibleSingletonTagBase(AnsibleDatatagBase):
585
+ def __new__(cls):
586
+ try:
587
+ # noinspection PyUnresolvedReferences
588
+ return cls._instance
589
+ except AttributeError:
590
+ cls._instance = AnsibleDatatagBase.__new__(cls)
591
+
592
+ # noinspection PyUnresolvedReferences
593
+ return cls._instance
594
+
595
+ def _as_dict(self) -> t.Dict[str, t.Any]:
596
+ return {}
597
+
598
+
599
+ class AnsibleTaggedObject(AnsibleSerializable):
600
+ __slots__ = _NO_INSTANCE_STORAGE
601
+
602
+ _native_type: t.ClassVar[type]
603
+ _item_source: t.ClassVar[t.Optional[t.Callable]] = None
604
+
605
+ _tagged_type_map: t.ClassVar[t.Dict[type, t.Type['AnsibleTaggedObject']]] = {}
606
+ _tagged_collection_types: t.ClassVar[t.Set[t.Type[c.Collection]]] = set()
607
+ _collection_types: t.ClassVar[t.Set[t.Type[c.Collection]]] = set()
608
+
609
+ _empty_tags_as_native: t.ClassVar[bool] = True # by default, untag will revert to the native type when no tags remain
610
+ _subclasses_native_type: t.ClassVar[bool] = True # by default, tagged types are assumed to subclass the type they augment
611
+
612
+ _ansible_tags_mapping: _AnsibleTagsMapping | _EmptyROInternalTagsMapping = _EMPTY_INTERNAL_TAGS_MAPPING
613
+ """
614
+ Efficient internal storage of tags, indexed by tag type.
615
+ Contains no more than one instance of each tag type.
616
+ This is defined as a class attribute to support type hinting and documentation.
617
+ It is overwritten with an instance attribute during instance creation.
618
+ The instance attribute slot is provided by the derived type.
619
+ """
620
+
621
+ def __init_subclass__(cls, **kwargs) -> None:
622
+ super().__init_subclass__(**kwargs)
623
+
624
+ try:
625
+ init_class = cls._init_class # type: ignore[attr-defined]
626
+ except AttributeError:
627
+ pass
628
+ else:
629
+ init_class()
630
+
631
+ if not cls._subclasses_native_type:
632
+ return # NOTE: When not subclassing a native type, the derived type must set cls._native_type itself and cls._empty_tags_as_native to False.
633
+
634
+ try:
635
+ # Subclasses of tagged types will already have a native type set and won't need to detect it.
636
+ # Special types which do not subclass a native type can also have their native type already set.
637
+ # Automatic item source selection is only implemented for types that don't set _native_type.
638
+ cls._native_type
639
+ except AttributeError:
640
+ # Direct subclasses of native types won't have cls._native_type set, so detect the native type.
641
+ cls._native_type = cls.__bases__[0]
642
+
643
+ # Detect the item source if not already set.
644
+ if cls._item_source is None and is_non_scalar_collection_type(cls._native_type):
645
+ cls._item_source = cls._native_type.__iter__ # type: ignore[attr-defined]
646
+
647
+ # Use a collection specific factory for types with item sources.
648
+ if cls._item_source:
649
+ cls._instance_factory = cls._instance_factory_collection # type: ignore[method-assign]
650
+
651
+ new_type_direct_subclass = cls.__mro__[1]
652
+
653
+ conflicting_impl = AnsibleTaggedObject._tagged_type_map.get(new_type_direct_subclass)
654
+
655
+ if conflicting_impl:
656
+ raise TypeError(f'Cannot define type {cls.__name__!r} since {conflicting_impl.__name__!r} already extends {new_type_direct_subclass.__name__!r}.')
657
+
658
+ AnsibleTaggedObject._tagged_type_map[new_type_direct_subclass] = cls
659
+
660
+ if is_non_scalar_collection_type(cls):
661
+ AnsibleTaggedObject._tagged_collection_types.add(cls)
662
+ AnsibleTaggedObject._collection_types.update({cls, new_type_direct_subclass})
663
+
664
+ def _native_copy(self) -> t.Any:
665
+ """
666
+ Returns a copy of the current instance as its native Python type.
667
+ Any dynamic access behaviors that apply to this instance will be used during creation of the copy.
668
+ In the case of a container type, this is a shallow copy.
669
+ Recursive calls to native_copy are the responsibility of the caller.
670
+ """
671
+ return self._native_type(self) # pylint: disable=abstract-class-instantiated
672
+
673
+ @classmethod
674
+ def _instance_factory(cls, value: t.Any, tags_mapping: _AnsibleTagsMapping) -> t.Self:
675
+ # There's no way to indicate cls is callable with a single arg without defining a useless __init__.
676
+ instance = cls(value) # type: ignore[call-arg]
677
+ instance._ansible_tags_mapping = tags_mapping
678
+
679
+ return instance
680
+
681
+ @staticmethod
682
+ def _get_tagged_type(value_type: type) -> type[AnsibleTaggedObject]:
683
+ tagged_type: t.Optional[type[AnsibleTaggedObject]]
684
+
685
+ if issubclass(value_type, AnsibleTaggedObject):
686
+ tagged_type = value_type
687
+ else:
688
+ tagged_type = AnsibleTaggedObject._tagged_type_map.get(value_type)
689
+
690
+ if not tagged_type:
691
+ raise NotTaggableError(value_type)
692
+
693
+ return tagged_type
694
+
695
+ def _as_dict(self) -> t.Dict[str, t.Any]:
696
+ return dict(
697
+ value=self._native_copy(),
698
+ tags=list(self._ansible_tags_mapping.values()),
699
+ )
700
+
701
+ @classmethod
702
+ def _from_dict(cls: t.Type[_TAnsibleTaggedObject], d: t.Dict[str, t.Any]) -> _TAnsibleTaggedObject:
703
+ return AnsibleTagHelper.tag(**d)
704
+
705
+ @classmethod
706
+ def _instance_factory_collection(
707
+ cls,
708
+ value: t.Any,
709
+ tags_mapping: _AnsibleTagsMapping,
710
+ ) -> t.Self:
711
+ if type(value) in AnsibleTaggedObject._collection_types:
712
+ # use the underlying iterator to avoid access/iteration side effects (e.g. templating/wrapping on Lazy subclasses)
713
+ instance = cls(cls._item_source(value)) # type: ignore[call-arg,misc]
714
+ else:
715
+ # this is used when the value is a generator
716
+ instance = cls(value) # type: ignore[call-arg]
717
+
718
+ instance._ansible_tags_mapping = tags_mapping
719
+
720
+ return instance
721
+
722
+ def _copy_collection(self) -> AnsibleTaggedObject:
723
+ """
724
+ Return a shallow copy of this instance, which must be a collection.
725
+ This uses the underlying iterator to avoid access/iteration side effects (e.g. templating/wrapping on Lazy subclasses).
726
+ """
727
+ return AnsibleTagHelper.tag_copy(self, type(self)._item_source(self), value_type=type(self)) # type: ignore[misc]
728
+
729
+ @classmethod
730
+ def _new(cls, value: t.Any, *args, **kwargs) -> t.Self:
731
+ if type(value) is _AnsibleTagsMapping: # pylint: disable=unidiomatic-typecheck
732
+ self = cls._native_type.__new__(cls, *args, **kwargs)
733
+ self._ansible_tags_mapping = value
734
+ return self
735
+
736
+ return cls._native_type.__new__(cls, value, *args, **kwargs)
737
+
738
+ def _reduce(self, reduced: t.Union[str, tuple[t.Any, ...]]) -> tuple:
739
+ if type(reduced) is not tuple: # pylint: disable=unidiomatic-typecheck
740
+ raise TypeError()
741
+
742
+ updated: list[t.Any] = list(reduced)
743
+ updated[1] = (self._ansible_tags_mapping,) + updated[1]
744
+
745
+ return tuple(updated)
746
+
747
+
748
+ class _AnsibleTaggedStr(str, AnsibleTaggedObject):
749
+ __slots__ = _ANSIBLE_TAGGED_OBJECT_SLOTS
750
+
751
+
752
+ class _AnsibleTaggedBytes(bytes, AnsibleTaggedObject):
753
+ # nonempty __slots__ not supported for subtype of 'bytes'
754
+ pass
755
+
756
+
757
+ class _AnsibleTaggedInt(int, AnsibleTaggedObject):
758
+ # nonempty __slots__ not supported for subtype of 'int'
759
+ pass
760
+
761
+
762
+ class _AnsibleTaggedFloat(float, AnsibleTaggedObject):
763
+ __slots__ = _ANSIBLE_TAGGED_OBJECT_SLOTS
764
+
765
+
766
+ class _AnsibleTaggedDateTime(datetime.datetime, AnsibleTaggedObject):
767
+ __slots__ = _ANSIBLE_TAGGED_OBJECT_SLOTS
768
+
769
+ @classmethod
770
+ def _instance_factory(cls, value: datetime.datetime, tags_mapping: _AnsibleTagsMapping) -> _AnsibleTaggedDateTime:
771
+ instance = cls(
772
+ year=value.year,
773
+ month=value.month,
774
+ day=value.day,
775
+ hour=value.hour,
776
+ minute=value.minute,
777
+ second=value.second,
778
+ microsecond=value.microsecond,
779
+ tzinfo=value.tzinfo,
780
+ fold=value.fold,
781
+ )
782
+
783
+ instance._ansible_tags_mapping = tags_mapping
784
+
785
+ return instance
786
+
787
+ def _native_copy(self) -> datetime.datetime:
788
+ return datetime.datetime(
789
+ year=self.year,
790
+ month=self.month,
791
+ day=self.day,
792
+ hour=self.hour,
793
+ minute=self.minute,
794
+ second=self.second,
795
+ microsecond=self.microsecond,
796
+ tzinfo=self.tzinfo,
797
+ fold=self.fold,
798
+ )
799
+
800
+ def __new__(cls, year, *args, **kwargs):
801
+ return super()._new(year, *args, **kwargs)
802
+
803
+ def __reduce_ex__(self, protocol: t.SupportsIndex) -> tuple:
804
+ return super()._reduce(super().__reduce_ex__(protocol))
805
+
806
+ def __repr__(self) -> str:
807
+ return self._native_copy().__repr__()
808
+
809
+
810
+ class _AnsibleTaggedDate(datetime.date, AnsibleTaggedObject):
811
+ __slots__ = _ANSIBLE_TAGGED_OBJECT_SLOTS
812
+
813
+ @classmethod
814
+ def _instance_factory(cls, value: datetime.date, tags_mapping: _AnsibleTagsMapping) -> _AnsibleTaggedDate:
815
+ instance = cls(
816
+ year=value.year,
817
+ month=value.month,
818
+ day=value.day,
819
+ )
820
+
821
+ instance._ansible_tags_mapping = tags_mapping
822
+
823
+ return instance
824
+
825
+ def _native_copy(self) -> datetime.date:
826
+ return datetime.date(
827
+ year=self.year,
828
+ month=self.month,
829
+ day=self.day,
830
+ )
831
+
832
+ def __new__(cls, year, *args, **kwargs):
833
+ return super()._new(year, *args, **kwargs)
834
+
835
+ def __reduce__(self) -> tuple:
836
+ return super()._reduce(super().__reduce__())
837
+
838
+ def __repr__(self) -> str:
839
+ return self._native_copy().__repr__()
840
+
841
+
842
+ class _AnsibleTaggedTime(datetime.time, AnsibleTaggedObject):
843
+ __slots__ = _ANSIBLE_TAGGED_OBJECT_SLOTS
844
+
845
+ @classmethod
846
+ def _instance_factory(cls, value: datetime.time, tags_mapping: _AnsibleTagsMapping) -> _AnsibleTaggedTime:
847
+ instance = cls(
848
+ hour=value.hour,
849
+ minute=value.minute,
850
+ second=value.second,
851
+ microsecond=value.microsecond,
852
+ tzinfo=value.tzinfo,
853
+ fold=value.fold,
854
+ )
855
+
856
+ instance._ansible_tags_mapping = tags_mapping
857
+
858
+ return instance
859
+
860
+ def _native_copy(self) -> datetime.time:
861
+ return datetime.time(
862
+ hour=self.hour,
863
+ minute=self.minute,
864
+ second=self.second,
865
+ microsecond=self.microsecond,
866
+ tzinfo=self.tzinfo,
867
+ fold=self.fold,
868
+ )
869
+
870
+ def __new__(cls, hour, *args, **kwargs):
871
+ return super()._new(hour, *args, **kwargs)
872
+
873
+ def __reduce_ex__(self, protocol: t.SupportsIndex) -> tuple:
874
+ return super()._reduce(super().__reduce_ex__(protocol))
875
+
876
+ def __repr__(self) -> str:
877
+ return self._native_copy().__repr__()
878
+
879
+
880
+ class _AnsibleTaggedDict(dict, AnsibleTaggedObject):
881
+ __slots__ = _ANSIBLE_TAGGED_OBJECT_SLOTS
882
+
883
+ _item_source: t.ClassVar[t.Optional[t.Callable]] = dict.items
884
+
885
+ def __copy__(self):
886
+ return super()._copy_collection()
887
+
888
+ def copy(self) -> _AnsibleTaggedDict:
889
+ return copy.copy(self)
890
+
891
+ # NB: Tags are intentionally not preserved for operator methods that return a new instance. In-place operators ignore tags from the `other` instance.
892
+ # Propagation of tags in these cases is left to the caller, based on needs specific to their use case.
893
+
894
+
895
+ class _AnsibleTaggedList(list, AnsibleTaggedObject):
896
+ __slots__ = _ANSIBLE_TAGGED_OBJECT_SLOTS
897
+
898
+ def __copy__(self):
899
+ return super()._copy_collection()
900
+
901
+ def copy(self) -> _AnsibleTaggedList:
902
+ return copy.copy(self)
903
+
904
+ # NB: Tags are intentionally not preserved for operator methods that return a new instance. In-place operators ignore tags from the `other` instance.
905
+ # Propagation of tags in these cases is left to the caller, based on needs specific to their use case.
906
+
907
+
908
+ class _AnsibleTaggedSet(set, AnsibleTaggedObject):
909
+ __slots__ = _ANSIBLE_TAGGED_OBJECT_SLOTS
910
+
911
+ def __copy__(self):
912
+ return super()._copy_collection()
913
+
914
+ def copy(self):
915
+ return copy.copy(self)
916
+
917
+ def __init__(self, value=None, *args, **kwargs):
918
+ if type(value) is _AnsibleTagsMapping: # pylint: disable=unidiomatic-typecheck
919
+ super().__init__(*args, **kwargs)
920
+ else:
921
+ super().__init__(value, *args, **kwargs)
922
+
923
+ def __new__(cls, value=None, *args, **kwargs):
924
+ return super()._new(value, *args, **kwargs)
925
+
926
+ def __reduce_ex__(self, protocol: t.SupportsIndex) -> tuple:
927
+ return super()._reduce(super().__reduce_ex__(protocol))
928
+
929
+ def __str__(self) -> str:
930
+ return self._native_copy().__str__()
931
+
932
+ def __repr__(self) -> str:
933
+ return self._native_copy().__repr__()
934
+
935
+
936
+ class _AnsibleTaggedTuple(tuple, AnsibleTaggedObject):
937
+ # nonempty __slots__ not supported for subtype of 'tuple'
938
+
939
+ def __copy__(self):
940
+ return super()._copy_collection()
941
+
942
+
943
+ _untaggable_types = {type(None), bool}
944
+ """
945
+ Attempts to apply tags to values of these types will be silently ignored.
946
+ While we could proxy or subclass builtin singletons, they're idiomatically compared with "is" reference equality, which we can't customize.
947
+ This set gets augmented with additional types when some controller-only types are imported.
948
+ """
949
+
950
+ # noinspection PyProtectedMember
951
+ _ANSIBLE_ALLOWED_VAR_TYPES = frozenset({type(None), bool}) | set(AnsibleTaggedObject._tagged_type_map) | set(AnsibleTaggedObject._tagged_type_map.values())
952
+ """These are the exact types supported by Ansible's variable storage."""
953
+
954
+ _ANSIBLE_ALLOWED_NON_SCALAR_COLLECTION_VAR_TYPES = frozenset(item for item in _ANSIBLE_ALLOWED_VAR_TYPES if is_non_scalar_collection_type(item))
955
+ """These are the exact non-scalar collection types supported by Ansible's variable storage."""
956
+
957
+ _ANSIBLE_ALLOWED_MAPPING_VAR_TYPES = frozenset(item for item in _ANSIBLE_ALLOWED_VAR_TYPES if issubclass(item, c.Mapping))
958
+ """These are the exact mapping types supported by Ansible's variable storage."""
959
+
960
+ _ANSIBLE_ALLOWED_SCALAR_VAR_TYPES = _ANSIBLE_ALLOWED_VAR_TYPES - _ANSIBLE_ALLOWED_NON_SCALAR_COLLECTION_VAR_TYPES
961
+ """These are the exact scalar types supported by Ansible's variable storage."""