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
@@ -10,13 +10,13 @@ from ansible.utils.vars import combine_vars
10
10
 
11
11
 
12
12
  class ActionModule(ActionBase):
13
- ''' Validate an arg spec'''
13
+ """ Validate an arg spec"""
14
14
 
15
15
  TRANSFERS_FILES = False
16
16
  _requires_connection = False
17
17
 
18
18
  def get_args_from_task_vars(self, argument_spec, task_vars):
19
- '''
19
+ """
20
20
  Get any arguments that may come from `task_vars`.
21
21
 
22
22
  Expand templated variables so we can validate the actual values.
@@ -25,7 +25,7 @@ class ActionModule(ActionBase):
25
25
  :param task_vars: A dict of task variables.
26
26
 
27
27
  :returns: A dict of values that can be validated against the arg spec.
28
- '''
28
+ """
29
29
  args = {}
30
30
 
31
31
  for argument_name, argument_attrs in argument_spec.items():
@@ -35,7 +35,7 @@ class ActionModule(ActionBase):
35
35
  return args
36
36
 
37
37
  def run(self, tmp=None, task_vars=None):
38
- '''
38
+ """
39
39
  Validate an argument specification against a provided set of data.
40
40
 
41
41
  The `validate_argument_spec` module expects to receive the arguments:
@@ -48,7 +48,7 @@ class ActionModule(ActionBase):
48
48
  :param task_vars: A dict of task variables.
49
49
  :return: An action result dict, including a 'argument_errors' key with a
50
50
  list of validation errors found.
51
- '''
51
+ """
52
52
  if task_vars is None:
53
53
  task_vars = dict()
54
54
 
@@ -76,7 +76,7 @@ class ActionModule(ActionBase):
76
76
  del tmp # tmp no longer has any effect
77
77
 
78
78
  def ping_module_test(connect_timeout):
79
- ''' Test ping module, if available '''
79
+ """ Test ping module, if available """
80
80
  display.vvv("wait_for_connection: attempting ping module test")
81
81
  # re-run interpreter discovery if we ran it in the first iteration
82
82
  if self._discovered_interpreter_key:
@@ -3,6 +3,7 @@
3
3
  # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
4
4
  from __future__ import annotations
5
5
 
6
+ import re
6
7
  import shlex
7
8
 
8
9
  from abc import abstractmethod
@@ -13,10 +14,11 @@ from gettext import dgettext
13
14
  from ansible.errors import AnsibleError
14
15
  from ansible.module_utils.common.text.converters import to_bytes
15
16
  from ansible.plugins import AnsiblePlugin
17
+ from ansible.utils import display as _display
16
18
 
17
19
 
18
20
  def _gen_id(length=32):
19
- ''' return random string used to identify the current privilege escalation '''
21
+ """ return random string used to identify the current privilege escalation """
20
22
  return ''.join(choice(ascii_lowercase) for x in range(length))
21
23
 
22
24
 
@@ -32,6 +34,9 @@ class BecomeBase(AnsiblePlugin):
32
34
  # plugin requires a tty, i.e su
33
35
  require_tty = False
34
36
 
37
+ # plugin allows for pipelining execution
38
+ pipelining = True
39
+
35
40
  # prompt to match
36
41
  prompt = ''
37
42
 
@@ -53,11 +58,11 @@ class BecomeBase(AnsiblePlugin):
53
58
 
54
59
  return getattr(playcontext, option, None)
55
60
 
56
- def expect_prompt(self):
61
+ def expect_prompt(self) -> bool:
57
62
  """This function assists connection plugins in determining if they need to wait for
58
63
  a prompt. Both a prompt and a password are required.
59
64
  """
60
- return self.prompt and self.get_option('become_pass')
65
+ return bool(self.prompt and self.get_option('become_pass'))
61
66
 
62
67
  def _build_success_command(self, cmd, shell, noexe=False):
63
68
  if not all((cmd, shell, self.success)):
@@ -65,9 +70,8 @@ class BecomeBase(AnsiblePlugin):
65
70
 
66
71
  try:
67
72
  cmd = shlex.quote('%s %s %s %s' % (shell.ECHO, self.success, shell.COMMAND_SEP, cmd))
68
- except AttributeError:
69
- # TODO: This should probably become some more robust functionality used to detect incompat
70
- raise AnsibleError('The %s shell family is incompatible with the %s become plugin' % (shell.SHELL_FAMILY, self.name))
73
+ except AttributeError as ex:
74
+ raise AnsibleError(f'The {shell._load_name!r} shell plugin does not support become. It is missing the {ex.name!r} attribute.')
71
75
  exe = getattr(shell, 'executable', None)
72
76
  if exe and not noexe:
73
77
  cmd = '%s -c %s' % (exe, cmd)
@@ -78,19 +82,38 @@ class BecomeBase(AnsiblePlugin):
78
82
  self._id = _gen_id()
79
83
  self.success = 'BECOME-SUCCESS-%s' % self._id
80
84
 
85
+ def strip_become_prompt(self, data: bytes) -> bytes:
86
+ """
87
+ Strips the first found configured become prompt from `data`, trailing whitespace and anything that precedes the prompt, then returns the result.
88
+ If no prompt is expected, or the prompt is not `str` or `bytes`, `data` will be returned as-is.
89
+ """
90
+ if not self.prompt or not isinstance(self.prompt, (str, bytes)) or not self.expect_prompt():
91
+ return data
92
+
93
+ return self._strip_through_prefix(self.prompt, data)
94
+
95
+ def strip_become_success(self, data: bytes) -> bytes:
96
+ """Strips the first found success marker from `data`, trailing whitespace and anything that precedes the success marker, then returns the result."""
97
+ return self._strip_through_prefix(self.success, data)
98
+
99
+ @staticmethod
100
+ def _strip_through_prefix(match: str | bytes, data: bytes) -> bytes:
101
+ """Strips the first occurrence of `match` from `data`, trailing whitespace and anything that precedes `match`, then returns the result."""
102
+ return re.sub(br'^.*?' + re.escape(to_bytes(match)) + br'\s*', b'', data, count=1, flags=re.DOTALL)
103
+
81
104
  def check_success(self, b_output):
82
105
  b_success = to_bytes(self.success)
83
106
  return any(b_success in l.rstrip() for l in b_output.splitlines(True))
84
107
 
85
108
  def check_password_prompt(self, b_output):
86
- ''' checks if the expected password prompt exists in b_output '''
109
+ """ checks if the expected password prompt exists in b_output """
87
110
  if self.prompt:
88
111
  b_prompt = to_bytes(self.prompt).strip()
89
112
  return any(l.strip().startswith(b_prompt) for l in b_output.splitlines())
90
113
  return False
91
114
 
92
115
  def _check_password_error(self, b_out, msg):
93
- ''' returns True/False if domain specific i18n version of msg is found in b_out '''
116
+ """ returns True/False if domain specific i18n version of msg is found in b_out """
94
117
  b_fail = to_bytes(dgettext(self.name, msg))
95
118
  return b_fail and b_fail in b_out
96
119
 
@@ -61,6 +61,8 @@ DOCUMENTATION = """
61
61
  - The Secondary Logon service (seclogon) must be running to use runas
62
62
  """
63
63
 
64
+ from ansible.errors import AnsibleError
65
+ from ansible.parsing.splitter import split_args
64
66
  from ansible.plugins.become import BecomeBase
65
67
 
66
68
 
@@ -72,3 +74,72 @@ class BecomeModule(BecomeBase):
72
74
  # this is a noop, the 'real' runas is implemented
73
75
  # inside the windows powershell execution subsystem
74
76
  return cmd
77
+
78
+ def _build_powershell_wrapper_action(self) -> tuple[str, dict[str, object], dict[str, object]]:
79
+ # See ansible.executor.powershell.become_wrapper.ps1 for the
80
+ # parameter names
81
+ params = {
82
+ 'BecomeUser': self.get_option('become_user'),
83
+ }
84
+ secure_params = {}
85
+
86
+ password = self.get_option('become_pass')
87
+ if password:
88
+ secure_params['BecomePassword'] = password
89
+
90
+ flags = self.get_option('become_flags')
91
+ if flags:
92
+ split_flags = split_args(flags)
93
+ for flag in split_flags:
94
+ if '=' not in flag:
95
+ raise ValueError(f"become_flags entry '{flag}' is in an invalid format, must be a key=value pair")
96
+
97
+ k, v = flag.split('=', 1)
98
+
99
+ param_name, param_value = self._parse_flag(k, v)
100
+ params[param_name] = param_value
101
+
102
+ return 'become_wrapper.ps1', params, secure_params
103
+
104
+ def _parse_flag(self, name: str, value: str) -> tuple[str, str]:
105
+ logon_types = {
106
+ 'interactive': 'Interactive',
107
+ 'network': 'Network',
108
+ 'batch': 'Batch',
109
+ 'service': 'Service',
110
+ 'unlock': 'Unlock',
111
+ 'network_cleartext': 'NetworkCleartext',
112
+ 'new_credentials': 'NewCredentials',
113
+ }
114
+ logon_flags = {
115
+ 'none': 'None',
116
+ 'with_profile': 'WithProfile',
117
+ 'netcredentials_only': 'NetCredentialsOnly',
118
+ }
119
+
120
+ match name.lower():
121
+ case 'logon_type':
122
+ param_name = 'LogonType'
123
+ if param_value := logon_types.get(value.lower(), None):
124
+ return param_name, param_value
125
+ else:
126
+ raise AnsibleError(f"become_flags logon_type value '{value}' is not valid, valid values are: {', '.join(logon_types.keys())}")
127
+
128
+ case 'logon_flags':
129
+ param_name = 'LogonFlags'
130
+ flags = value.split(',')
131
+
132
+ param_values: list[str] = []
133
+ for flag in flags:
134
+ if not flag:
135
+ continue
136
+
137
+ if flag_value := logon_flags.get(flag.lower(), None):
138
+ param_values.append(flag_value)
139
+ else:
140
+ raise AnsibleError(f"become_flags logon_flags value '{flag}' is not valid, valid values are: {', '.join(logon_flags.keys())}")
141
+
142
+ return param_name, ", ".join(param_values)
143
+
144
+ case _:
145
+ raise AnsibleError(f"become_flags key '{name}' is not a valid runas flag, must be 'logon_type' or 'logon_flags'")
@@ -93,7 +93,7 @@ DOCUMENTATION = """
93
93
  import re
94
94
  import shlex
95
95
 
96
- from ansible.module_utils.common.text.converters import to_bytes
96
+ from ansible.module_utils.common.text.converters import to_text
97
97
  from ansible.plugins.become import BecomeBase
98
98
 
99
99
 
@@ -101,6 +101,8 @@ class BecomeModule(BecomeBase):
101
101
 
102
102
  name = 'su'
103
103
 
104
+ pipelining = False
105
+
104
106
  # messages for detecting prompted password issues
105
107
  fail = ('Authentication failure',)
106
108
 
@@ -139,15 +141,18 @@ class BecomeModule(BecomeBase):
139
141
  '口令',
140
142
  ]
141
143
 
142
- def check_password_prompt(self, b_output):
143
- ''' checks if the expected password prompt exists in b_output '''
144
-
144
+ def check_password_prompt(self, b_output: bytes) -> bool:
145
+ """ checks if the expected password prompt exists in b_output """
145
146
  prompts = self.get_option('prompt_l10n') or self.SU_PROMPT_LOCALIZATIONS
146
- b_password_string = b"|".join((br'(\w+\'s )?' + to_bytes(p)) for p in prompts)
147
+ password_prompt_strings = "|".join(re.escape(p) for p in prompts)
147
148
  # Colon or unicode fullwidth colon
148
- b_password_string = b_password_string + to_bytes(u' ?(:|:) ?')
149
- b_su_prompt_localizations_re = re.compile(b_password_string, flags=re.IGNORECASE)
150
- return bool(b_su_prompt_localizations_re.match(b_output))
149
+ prompt_pattern = rf"(?:{password_prompt_strings})\s*[::]"
150
+ match = re.search(prompt_pattern, to_text(b_output), flags=re.IGNORECASE)
151
+
152
+ if match:
153
+ self.prompt = match.group(0) # preserve the actual matched string so we can scrub the output
154
+
155
+ return bool(match)
151
156
 
152
157
  def build_become_command(self, cmd, shell):
153
158
  super(BecomeModule, self).build_become_command(cmd, shell)
@@ -72,12 +72,25 @@ DOCUMENTATION = """
72
72
  ini:
73
73
  - section: sudo_become_plugin
74
74
  key: password
75
+ sudo_chdir:
76
+ description: Directory to change to before invoking sudo; can avoid permission errors when dropping privileges.
77
+ type: string
78
+ required: False
79
+ version_added: '2.19'
80
+ vars:
81
+ - name: ansible_sudo_chdir
82
+ env:
83
+ - name: ANSIBLE_SUDO_CHDIR
84
+ ini:
85
+ - section: sudo_become_plugin
86
+ key: chdir
75
87
  """
76
88
 
77
89
  import re
78
90
  import shlex
79
91
 
80
92
  from ansible.plugins.become import BecomeBase
93
+ from ansible.errors import AnsibleError
81
94
 
82
95
 
83
96
  class BecomeModule(BecomeBase):
@@ -117,4 +130,10 @@ class BecomeModule(BecomeBase):
117
130
  if user:
118
131
  user = '-u %s' % (user)
119
132
 
133
+ if chdir := self.get_option('sudo_chdir'):
134
+ try:
135
+ becomecmd = f'{shell.CD} {shlex.quote(chdir)} {shell._SHELL_AND} {becomecmd}'
136
+ except AttributeError as ex:
137
+ raise AnsibleError(f'The {shell._load_name!r} shell plugin does not support sudo chdir. It is missing the {ex.name!r} attribute.')
138
+
120
139
  return ' '.join([becomecmd, flags, prompt, user, self._build_success_command(cmd, shell)])
@@ -18,18 +18,18 @@
18
18
  from __future__ import annotations
19
19
 
20
20
  import copy
21
- import errno
22
21
  import os
23
22
  import tempfile
24
23
  import time
24
+ import typing as t
25
25
 
26
26
  from abc import abstractmethod
27
- from collections.abc import MutableMapping
27
+ from collections import abc as c
28
28
 
29
29
  from ansible import constants as C
30
30
  from ansible.errors import AnsibleError
31
31
  from ansible.module_utils.common.file import S_IRWU_RG_RO
32
- from ansible.module_utils.common.text.converters import to_bytes, to_text
32
+ from ansible.module_utils.common.text.converters import to_bytes
33
33
  from ansible.plugins import AnsiblePlugin
34
34
  from ansible.plugins.loader import cache_loader
35
35
  from ansible.utils.collection_loader import resource_from_fqcr
@@ -42,37 +42,36 @@ class BaseCacheModule(AnsiblePlugin):
42
42
 
43
43
  # Backwards compat only. Just import the global display instead
44
44
  _display = display
45
+ _persistent = True
46
+ """Plugins that do not persist data between runs can set False to bypass schema-version key munging and JSON serialization wrapper."""
45
47
 
46
- def __init__(self, *args, **kwargs):
47
- super(BaseCacheModule, self).__init__()
48
- self.set_options(var_options=args, direct=kwargs)
48
+ def __init__(self, *args, **kwargs) -> None:
49
+ super().__init__()
49
50
 
50
- @abstractmethod
51
- def get(self, key):
52
- pass
51
+ self.set_options(var_options=args, direct=kwargs)
53
52
 
54
53
  @abstractmethod
55
- def set(self, key, value):
54
+ def get(self, key: str) -> dict[str, object]:
56
55
  pass
57
56
 
58
57
  @abstractmethod
59
- def keys(self):
58
+ def set(self, key: str, value: dict[str, object]) -> None:
60
59
  pass
61
60
 
62
61
  @abstractmethod
63
- def contains(self, key):
62
+ def keys(self) -> t.Sequence[str]:
64
63
  pass
65
64
 
66
65
  @abstractmethod
67
- def delete(self, key):
66
+ def contains(self, key: object) -> bool:
68
67
  pass
69
68
 
70
69
  @abstractmethod
71
- def flush(self):
70
+ def delete(self, key: str) -> None:
72
71
  pass
73
72
 
74
73
  @abstractmethod
75
- def copy(self):
74
+ def flush(self) -> None:
76
75
  pass
77
76
 
78
77
 
@@ -108,15 +107,15 @@ class BaseFileCacheModule(BaseCacheModule):
108
107
  if not os.path.exists(self._cache_dir):
109
108
  try:
110
109
  os.makedirs(self._cache_dir)
111
- except (OSError, IOError) as e:
112
- raise AnsibleError("error in '%s' cache plugin while trying to create cache dir %s : %s" % (self.plugin_name, self._cache_dir, to_bytes(e)))
110
+ except OSError as ex:
111
+ raise AnsibleError(f"Error in {self.plugin_name!r} cache plugin while trying to create cache dir {self._cache_dir!r}.") from ex
113
112
  else:
114
113
  for x in (os.R_OK, os.W_OK, os.X_OK):
115
114
  if not os.access(self._cache_dir, x):
116
115
  raise AnsibleError("error in '%s' cache, configured path (%s) does not have necessary permissions (rwx), disabling plugin" % (
117
116
  self.plugin_name, self._cache_dir))
118
117
 
119
- def _get_cache_file_name(self, key):
118
+ def _get_cache_file_name(self, key: str) -> str:
120
119
  prefix = self.get_option('_prefix')
121
120
  if prefix:
122
121
  cachefile = "%s/%s%s" % (self._cache_dir, prefix, key)
@@ -144,11 +143,10 @@ class BaseFileCacheModule(BaseCacheModule):
144
143
  self.delete(key)
145
144
  raise AnsibleError("The cache file %s was corrupt, or did not otherwise contain valid data. "
146
145
  "It has been removed, so you can re-run your command now." % cachefile)
147
- except (OSError, IOError) as e:
148
- display.warning("error in '%s' cache plugin while trying to read %s : %s" % (self.plugin_name, cachefile, to_bytes(e)))
146
+ except FileNotFoundError:
149
147
  raise KeyError
150
- except Exception as e:
151
- raise AnsibleError("Error while decoding the cache file %s: %s" % (cachefile, to_bytes(e)))
148
+ except Exception as ex:
149
+ raise AnsibleError(f"Error while accessing the cache file {cachefile!r}.") from ex
152
150
 
153
151
  return self._cache.get(key)
154
152
 
@@ -161,13 +159,13 @@ class BaseFileCacheModule(BaseCacheModule):
161
159
  try:
162
160
  try:
163
161
  self._dump(value, tmpfile_path)
164
- except (OSError, IOError) as e:
165
- display.warning("error in '%s' cache plugin while trying to write to '%s' : %s" % (self.plugin_name, tmpfile_path, to_bytes(e)))
162
+ except OSError as ex:
163
+ display.error_as_warning(f"Error in {self.plugin_name!r} cache plugin while trying to write to {tmpfile_path!r}.", exception=ex)
166
164
  try:
167
165
  os.rename(tmpfile_path, cachefile)
168
166
  os.chmod(cachefile, mode=S_IRWU_RG_RO)
169
- except (OSError, IOError) as e:
170
- display.warning("error in '%s' cache plugin while trying to move '%s' to '%s' : %s" % (self.plugin_name, tmpfile_path, cachefile, to_bytes(e)))
167
+ except OSError as ex:
168
+ display.error_as_warning(f"Error in {self.plugin_name!r} cache plugin while trying to move {tmpfile_path!r} to {cachefile!r}.", exception=ex)
171
169
  finally:
172
170
  try:
173
171
  os.unlink(tmpfile_path)
@@ -182,12 +180,12 @@ class BaseFileCacheModule(BaseCacheModule):
182
180
  cachefile = self._get_cache_file_name(key)
183
181
  try:
184
182
  st = os.stat(cachefile)
185
- except (OSError, IOError) as e:
186
- if e.errno == errno.ENOENT:
187
- return False
188
- else:
189
- display.warning("error in '%s' cache plugin while trying to stat %s : %s" % (self.plugin_name, cachefile, to_bytes(e)))
190
- return False
183
+ except FileNotFoundError:
184
+ return False
185
+ except OSError as ex:
186
+ display.error_as_warning(f"Error in {self.plugin_name!r} cache plugin while trying to stat {cachefile!r}.", exception=ex)
187
+
188
+ return False
191
189
 
192
190
  if time.time() - st.st_mtime <= self._timeout:
193
191
  return False
@@ -224,11 +222,10 @@ class BaseFileCacheModule(BaseCacheModule):
224
222
  try:
225
223
  os.stat(cachefile)
226
224
  return True
227
- except (OSError, IOError) as e:
228
- if e.errno == errno.ENOENT:
229
- return False
230
- else:
231
- display.warning("error in '%s' cache plugin while trying to stat %s : %s" % (self.plugin_name, cachefile, to_bytes(e)))
225
+ except FileNotFoundError:
226
+ return False
227
+ except OSError as ex:
228
+ display.error_as_warning(f"Error in {self.plugin_name!r} cache plugin while trying to stat {cachefile!r}.", exception=ex)
232
229
 
233
230
  def delete(self, key):
234
231
  try:
@@ -237,7 +234,7 @@ class BaseFileCacheModule(BaseCacheModule):
237
234
  pass
238
235
  try:
239
236
  os.remove(self._get_cache_file_name(key))
240
- except (OSError, IOError):
237
+ except OSError:
241
238
  pass # TODO: only pass on non existing?
242
239
 
243
240
  def flush(self):
@@ -245,14 +242,8 @@ class BaseFileCacheModule(BaseCacheModule):
245
242
  for key in self.keys():
246
243
  self.delete(key)
247
244
 
248
- def copy(self):
249
- ret = dict()
250
- for key in self.keys():
251
- ret[key] = self.get(key)
252
- return ret
253
-
254
245
  @abstractmethod
255
- def _load(self, filepath):
246
+ def _load(self, filepath: str) -> object:
256
247
  """
257
248
  Read data from a filepath and return it as a value
258
249
 
@@ -271,7 +262,7 @@ class BaseFileCacheModule(BaseCacheModule):
271
262
  pass
272
263
 
273
264
  @abstractmethod
274
- def _dump(self, value, filepath):
265
+ def _dump(self, value: object, filepath: str) -> None:
275
266
  """
276
267
  Write data to a filepath
277
268
 
@@ -281,19 +272,13 @@ class BaseFileCacheModule(BaseCacheModule):
281
272
  pass
282
273
 
283
274
 
284
- class CachePluginAdjudicator(MutableMapping):
285
- """
286
- Intermediary between a cache dictionary and a CacheModule
287
- """
275
+ class CachePluginAdjudicator(c.MutableMapping):
276
+ """Batch update wrapper around a cache plugin."""
277
+
288
278
  def __init__(self, plugin_name='memory', **kwargs):
289
279
  self._cache = {}
290
280
  self._retrieved = {}
291
-
292
281
  self._plugin = cache_loader.get(plugin_name, **kwargs)
293
- if not self._plugin:
294
- raise AnsibleError('Unable to load the cache plugin (%s).' % plugin_name)
295
-
296
- self._plugin_name = plugin_name
297
282
 
298
283
  def update_cache_if_changed(self):
299
284
  if self._retrieved != self._cache:
@@ -302,6 +287,7 @@ class CachePluginAdjudicator(MutableMapping):
302
287
  def set_cache(self):
303
288
  for top_level_cache_key in self._cache.keys():
304
289
  self._plugin.set(top_level_cache_key, self._cache[top_level_cache_key])
290
+
305
291
  self._retrieved = copy.deepcopy(self._cache)
306
292
 
307
293
  def load_whole_cache(self):
@@ -309,7 +295,7 @@ class CachePluginAdjudicator(MutableMapping):
309
295
  self._cache[key] = self._plugin.get(key)
310
296
 
311
297
  def __repr__(self):
312
- return to_text(self._cache)
298
+ return repr(self._cache)
313
299
 
314
300
  def __iter__(self):
315
301
  return iter(self.keys())
@@ -319,13 +305,10 @@ class CachePluginAdjudicator(MutableMapping):
319
305
 
320
306
  def _do_load_key(self, key):
321
307
  load = False
322
- if all([
323
- key not in self._cache,
324
- key not in self._retrieved,
325
- self._plugin_name != 'memory',
326
- self._plugin.contains(key),
327
- ]):
308
+
309
+ if key not in self._cache and key not in self._retrieved and self._plugin._persistent and self._plugin.contains(key):
328
310
  load = True
311
+
329
312
  return load
330
313
 
331
314
  def __getitem__(self, key):
@@ -336,16 +319,18 @@ class CachePluginAdjudicator(MutableMapping):
336
319
  pass
337
320
  else:
338
321
  self._retrieved[key] = self._cache[key]
322
+
339
323
  return self._cache[key]
340
324
 
341
325
  def get(self, key, default=None):
342
326
  if self._do_load_key(key):
343
327
  try:
344
328
  self._cache[key] = self._plugin.get(key)
345
- except KeyError as e:
329
+ except KeyError:
346
330
  pass
347
331
  else:
348
332
  self._retrieved[key] = self._cache[key]
333
+
349
334
  return self._cache.get(key, default)
350
335
 
351
336
  def items(self):
@@ -360,6 +345,7 @@ class CachePluginAdjudicator(MutableMapping):
360
345
  def pop(self, key, *args):
361
346
  if args:
362
347
  return self._cache.pop(key, args[0])
348
+
363
349
  return self._cache.pop(key)
364
350
 
365
351
  def __delitem__(self, key):
@@ -368,6 +354,9 @@ class CachePluginAdjudicator(MutableMapping):
368
354
  def __setitem__(self, key, value):
369
355
  self._cache[key] = value
370
356
 
357
+ def clear(self):
358
+ self.flush()
359
+
371
360
  def flush(self):
372
361
  self._plugin.flush()
373
362
  self._cache = {}
@@ -18,3 +18,11 @@ from __future__ import annotations
18
18
 
19
19
  # moved actual classes to __init__ kept here for backward compat with 3rd parties
20
20
  from ansible.plugins.cache import BaseCacheModule, BaseFileCacheModule # pylint: disable=unused-import
21
+
22
+ from ansible.utils.display import Display as _Display
23
+
24
+ _Display().deprecated(
25
+ msg="The `ansible.plugins.cache.base` Python module is deprecated.",
26
+ help_text="Import from `ansible.plugins.cache` instead.",
27
+ version="2.23",
28
+ )
@@ -4,7 +4,7 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- DOCUMENTATION = '''
7
+ DOCUMENTATION = """
8
8
  name: jsonfile
9
9
  short_description: JSON formatted files.
10
10
  description:
@@ -38,25 +38,19 @@ DOCUMENTATION = '''
38
38
  - key: fact_caching_timeout
39
39
  section: defaults
40
40
  type: integer
41
- '''
41
+ """
42
42
 
43
- import codecs
44
43
  import json
44
+ import pathlib
45
45
 
46
- from ansible.parsing.ajson import AnsibleJSONEncoder, AnsibleJSONDecoder
47
46
  from ansible.plugins.cache import BaseFileCacheModule
48
47
 
49
48
 
50
49
  class CacheModule(BaseFileCacheModule):
51
- """
52
- A caching module backed by json files.
53
- """
54
-
55
- def _load(self, filepath):
56
- # Valid JSON is always UTF-8 encoded.
57
- with codecs.open(filepath, 'r', encoding='utf-8') as f:
58
- return json.load(f, cls=AnsibleJSONDecoder)
59
-
60
- def _dump(self, value, filepath):
61
- with codecs.open(filepath, 'w', encoding='utf-8') as f:
62
- f.write(json.dumps(value, cls=AnsibleJSONEncoder, sort_keys=True, indent=4))
50
+ """A caching module backed by json files."""
51
+
52
+ def _load(self, filepath: str) -> object:
53
+ return json.loads(pathlib.Path(filepath).read_text())
54
+
55
+ def _dump(self, value: object, filepath: str) -> None:
56
+ pathlib.Path(filepath).write_text(json.dumps(value))