ansible-core 2.18.5rc1__py3-none-any.whl → 2.19.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (709) hide show
  1. ansible/_internal/__init__.py +53 -0
  2. ansible/_internal/_ansiballz.py +265 -0
  3. ansible/_internal/_datatag/__init__.py +0 -0
  4. ansible/_internal/_datatag/_tags.py +130 -0
  5. ansible/_internal/_datatag/_utils.py +19 -0
  6. ansible/_internal/_datatag/_wrappers.py +33 -0
  7. ansible/_internal/_errors/__init__.py +0 -0
  8. ansible/_internal/_errors/_captured.py +128 -0
  9. ansible/_internal/_errors/_handler.py +91 -0
  10. ansible/_internal/_errors/_utils.py +310 -0
  11. ansible/_internal/_json/__init__.py +160 -0
  12. ansible/_internal/_json/_legacy_encoder.py +34 -0
  13. ansible/_internal/_json/_profiles/__init__.py +0 -0
  14. ansible/_internal/_json/_profiles/_cache_persistence.py +55 -0
  15. ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
  16. ansible/_internal/_json/_profiles/_legacy.py +198 -0
  17. ansible/_internal/_locking.py +21 -0
  18. ansible/_internal/_plugins/__init__.py +0 -0
  19. ansible/_internal/_plugins/_cache.py +57 -0
  20. ansible/_internal/_task.py +78 -0
  21. ansible/_internal/_templating/__init__.py +10 -0
  22. ansible/_internal/_templating/_access.py +86 -0
  23. ansible/_internal/_templating/_chain_templar.py +63 -0
  24. ansible/_internal/_templating/_datatag.py +95 -0
  25. ansible/_internal/_templating/_engine.py +588 -0
  26. ansible/_internal/_templating/_errors.py +28 -0
  27. ansible/_internal/_templating/_jinja_bits.py +1066 -0
  28. ansible/_internal/_templating/_jinja_common.py +332 -0
  29. ansible/_internal/_templating/_jinja_patches.py +44 -0
  30. ansible/_internal/_templating/_jinja_plugins.py +351 -0
  31. ansible/_internal/_templating/_lazy_containers.py +633 -0
  32. ansible/_internal/_templating/_marker_behaviors.py +103 -0
  33. ansible/_internal/_templating/_transform.py +63 -0
  34. ansible/_internal/_templating/_utils.py +107 -0
  35. ansible/_internal/_wrapt.py +1052 -0
  36. ansible/_internal/_yaml/__init__.py +0 -0
  37. ansible/_internal/_yaml/_constructor.py +240 -0
  38. ansible/_internal/_yaml/_dumper.py +62 -0
  39. ansible/_internal/_yaml/_errors.py +166 -0
  40. ansible/_internal/_yaml/_loader.py +66 -0
  41. ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
  42. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
  43. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
  44. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +18 -0
  45. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
  46. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
  47. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
  48. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
  49. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
  50. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
  51. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
  52. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
  53. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
  54. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
  55. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
  56. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
  57. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
  58. ansible/cli/__init__.py +153 -89
  59. ansible/cli/_ssh_askpass.py +47 -0
  60. ansible/cli/adhoc.py +14 -7
  61. ansible/cli/arguments/option_helpers.py +154 -7
  62. ansible/cli/config.py +43 -68
  63. ansible/cli/console.py +10 -8
  64. ansible/cli/doc.py +48 -46
  65. ansible/cli/galaxy.py +27 -20
  66. ansible/cli/inventory.py +28 -26
  67. ansible/cli/playbook.py +4 -12
  68. ansible/cli/pull.py +51 -11
  69. ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
  70. ansible/cli/vault.py +12 -11
  71. ansible/compat/__init__.py +2 -2
  72. ansible/config/base.yml +165 -108
  73. ansible/config/manager.py +52 -49
  74. ansible/constants.py +3 -4
  75. ansible/errors/__init__.py +277 -235
  76. ansible/executor/interpreter_discovery.py +28 -149
  77. ansible/executor/module_common.py +426 -493
  78. ansible/executor/play_iterator.py +22 -27
  79. ansible/executor/playbook_executor.py +11 -11
  80. ansible/executor/powershell/async_watchdog.ps1 +97 -102
  81. ansible/executor/powershell/async_wrapper.ps1 +202 -151
  82. ansible/executor/powershell/become_wrapper.ps1 +89 -144
  83. ansible/executor/powershell/bootstrap_wrapper.ps1 +24 -9
  84. ansible/executor/powershell/coverage_wrapper.ps1 +82 -135
  85. ansible/executor/powershell/exec_wrapper.ps1 +462 -196
  86. ansible/executor/powershell/module_manifest.py +417 -265
  87. ansible/executor/powershell/module_wrapper.ps1 +169 -186
  88. ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
  89. ansible/executor/powershell/psrp_put_file.ps1 +122 -0
  90. ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
  91. ansible/executor/powershell/winrm_put_file.ps1 +36 -0
  92. ansible/executor/process/worker.py +136 -76
  93. ansible/executor/stats.py +5 -5
  94. ansible/executor/task_executor.py +237 -236
  95. ansible/executor/task_queue_manager.py +62 -38
  96. ansible/executor/task_result.py +21 -12
  97. ansible/galaxy/__init__.py +2 -2
  98. ansible/galaxy/api.py +22 -18
  99. ansible/galaxy/collection/__init__.py +1 -1
  100. ansible/galaxy/collection/concrete_artifact_manager.py +8 -11
  101. ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
  102. ansible/galaxy/dependency_resolution/providers.py +1 -1
  103. ansible/galaxy/dependency_resolution/reporters.py +81 -0
  104. ansible/galaxy/role.py +4 -8
  105. ansible/galaxy/token.py +28 -21
  106. ansible/inventory/data.py +47 -57
  107. ansible/inventory/group.py +44 -72
  108. ansible/inventory/helpers.py +9 -0
  109. ansible/inventory/host.py +32 -54
  110. ansible/inventory/manager.py +77 -34
  111. ansible/keyword_desc.yml +1 -1
  112. ansible/module_utils/_internal/__init__.py +55 -0
  113. ansible/module_utils/_internal/_ambient_context.py +58 -0
  114. ansible/module_utils/_internal/_ansiballz.py +133 -0
  115. ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
  116. ansible/module_utils/_internal/_dataclass_annotation_patch.py +64 -0
  117. ansible/module_utils/_internal/_dataclass_validation.py +217 -0
  118. ansible/module_utils/_internal/_datatag/__init__.py +928 -0
  119. ansible/module_utils/_internal/_datatag/_tags.py +38 -0
  120. ansible/module_utils/_internal/_debugging.py +31 -0
  121. ansible/module_utils/_internal/_errors.py +30 -0
  122. ansible/module_utils/_internal/_json/__init__.py +63 -0
  123. ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
  124. ansible/module_utils/_internal/_json/_profiles/__init__.py +410 -0
  125. ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
  126. ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +31 -0
  127. ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +35 -0
  128. ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
  129. ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
  130. ansible/module_utils/_internal/_json/_profiles/_tagless.py +50 -0
  131. ansible/module_utils/_internal/_patches/__init__.py +66 -0
  132. ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +55 -0
  133. ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
  134. ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
  135. ansible/module_utils/_internal/_plugin_exec_context.py +49 -0
  136. ansible/module_utils/_internal/_testing.py +0 -0
  137. ansible/module_utils/_internal/_traceback.py +89 -0
  138. ansible/module_utils/ansible_release.py +2 -2
  139. ansible/module_utils/api.py +1 -2
  140. ansible/module_utils/basic.py +154 -120
  141. ansible/module_utils/common/_utils.py +24 -28
  142. ansible/module_utils/common/collections.py +1 -2
  143. ansible/module_utils/common/dict_transformations.py +2 -2
  144. ansible/module_utils/common/file.py +2 -2
  145. ansible/module_utils/common/json.py +90 -84
  146. ansible/module_utils/common/locale.py +2 -2
  147. ansible/module_utils/common/messages.py +108 -0
  148. ansible/module_utils/common/parameters.py +27 -24
  149. ansible/module_utils/common/process.py +2 -2
  150. ansible/module_utils/common/respawn.py +41 -19
  151. ansible/module_utils/common/sentinel.py +66 -0
  152. ansible/module_utils/common/sys_info.py +8 -8
  153. ansible/module_utils/common/text/converters.py +16 -37
  154. ansible/module_utils/common/validation.py +35 -24
  155. ansible/module_utils/common/warnings.py +86 -25
  156. ansible/module_utils/common/yaml.py +29 -3
  157. ansible/module_utils/compat/datetime.py +33 -21
  158. ansible/module_utils/compat/paramiko.py +21 -10
  159. ansible/module_utils/compat/typing.py +6 -5
  160. ansible/module_utils/connection.py +2 -2
  161. ansible/module_utils/csharp/Ansible.Basic.cs +14 -11
  162. ansible/module_utils/csharp/Ansible.Become.cs +1 -0
  163. ansible/module_utils/csharp/Ansible._Async.cs +517 -0
  164. ansible/module_utils/datatag.py +46 -0
  165. ansible/module_utils/distro/__init__.py +2 -2
  166. ansible/module_utils/facts/ansible_collector.py +4 -5
  167. ansible/module_utils/facts/collector.py +13 -14
  168. ansible/module_utils/facts/compat.py +4 -4
  169. ansible/module_utils/facts/default_collectors.py +1 -1
  170. ansible/module_utils/facts/hardware/aix.py +34 -0
  171. ansible/module_utils/facts/hardware/base.py +1 -1
  172. ansible/module_utils/facts/hardware/darwin.py +1 -3
  173. ansible/module_utils/facts/hardware/freebsd.py +2 -2
  174. ansible/module_utils/facts/hardware/linux.py +4 -4
  175. ansible/module_utils/facts/namespace.py +1 -1
  176. ansible/module_utils/facts/network/base.py +1 -1
  177. ansible/module_utils/facts/network/fc_wwn.py +1 -2
  178. ansible/module_utils/facts/network/iscsi.py +1 -2
  179. ansible/module_utils/facts/network/nvme.py +1 -2
  180. ansible/module_utils/facts/other/facter.py +1 -2
  181. ansible/module_utils/facts/other/ohai.py +2 -3
  182. ansible/module_utils/facts/system/apparmor.py +1 -2
  183. ansible/module_utils/facts/system/caps.py +1 -1
  184. ansible/module_utils/facts/system/chroot.py +1 -2
  185. ansible/module_utils/facts/system/cmdline.py +1 -2
  186. ansible/module_utils/facts/system/date_time.py +5 -3
  187. ansible/module_utils/facts/system/distribution.py +9 -8
  188. ansible/module_utils/facts/system/dns.py +1 -1
  189. ansible/module_utils/facts/system/env.py +1 -2
  190. ansible/module_utils/facts/system/fips.py +7 -20
  191. ansible/module_utils/facts/system/loadavg.py +1 -2
  192. ansible/module_utils/facts/system/local.py +1 -2
  193. ansible/module_utils/facts/system/lsb.py +1 -2
  194. ansible/module_utils/facts/system/pkg_mgr.py +1 -2
  195. ansible/module_utils/facts/system/platform.py +1 -2
  196. ansible/module_utils/facts/system/python.py +1 -2
  197. ansible/module_utils/facts/system/selinux.py +1 -1
  198. ansible/module_utils/facts/system/service_mgr.py +1 -2
  199. ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
  200. ansible/module_utils/facts/system/systemd.py +1 -1
  201. ansible/module_utils/facts/system/user.py +1 -2
  202. ansible/module_utils/facts/utils.py +3 -3
  203. ansible/module_utils/facts/virtual/base.py +1 -1
  204. ansible/module_utils/facts/virtual/sunos.py +3 -15
  205. ansible/module_utils/facts/virtual/sysctl.py +3 -16
  206. ansible/module_utils/json_utils.py +2 -2
  207. ansible/module_utils/parsing/convert_bool.py +1 -1
  208. ansible/module_utils/service.py +18 -21
  209. ansible/module_utils/splitter.py +7 -7
  210. ansible/module_utils/testing.py +31 -0
  211. ansible/module_utils/urls.py +60 -31
  212. ansible/modules/add_host.py +4 -4
  213. ansible/modules/apt.py +60 -46
  214. ansible/modules/apt_key.py +19 -12
  215. ansible/modules/apt_repository.py +19 -16
  216. ansible/modules/assemble.py +6 -6
  217. ansible/modules/assert.py +4 -4
  218. ansible/modules/async_status.py +10 -12
  219. ansible/modules/async_wrapper.py +8 -3
  220. ansible/modules/blockinfile.py +6 -7
  221. ansible/modules/command.py +10 -17
  222. ansible/modules/copy.py +57 -144
  223. ansible/modules/cron.py +20 -15
  224. ansible/modules/deb822_repository.py +8 -9
  225. ansible/modules/debconf.py +5 -5
  226. ansible/modules/debug.py +4 -4
  227. ansible/modules/dnf.py +8 -8
  228. ansible/modules/dnf5.py +39 -13
  229. ansible/modules/dpkg_selections.py +4 -4
  230. ansible/modules/expect.py +8 -10
  231. ansible/modules/fail.py +4 -4
  232. ansible/modules/fetch.py +4 -4
  233. ansible/modules/file.py +174 -133
  234. ansible/modules/find.py +19 -17
  235. ansible/modules/gather_facts.py +3 -3
  236. ansible/modules/get_url.py +59 -53
  237. ansible/modules/getent.py +7 -9
  238. ansible/modules/git.py +28 -25
  239. ansible/modules/group.py +6 -6
  240. ansible/modules/group_by.py +4 -4
  241. ansible/modules/hostname.py +13 -29
  242. ansible/modules/import_playbook.py +6 -6
  243. ansible/modules/import_role.py +6 -6
  244. ansible/modules/import_tasks.py +6 -6
  245. ansible/modules/include_role.py +6 -6
  246. ansible/modules/include_tasks.py +6 -6
  247. ansible/modules/include_vars.py +6 -6
  248. ansible/modules/iptables.py +86 -73
  249. ansible/modules/known_hosts.py +10 -10
  250. ansible/modules/lineinfile.py +5 -5
  251. ansible/modules/meta.py +4 -4
  252. ansible/modules/mount_facts.py +2 -2
  253. ansible/modules/package.py +4 -4
  254. ansible/modules/package_facts.py +22 -10
  255. ansible/modules/pause.py +6 -6
  256. ansible/modules/ping.py +6 -6
  257. ansible/modules/pip.py +10 -11
  258. ansible/modules/raw.py +4 -4
  259. ansible/modules/reboot.py +6 -6
  260. ansible/modules/replace.py +9 -13
  261. ansible/modules/rpm_key.py +7 -8
  262. ansible/modules/script.py +4 -4
  263. ansible/modules/service.py +7 -8
  264. ansible/modules/service_facts.py +87 -10
  265. ansible/modules/set_fact.py +5 -5
  266. ansible/modules/set_stats.py +4 -4
  267. ansible/modules/setup.py +2 -2
  268. ansible/modules/shell.py +6 -6
  269. ansible/modules/slurp.py +6 -6
  270. ansible/modules/stat.py +9 -23
  271. ansible/modules/subversion.py +15 -15
  272. ansible/modules/systemd.py +6 -6
  273. ansible/modules/systemd_service.py +6 -6
  274. ansible/modules/sysvinit.py +6 -6
  275. ansible/modules/tempfile.py +5 -6
  276. ansible/modules/template.py +6 -6
  277. ansible/modules/unarchive.py +32 -11
  278. ansible/modules/uri.py +33 -26
  279. ansible/modules/user.py +53 -34
  280. ansible/modules/validate_argument_spec.py +10 -7
  281. ansible/modules/wait_for.py +32 -27
  282. ansible/modules/wait_for_connection.py +6 -6
  283. ansible/modules/yum_repository.py +6 -6
  284. ansible/parsing/ajson.py +14 -32
  285. ansible/parsing/dataloader.py +99 -54
  286. ansible/parsing/mod_args.py +28 -44
  287. ansible/parsing/plugin_docs.py +21 -86
  288. ansible/parsing/quoting.py +1 -1
  289. ansible/parsing/splitter.py +27 -12
  290. ansible/parsing/utils/addresses.py +24 -24
  291. ansible/parsing/utils/yaml.py +32 -61
  292. ansible/parsing/vault/__init__.py +319 -87
  293. ansible/parsing/yaml/__init__.py +0 -18
  294. ansible/parsing/yaml/dumper.py +6 -120
  295. ansible/parsing/yaml/loader.py +6 -39
  296. ansible/parsing/yaml/objects.py +36 -339
  297. ansible/playbook/__init__.py +1 -1
  298. ansible/playbook/attribute.py +8 -3
  299. ansible/playbook/base.py +182 -132
  300. ansible/playbook/block.py +26 -24
  301. ansible/playbook/collectionsearch.py +1 -15
  302. ansible/playbook/conditional.py +3 -77
  303. ansible/playbook/handler.py +8 -2
  304. ansible/playbook/helpers.py +41 -53
  305. ansible/playbook/included_file.py +6 -15
  306. ansible/playbook/loop_control.py +2 -2
  307. ansible/playbook/play.py +85 -44
  308. ansible/playbook/play_context.py +12 -17
  309. ansible/playbook/playbook_include.py +14 -15
  310. ansible/playbook/role/__init__.py +24 -26
  311. ansible/playbook/role/definition.py +15 -17
  312. ansible/playbook/role/include.py +2 -4
  313. ansible/playbook/role/metadata.py +10 -11
  314. ansible/playbook/role_include.py +3 -3
  315. ansible/playbook/taggable.py +13 -8
  316. ansible/playbook/task.py +188 -118
  317. ansible/playbook/task_include.py +5 -5
  318. ansible/plugins/__init__.py +68 -21
  319. ansible/plugins/action/__init__.py +209 -176
  320. ansible/plugins/action/add_host.py +1 -1
  321. ansible/plugins/action/assemble.py +1 -1
  322. ansible/plugins/action/assert.py +54 -66
  323. ansible/plugins/action/copy.py +7 -11
  324. ansible/plugins/action/debug.py +37 -31
  325. ansible/plugins/action/dnf.py +3 -4
  326. ansible/plugins/action/fail.py +1 -1
  327. ansible/plugins/action/fetch.py +4 -5
  328. ansible/plugins/action/gather_facts.py +7 -6
  329. ansible/plugins/action/group_by.py +1 -1
  330. ansible/plugins/action/include_vars.py +10 -11
  331. ansible/plugins/action/package.py +3 -6
  332. ansible/plugins/action/pause.py +2 -2
  333. ansible/plugins/action/script.py +15 -8
  334. ansible/plugins/action/service.py +6 -11
  335. ansible/plugins/action/set_fact.py +3 -12
  336. ansible/plugins/action/set_stats.py +3 -8
  337. ansible/plugins/action/template.py +35 -59
  338. ansible/plugins/action/unarchive.py +1 -1
  339. ansible/plugins/action/validate_argument_spec.py +5 -5
  340. ansible/plugins/action/wait_for_connection.py +1 -1
  341. ansible/plugins/become/__init__.py +31 -8
  342. ansible/plugins/become/runas.py +71 -0
  343. ansible/plugins/become/su.py +13 -8
  344. ansible/plugins/become/sudo.py +19 -0
  345. ansible/plugins/cache/__init__.py +35 -44
  346. ansible/plugins/cache/base.py +8 -0
  347. ansible/plugins/cache/jsonfile.py +10 -16
  348. ansible/plugins/cache/memory.py +6 -12
  349. ansible/plugins/callback/__init__.py +141 -123
  350. ansible/plugins/callback/default.py +30 -23
  351. ansible/plugins/callback/junit.py +28 -24
  352. ansible/plugins/callback/minimal.py +17 -14
  353. ansible/plugins/callback/oneline.py +13 -7
  354. ansible/plugins/callback/tree.py +10 -6
  355. ansible/plugins/connection/__init__.py +47 -34
  356. ansible/plugins/connection/local.py +150 -54
  357. ansible/plugins/connection/paramiko_ssh.py +21 -18
  358. ansible/plugins/connection/psrp.py +76 -165
  359. ansible/plugins/connection/ssh.py +301 -78
  360. ansible/plugins/connection/winrm.py +58 -140
  361. ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
  362. ansible/plugins/doc_fragments/action_core.py +6 -6
  363. ansible/plugins/doc_fragments/backup.py +2 -2
  364. ansible/plugins/doc_fragments/checksum_common.py +27 -0
  365. ansible/plugins/doc_fragments/constructed.py +6 -2
  366. ansible/plugins/doc_fragments/decrypt.py +2 -2
  367. ansible/plugins/doc_fragments/default_callback.py +2 -2
  368. ansible/plugins/doc_fragments/files.py +2 -2
  369. ansible/plugins/doc_fragments/inventory_cache.py +2 -2
  370. ansible/plugins/doc_fragments/result_format_callback.py +2 -2
  371. ansible/plugins/doc_fragments/return_common.py +2 -2
  372. ansible/plugins/doc_fragments/template_common.py +4 -4
  373. ansible/plugins/doc_fragments/url.py +17 -1
  374. ansible/plugins/doc_fragments/url_windows.py +2 -2
  375. ansible/plugins/doc_fragments/validate.py +2 -2
  376. ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
  377. ansible/plugins/filter/__init__.py +6 -2
  378. ansible/plugins/filter/b64decode.yml +22 -0
  379. ansible/plugins/filter/b64encode.yml +22 -0
  380. ansible/plugins/filter/bool.yml +11 -4
  381. ansible/plugins/filter/core.py +218 -108
  382. ansible/plugins/filter/encryption.py +32 -32
  383. ansible/plugins/filter/flatten.yml +3 -2
  384. ansible/plugins/filter/human_to_bytes.yml +1 -1
  385. ansible/plugins/filter/mathstuff.py +30 -37
  386. ansible/plugins/filter/password_hash.yml +8 -0
  387. ansible/plugins/filter/regex_search.yml +1 -4
  388. ansible/plugins/filter/split.yml +1 -1
  389. ansible/plugins/filter/to_nice_yaml.yml +0 -4
  390. ansible/plugins/filter/to_yaml.yml +0 -4
  391. ansible/plugins/filter/unvault.yml +1 -1
  392. ansible/plugins/filter/urls.py +1 -1
  393. ansible/plugins/filter/urlsplit.py +8 -9
  394. ansible/plugins/filter/vault.yml +14 -9
  395. ansible/plugins/filter/win_basename.yml +6 -1
  396. ansible/plugins/filter/win_dirname.yml +5 -0
  397. ansible/plugins/inventory/__init__.py +97 -77
  398. ansible/plugins/inventory/advanced_host_list.py +7 -5
  399. ansible/plugins/inventory/auto.py +11 -4
  400. ansible/plugins/inventory/constructed.py +21 -24
  401. ansible/plugins/inventory/generator.py +16 -11
  402. ansible/plugins/inventory/host_list.py +7 -5
  403. ansible/plugins/inventory/ini.py +78 -44
  404. ansible/plugins/inventory/script.py +189 -119
  405. ansible/plugins/inventory/toml.py +16 -126
  406. ansible/plugins/inventory/yaml.py +10 -8
  407. ansible/plugins/list.py +3 -3
  408. ansible/plugins/loader.py +197 -82
  409. ansible/plugins/lookup/__init__.py +21 -4
  410. ansible/plugins/lookup/config.py +21 -35
  411. ansible/plugins/lookup/csvfile.py +3 -2
  412. ansible/plugins/lookup/dict.py +1 -6
  413. ansible/plugins/lookup/env.py +12 -9
  414. ansible/plugins/lookup/file.py +5 -8
  415. ansible/plugins/lookup/first_found.py +86 -55
  416. ansible/plugins/lookup/indexed_items.py +1 -10
  417. ansible/plugins/lookup/ini.py +14 -13
  418. ansible/plugins/lookup/items.py +1 -1
  419. ansible/plugins/lookup/lines.py +8 -1
  420. ansible/plugins/lookup/list.py +1 -1
  421. ansible/plugins/lookup/nested.py +2 -18
  422. ansible/plugins/lookup/password.py +5 -5
  423. ansible/plugins/lookup/pipe.py +5 -7
  424. ansible/plugins/lookup/sequence.py +18 -8
  425. ansible/plugins/lookup/subelements.py +1 -4
  426. ansible/plugins/lookup/template.py +42 -36
  427. ansible/plugins/lookup/together.py +0 -12
  428. ansible/plugins/lookup/unvault.py +1 -5
  429. ansible/plugins/lookup/url.py +2 -8
  430. ansible/plugins/lookup/vars.py +16 -24
  431. ansible/plugins/shell/__init__.py +2 -2
  432. ansible/plugins/shell/cmd.py +2 -2
  433. ansible/plugins/shell/powershell.py +39 -22
  434. ansible/plugins/shell/sh.py +3 -2
  435. ansible/plugins/strategy/__init__.py +94 -113
  436. ansible/plugins/strategy/debug.py +2 -2
  437. ansible/plugins/strategy/free.py +13 -28
  438. ansible/plugins/strategy/host_pinned.py +2 -2
  439. ansible/plugins/strategy/linear.py +31 -33
  440. ansible/plugins/terminal/__init__.py +4 -4
  441. ansible/plugins/test/__init__.py +7 -2
  442. ansible/plugins/test/core.py +54 -20
  443. ansible/plugins/test/files.py +1 -1
  444. ansible/plugins/test/mathstuff.py +3 -3
  445. ansible/plugins/test/uri.py +3 -3
  446. ansible/plugins/vars/host_group_vars.py +7 -14
  447. ansible/release.py +2 -2
  448. ansible/template/__init__.py +368 -944
  449. ansible/utils/__init__.py +0 -18
  450. ansible/utils/_ssh_agent.py +657 -0
  451. ansible/utils/collection_loader/__init__.py +52 -5
  452. ansible/utils/collection_loader/_collection_config.py +5 -6
  453. ansible/utils/collection_loader/_collection_finder.py +79 -93
  454. ansible/utils/collection_loader/_collection_meta.py +13 -8
  455. ansible/utils/display.py +428 -58
  456. ansible/utils/encrypt.py +27 -19
  457. ansible/utils/fqcn.py +2 -2
  458. ansible/utils/hashing.py +2 -2
  459. ansible/utils/helpers.py +2 -2
  460. ansible/utils/listify.py +8 -8
  461. ansible/utils/lock.py +2 -2
  462. ansible/utils/path.py +4 -4
  463. ansible/utils/plugin_docs.py +14 -13
  464. ansible/utils/sentinel.py +4 -62
  465. ansible/utils/singleton.py +2 -0
  466. ansible/utils/ssh_functions.py +1 -1
  467. ansible/utils/unsafe_proxy.py +23 -332
  468. ansible/utils/vars.py +28 -8
  469. ansible/utils/version.py +2 -2
  470. ansible/vars/clean.py +4 -4
  471. ansible/vars/hostvars.py +60 -90
  472. ansible/vars/manager.py +205 -264
  473. ansible/vars/reserved.py +8 -9
  474. ansible_core-2.19.0b1.dist-info/BSD-3-Clause.txt +28 -0
  475. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/METADATA +5 -4
  476. ansible_core-2.19.0b1.dist-info/RECORD +1070 -0
  477. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/WHEEL +1 -1
  478. ansible_test/_data/completion/docker.txt +7 -7
  479. ansible_test/_data/completion/remote.txt +6 -6
  480. ansible_test/_data/completion/windows.txt +1 -0
  481. ansible_test/_data/requirements/ansible.txt +2 -2
  482. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  483. ansible_test/_data/requirements/sanity.changelog.txt +1 -1
  484. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  485. ansible_test/_data/requirements/sanity.pylint.txt +4 -4
  486. ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
  487. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  488. ansible_test/_data/requirements/units.txt +1 -0
  489. ansible_test/_internal/__init__.py +1 -0
  490. ansible_test/_internal/ansible_util.py +2 -0
  491. ansible_test/_internal/become.py +1 -0
  492. ansible_test/_internal/bootstrap.py +1 -0
  493. ansible_test/_internal/cache.py +1 -0
  494. ansible_test/_internal/cgroup.py +1 -0
  495. ansible_test/_internal/ci/__init__.py +1 -0
  496. ansible_test/_internal/ci/azp.py +1 -0
  497. ansible_test/_internal/ci/local.py +1 -0
  498. ansible_test/_internal/classification/__init__.py +1 -0
  499. ansible_test/_internal/classification/common.py +1 -0
  500. ansible_test/_internal/classification/csharp.py +1 -0
  501. ansible_test/_internal/classification/powershell.py +1 -0
  502. ansible_test/_internal/classification/python.py +1 -0
  503. ansible_test/_internal/cli/__init__.py +1 -0
  504. ansible_test/_internal/cli/actions.py +1 -0
  505. ansible_test/_internal/cli/argparsing/__init__.py +1 -0
  506. ansible_test/_internal/cli/argparsing/actions.py +1 -0
  507. ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
  508. ansible_test/_internal/cli/argparsing/parsers.py +1 -0
  509. ansible_test/_internal/cli/commands/__init__.py +11 -0
  510. ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
  511. ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
  512. ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
  513. ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
  514. ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
  515. ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
  516. ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
  517. ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
  518. ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
  519. ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
  520. ansible_test/_internal/cli/commands/coverage/html.py +1 -0
  521. ansible_test/_internal/cli/commands/coverage/report.py +1 -0
  522. ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
  523. ansible_test/_internal/cli/commands/env.py +1 -0
  524. ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
  525. ansible_test/_internal/cli/commands/integration/network.py +1 -0
  526. ansible_test/_internal/cli/commands/integration/posix.py +1 -0
  527. ansible_test/_internal/cli/commands/integration/windows.py +1 -0
  528. ansible_test/_internal/cli/commands/sanity.py +9 -0
  529. ansible_test/_internal/cli/commands/shell.py +1 -0
  530. ansible_test/_internal/cli/commands/units.py +1 -0
  531. ansible_test/_internal/cli/compat.py +1 -0
  532. ansible_test/_internal/cli/completers.py +1 -0
  533. ansible_test/_internal/cli/converters.py +1 -0
  534. ansible_test/_internal/cli/environments.py +1 -0
  535. ansible_test/_internal/cli/epilog.py +1 -0
  536. ansible_test/_internal/cli/parsers/__init__.py +1 -0
  537. ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
  538. ansible_test/_internal/cli/parsers/helpers.py +1 -0
  539. ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
  540. ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
  541. ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
  542. ansible_test/_internal/commands/__init__.py +1 -0
  543. ansible_test/_internal/commands/coverage/__init__.py +2 -1
  544. ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
  545. ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
  546. ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
  547. ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
  548. ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
  549. ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
  550. ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
  551. ansible_test/_internal/commands/coverage/combine.py +2 -1
  552. ansible_test/_internal/commands/coverage/erase.py +1 -0
  553. ansible_test/_internal/commands/coverage/html.py +1 -0
  554. ansible_test/_internal/commands/coverage/report.py +1 -0
  555. ansible_test/_internal/commands/coverage/xml.py +1 -0
  556. ansible_test/_internal/commands/env/__init__.py +2 -0
  557. ansible_test/_internal/commands/integration/__init__.py +4 -0
  558. ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
  559. ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
  560. ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
  561. ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
  562. ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
  563. ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
  564. ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
  565. ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
  566. ansible_test/_internal/commands/integration/cloud/httptester.py +2 -1
  567. ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
  568. ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
  569. ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
  570. ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
  571. ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
  572. ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
  573. ansible_test/_internal/commands/integration/coverage.py +1 -0
  574. ansible_test/_internal/commands/integration/filters.py +1 -0
  575. ansible_test/_internal/commands/integration/network.py +1 -0
  576. ansible_test/_internal/commands/integration/posix.py +1 -0
  577. ansible_test/_internal/commands/integration/windows.py +1 -0
  578. ansible_test/_internal/commands/sanity/__init__.py +16 -1
  579. ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
  580. ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
  581. ansible_test/_internal/commands/sanity/compile.py +1 -0
  582. ansible_test/_internal/commands/sanity/ignores.py +1 -0
  583. ansible_test/_internal/commands/sanity/import.py +1 -0
  584. ansible_test/_internal/commands/sanity/integration_aliases.py +1 -0
  585. ansible_test/_internal/commands/sanity/pep8.py +1 -0
  586. ansible_test/_internal/commands/sanity/pslint.py +1 -0
  587. ansible_test/_internal/commands/sanity/pylint.py +24 -26
  588. ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
  589. ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
  590. ansible_test/_internal/commands/sanity/yamllint.py +1 -0
  591. ansible_test/_internal/commands/shell/__init__.py +1 -0
  592. ansible_test/_internal/commands/units/__init__.py +1 -0
  593. ansible_test/_internal/compat/__init__.py +1 -0
  594. ansible_test/_internal/compat/packaging.py +1 -0
  595. ansible_test/_internal/compat/yaml.py +1 -0
  596. ansible_test/_internal/completion.py +1 -0
  597. ansible_test/_internal/config.py +2 -0
  598. ansible_test/_internal/connections.py +1 -0
  599. ansible_test/_internal/constants.py +1 -0
  600. ansible_test/_internal/containers.py +1 -0
  601. ansible_test/_internal/content_config.py +1 -0
  602. ansible_test/_internal/core_ci.py +1 -0
  603. ansible_test/_internal/coverage_util.py +11 -10
  604. ansible_test/_internal/data.py +1 -0
  605. ansible_test/_internal/delegation.py +1 -0
  606. ansible_test/_internal/dev/__init__.py +1 -0
  607. ansible_test/_internal/dev/container_probe.py +1 -0
  608. ansible_test/_internal/diff.py +3 -2
  609. ansible_test/_internal/docker_util.py +2 -1
  610. ansible_test/_internal/encoding.py +1 -0
  611. ansible_test/_internal/executor.py +1 -0
  612. ansible_test/_internal/git.py +1 -0
  613. ansible_test/_internal/host_configs.py +1 -0
  614. ansible_test/_internal/host_profiles.py +1 -0
  615. ansible_test/_internal/http.py +1 -0
  616. ansible_test/_internal/init.py +1 -0
  617. ansible_test/_internal/inventory.py +35 -3
  618. ansible_test/_internal/io.py +1 -0
  619. ansible_test/_internal/metadata.py +1 -0
  620. ansible_test/_internal/payload.py +1 -0
  621. ansible_test/_internal/provider/__init__.py +1 -0
  622. ansible_test/_internal/provider/layout/__init__.py +1 -0
  623. ansible_test/_internal/provider/layout/ansible.py +1 -0
  624. ansible_test/_internal/provider/layout/collection.py +1 -0
  625. ansible_test/_internal/provider/layout/unsupported.py +1 -0
  626. ansible_test/_internal/provider/source/__init__.py +1 -0
  627. ansible_test/_internal/provider/source/git.py +1 -0
  628. ansible_test/_internal/provider/source/installed.py +1 -0
  629. ansible_test/_internal/provider/source/unsupported.py +1 -0
  630. ansible_test/_internal/provider/source/unversioned.py +1 -0
  631. ansible_test/_internal/provisioning.py +1 -0
  632. ansible_test/_internal/pypi_proxy.py +6 -5
  633. ansible_test/_internal/python_requirements.py +1 -0
  634. ansible_test/_internal/ssh.py +1 -0
  635. ansible_test/_internal/target.py +1 -0
  636. ansible_test/_internal/test.py +3 -2
  637. ansible_test/_internal/thread.py +1 -0
  638. ansible_test/_internal/timeout.py +1 -0
  639. ansible_test/_internal/util.py +1 -0
  640. ansible_test/_internal/util_common.py +5 -2
  641. ansible_test/_internal/venv.py +1 -0
  642. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
  643. ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
  644. ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
  645. ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
  646. ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
  647. ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
  648. ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
  649. ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
  650. ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
  651. ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
  652. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
  653. ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
  654. ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
  655. ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
  656. ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
  657. ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
  658. ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
  659. ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +7 -5
  660. ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +7 -5
  661. ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +7 -5
  662. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +3 -5
  663. ansible_test/_util/controller/sanity/pylint/config/default.cfg +7 -7
  664. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -13
  665. ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
  666. ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
  667. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
  668. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
  669. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
  670. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
  671. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
  672. ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
  673. ansible_test/_util/controller/tools/collection_detail.py +1 -0
  674. ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
  675. ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
  676. ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
  677. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
  678. ansible_test/_util/target/sanity/compile/compile.py +1 -0
  679. ansible_test/_util/target/sanity/import/importer.py +15 -16
  680. ansible_test/_util/target/setup/bootstrap.sh +9 -20
  681. ansible_test/_util/target/setup/probe_cgroups.py +1 -0
  682. ansible_test/_util/target/setup/quiet_pip.py +1 -0
  683. ansible_test/_util/target/setup/requirements.py +35 -27
  684. ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
  685. ansible_test/_util/target/tools/yamlcheck.py +2 -1
  686. ansible/compat/selectors.py +0 -32
  687. ansible/errors/yaml_strings.py +0 -138
  688. ansible/executor/action_write_locks.py +0 -44
  689. ansible/executor/discovery/python_target.py +0 -47
  690. ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
  691. ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
  692. ansible/module_utils/compat/importlib.py +0 -26
  693. ansible/module_utils/compat/selectors.py +0 -32
  694. ansible/module_utils/pycompat24.py +0 -73
  695. ansible/parsing/utils/jsonify.py +0 -36
  696. ansible/parsing/yaml/constructor.py +0 -178
  697. ansible/template/native_helpers.py +0 -251
  698. ansible/template/template.py +0 -43
  699. ansible/template/vars.py +0 -77
  700. ansible/utils/native_jinja.py +0 -11
  701. ansible/vars/fact_cache.py +0 -71
  702. ansible_core-2.18.5rc1.dist-info/RECORD +0 -992
  703. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/Apache-License.txt +0 -0
  704. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/COPYING +0 -0
  705. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/MIT-license.txt +0 -0
  706. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/PSF-license.txt +0 -0
  707. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/entry_points.txt +0 -0
  708. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/simplified_bsd.txt +0 -0
  709. {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b1.dist-info}/top_level.txt +0 -0
@@ -4,6 +4,7 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  import base64
7
+ import functools
7
8
  import glob
8
9
  import hashlib
9
10
  import json
@@ -11,31 +12,34 @@ import ntpath
11
12
  import os.path
12
13
  import re
13
14
  import shlex
14
- import sys
15
15
  import time
16
16
  import uuid
17
17
  import yaml
18
18
  import datetime
19
+ import typing as t
19
20
 
20
21
  from collections.abc import Mapping
21
22
  from functools import partial
22
23
  from random import Random, SystemRandom, shuffle
23
24
 
24
- from jinja2.filters import pass_environment
25
+ from jinja2.filters import do_map, do_select, do_selectattr, do_reject, do_rejectattr, pass_environment, sync_do_groupby
26
+ from jinja2.environment import Environment
25
27
 
26
- from ansible.errors import AnsibleError, AnsibleFilterError, AnsibleFilterTypeError
27
- from ansible.module_utils.six import string_types, integer_types, reraise, text_type
28
+ from ansible._internal._templating import _lazy_containers
29
+ from ansible.errors import AnsibleFilterError, AnsibleTypeError
30
+ from ansible.module_utils.datatag import native_type_name
31
+ from ansible.module_utils.common.json import get_encoder, get_decoder
32
+ from ansible.module_utils.six import string_types, integer_types, text_type
28
33
  from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
29
34
  from ansible.module_utils.common.collections import is_sequence
30
35
  from ansible.module_utils.common.yaml import yaml_load, yaml_load_all
31
- from ansible.parsing.ajson import AnsibleJSONEncoder
32
36
  from ansible.parsing.yaml.dumper import AnsibleDumper
33
- from ansible.template import recursive_check_defined
37
+ from ansible.plugins import accept_args_markers, accept_lazy_markers
38
+ from ansible._internal._templating._jinja_common import MarkerError, UndefinedMarker, validate_arg_type
34
39
  from ansible.utils.display import Display
35
40
  from ansible.utils.encrypt import do_encrypt, PASSLIB_AVAILABLE
36
41
  from ansible.utils.hashing import md5s, checksum_s
37
42
  from ansible.utils.unicode import unicode_wrap
38
- from ansible.utils.unsafe_proxy import _is_unsafe
39
43
  from ansible.utils.vars import merge_hash
40
44
 
41
45
  display = Display()
@@ -43,53 +47,77 @@ display = Display()
43
47
  UUID_NAMESPACE_ANSIBLE = uuid.UUID('361E6D51-FAEC-444A-9079-341386DA8E2E')
44
48
 
45
49
 
46
- def to_yaml(a, *args, **kw):
47
- '''Make verbose, human-readable yaml'''
48
- default_flow_style = kw.pop('default_flow_style', None)
49
- try:
50
- transformed = yaml.dump(a, Dumper=AnsibleDumper, allow_unicode=True, default_flow_style=default_flow_style, **kw)
51
- except Exception as e:
52
- raise AnsibleFilterError("to_yaml - %s" % to_native(e), orig_exc=e)
53
- return to_text(transformed)
50
+ def to_yaml(a, *_args, default_flow_style: bool | None = None, dump_vault_tags: bool | None = None, **kwargs) -> str:
51
+ """Serialize input as terse flow-style YAML."""
52
+ dumper = partial(AnsibleDumper, dump_vault_tags=dump_vault_tags)
54
53
 
54
+ return yaml.dump(a, Dumper=dumper, allow_unicode=True, default_flow_style=default_flow_style, **kwargs)
55
55
 
56
- def to_nice_yaml(a, indent=4, *args, **kw):
57
- '''Make verbose, human-readable yaml'''
58
- try:
59
- transformed = yaml.dump(a, Dumper=AnsibleDumper, indent=indent, allow_unicode=True, default_flow_style=False, **kw)
60
- except Exception as e:
61
- raise AnsibleFilterError("to_nice_yaml - %s" % to_native(e), orig_exc=e)
62
- return to_text(transformed)
56
+
57
+ def to_nice_yaml(a, indent=4, *_args, default_flow_style=False, **kwargs) -> str:
58
+ """Serialize input as verbose multi-line YAML."""
59
+ return to_yaml(a, indent=indent, default_flow_style=default_flow_style, **kwargs)
60
+
61
+
62
+ def from_json(a, profile: str | None = None, **kwargs) -> t.Any:
63
+ """Deserialize JSON with an optional decoder profile."""
64
+ cls = get_decoder(profile or "tagless")
65
+
66
+ return json.loads(a, cls=cls, **kwargs)
63
67
 
64
68
 
65
- def to_json(a, *args, **kw):
66
- ''' Convert the value to JSON '''
69
+ def to_json(a, profile: str | None = None, vault_to_text: t.Any = ..., preprocess_unsafe: t.Any = ..., **kwargs) -> str:
70
+ """Serialize as JSON with an optional encoder profile."""
67
71
 
68
- # defaults for filters
69
- if 'vault_to_text' not in kw:
70
- kw['vault_to_text'] = True
71
- if 'preprocess_unsafe' not in kw:
72
- kw['preprocess_unsafe'] = False
72
+ if profile and vault_to_text is not ...:
73
+ raise ValueError("Only one of `vault_to_text` or `profile` can be specified.")
73
74
 
74
- return json.dumps(a, cls=AnsibleJSONEncoder, *args, **kw)
75
+ if profile and preprocess_unsafe is not ...:
76
+ raise ValueError("Only one of `preprocess_unsafe` or `profile` can be specified.")
75
77
 
78
+ # deprecated: description='deprecate vault_to_text' core_version='2.23'
79
+ # deprecated: description='deprecate preprocess_unsafe' core_version='2.23'
76
80
 
77
- def to_nice_json(a, indent=4, sort_keys=True, *args, **kw):
78
- '''Make verbose, human-readable JSON'''
81
+ cls = get_encoder(profile or "tagless")
82
+
83
+ return json.dumps(a, cls=cls, **kwargs)
84
+
85
+
86
+ def to_nice_json(a, indent=4, sort_keys=True, **kwargs):
87
+ """Make verbose, human-readable JSON."""
79
88
  # TODO separators can be potentially exposed to the user as well
80
- kw.pop('separators', None)
81
- return to_json(a, indent=indent, sort_keys=sort_keys, separators=(',', ': '), *args, **kw)
89
+ kwargs.pop('separators', None)
90
+ return to_json(a, indent=indent, sort_keys=sort_keys, separators=(',', ': '), **kwargs)
91
+
82
92
 
93
+ # CAUTION: Do not put non-string values here since they can have unwanted logical equality, such as 1.0 (equal to 1 and True) or 0.0 (equal to 0 and False).
94
+ _valid_bool_true = {'yes', 'on', 'true', '1'}
95
+ _valid_bool_false = {'no', 'off', 'false', '0'}
83
96
 
84
- def to_bool(a):
85
- ''' return a bool for the arg '''
86
- if a is None or isinstance(a, bool):
87
- return a
88
- if isinstance(a, string_types):
89
- a = a.lower()
90
- if a in ('yes', 'on', '1', 'true', 1):
97
+
98
+ def to_bool(value: object) -> bool:
99
+ """Convert well-known input values to a boolean value."""
100
+ value_to_check: object
101
+ if isinstance(value, str):
102
+ value_to_check = value.lower() # accept mixed case variants
103
+ elif isinstance(value, int): # bool is also an int
104
+ value_to_check = str(value).lower() # accept int (0, 1) and bool (True, False) -- not just string versions
105
+ else:
106
+ value_to_check = value
107
+
108
+ if value_to_check in _valid_bool_true:
91
109
  return True
92
- return False
110
+
111
+ if value_to_check in _valid_bool_false:
112
+ return False
113
+
114
+ # if we're still here, the value is unsupported- always fire a deprecation warning
115
+ result = value_to_check == 1 # backwards compatibility with the old code which checked: value in ('yes', 'on', '1', 'true', 1)
116
+
117
+ # NB: update the doc string to reflect reality once this fallback is removed
118
+ display.deprecated(f'The `bool` filter coerced invalid value {value!r} ({native_type_name(value)}) to {result!r}.', version='2.23')
119
+
120
+ return result
93
121
 
94
122
 
95
123
  def to_datetime(string, format="%Y-%m-%d %H:%M:%S"):
@@ -97,7 +125,7 @@ def to_datetime(string, format="%Y-%m-%d %H:%M:%S"):
97
125
 
98
126
 
99
127
  def strftime(string_format, second=None, utc=False):
100
- ''' return a date string using string. See https://docs.python.org/3/library/time.html#time.strftime for format '''
128
+ """ return a date string using string. See https://docs.python.org/3/library/time.html#time.strftime for format """
101
129
  if utc:
102
130
  timefn = time.gmtime
103
131
  else:
@@ -111,19 +139,19 @@ def strftime(string_format, second=None, utc=False):
111
139
 
112
140
 
113
141
  def quote(a):
114
- ''' return its argument quoted for shell usage '''
142
+ """ return its argument quoted for shell usage """
115
143
  if a is None:
116
144
  a = u''
117
145
  return shlex.quote(to_text(a))
118
146
 
119
147
 
120
148
  def fileglob(pathname):
121
- ''' return list of matched regular files for glob '''
149
+ """ return list of matched regular files for glob """
122
150
  return [g for g in glob.glob(pathname) if os.path.isfile(g)]
123
151
 
124
152
 
125
153
  def regex_replace(value='', pattern='', replacement='', ignorecase=False, multiline=False, count=0, mandatory_count=0):
126
- ''' Perform a `re.sub` returning a string '''
154
+ """ Perform a `re.sub` returning a string """
127
155
 
128
156
  value = to_text(value, errors='surrogate_or_strict', nonstring='simplerepr')
129
157
 
@@ -141,7 +169,7 @@ def regex_replace(value='', pattern='', replacement='', ignorecase=False, multil
141
169
 
142
170
 
143
171
  def regex_findall(value, regex, multiline=False, ignorecase=False):
144
- ''' Perform re.findall and return the list of matches '''
172
+ """ Perform re.findall and return the list of matches """
145
173
 
146
174
  value = to_text(value, errors='surrogate_or_strict', nonstring='simplerepr')
147
175
 
@@ -154,7 +182,7 @@ def regex_findall(value, regex, multiline=False, ignorecase=False):
154
182
 
155
183
 
156
184
  def regex_search(value, regex, *args, **kwargs):
157
- ''' Perform re.search and return the list of matches or a backref '''
185
+ """ Perform re.search and return the list of matches or a backref """
158
186
 
159
187
  value = to_text(value, errors='surrogate_or_strict', nonstring='simplerepr')
160
188
 
@@ -187,7 +215,7 @@ def regex_search(value, regex, *args, **kwargs):
187
215
 
188
216
 
189
217
  def ternary(value, true_val, false_val, none_val=None):
190
- ''' value ? true_val : false_val '''
218
+ """ value ? true_val : false_val """
191
219
  if value is None and none_val is not None:
192
220
  return none_val
193
221
  elif bool(value):
@@ -220,8 +248,6 @@ def from_yaml(data):
220
248
  # The ``text_type`` call here strips any custom
221
249
  # string wrapper class, so that CSafeLoader can
222
250
  # read the data
223
- if _is_unsafe(data):
224
- data = data._strip_unsafe()
225
251
  return yaml_load(text_type(to_text(data, errors='surrogate_or_strict')))
226
252
  return data
227
253
 
@@ -231,8 +257,6 @@ def from_yaml_all(data):
231
257
  # The ``text_type`` call here strips any custom
232
258
  # string wrapper class, so that CSafeLoader can
233
259
  # read the data
234
- if _is_unsafe(data):
235
- data = data._strip_unsafe()
236
260
  return yaml_load_all(text_type(to_text(data, errors='surrogate_or_strict')))
237
261
  return data
238
262
 
@@ -291,26 +315,10 @@ def get_encrypted_password(password, hashtype='sha512', salt=None, salt_size=Non
291
315
 
292
316
  hashtype = passlib_mapping.get(hashtype, hashtype)
293
317
 
294
- unknown_passlib_hashtype = False
295
318
  if PASSLIB_AVAILABLE and hashtype not in passlib_mapping and hashtype not in passlib_mapping.values():
296
- unknown_passlib_hashtype = True
297
- display.deprecated(
298
- f"Checking for unsupported password_hash passlib hashtype '{hashtype}'. "
299
- "This will be an error in the future as all supported hashtypes must be documented.",
300
- version='2.19'
301
- )
319
+ raise AnsibleFilterError(f"{hashtype} is not in the list of supported passlib algorithms: {', '.join(passlib_mapping)}")
302
320
 
303
- try:
304
- return do_encrypt(password, hashtype, salt=salt, salt_size=salt_size, rounds=rounds, ident=ident)
305
- except AnsibleError as e:
306
- reraise(AnsibleFilterError, AnsibleFilterError(to_native(e), orig_exc=e), sys.exc_info()[2])
307
- except Exception as e:
308
- if unknown_passlib_hashtype:
309
- # This can occur if passlib.hash has the hashtype attribute, but it has a different signature than the valid choices.
310
- # In 2.19 this will replace the deprecation warning above and the extra exception handling can be deleted.
311
- choices = ', '.join(passlib_mapping)
312
- raise AnsibleFilterError(f"{hashtype} is not in the list of supported passlib algorithms: {choices}") from e
313
- raise
321
+ return do_encrypt(password, hashtype, salt=salt, salt_size=salt_size, rounds=rounds, ident=ident)
314
322
 
315
323
 
316
324
  def to_uuid(string, namespace=UUID_NAMESPACE_ANSIBLE):
@@ -324,19 +332,21 @@ def to_uuid(string, namespace=UUID_NAMESPACE_ANSIBLE):
324
332
  return to_text(uuid.uuid5(uuid_namespace, to_native(string, errors='surrogate_or_strict')))
325
333
 
326
334
 
327
- def mandatory(a, msg=None):
335
+ @accept_args_markers
336
+ def mandatory(a: object, msg: str | None = None) -> object:
328
337
  """Make a variable mandatory."""
329
- from jinja2.runtime import Undefined
338
+ # DTFIX-RELEASE: deprecate this filter; there are much better ways via undef, etc...
339
+ # also remember to remove unit test checking for _undefined_name
340
+ if isinstance(a, UndefinedMarker):
341
+ if msg is not None:
342
+ raise AnsibleFilterError(to_text(msg))
330
343
 
331
- if isinstance(a, Undefined):
332
344
  if a._undefined_name is not None:
333
- name = "'%s' " % to_text(a._undefined_name)
345
+ name = f'{to_text(a._undefined_name)!r} '
334
346
  else:
335
347
  name = ''
336
348
 
337
- if msg is not None:
338
- raise AnsibleFilterError(to_native(msg))
339
- raise AnsibleFilterError("Mandatory variable %s not defined." % name)
349
+ raise AnsibleFilterError(f"Mandatory variable {name}not defined.")
340
350
 
341
351
  return a
342
352
 
@@ -350,9 +360,6 @@ def combine(*terms, **kwargs):
350
360
  # allow the user to do `[dict1, dict2, ...] | combine`
351
361
  dictionaries = flatten(terms, levels=1)
352
362
 
353
- # recursively check that every elements are defined (for jinja2)
354
- recursive_check_defined(dictionaries)
355
-
356
363
  if not dictionaries:
357
364
  return {}
358
365
 
@@ -458,7 +465,7 @@ def comment(text, style='plain', **kw):
458
465
 
459
466
 
460
467
  @pass_environment
461
- def extract(environment, item, container, morekeys=None):
468
+ def extract(environment: Environment, item, container, morekeys=None):
462
469
  if morekeys is None:
463
470
  keys = [item]
464
471
  elif isinstance(morekeys, list):
@@ -467,18 +474,28 @@ def extract(environment, item, container, morekeys=None):
467
474
  keys = [item, morekeys]
468
475
 
469
476
  value = container
477
+
470
478
  for key in keys:
471
- value = environment.getitem(value, key)
479
+ try:
480
+ value = environment.getitem(value, key)
481
+ except MarkerError as ex:
482
+ value = ex.source
472
483
 
473
484
  return value
474
485
 
475
486
 
476
- def b64encode(string, encoding='utf-8'):
477
- return to_text(base64.b64encode(to_bytes(string, encoding=encoding, errors='surrogate_or_strict')))
487
+ def b64encode(string, encoding='utf-8', urlsafe=False):
488
+ func = base64.b64encode
489
+ if urlsafe:
490
+ func = base64.urlsafe_b64encode
491
+ return to_text(func(to_bytes(string, encoding=encoding, errors='surrogate_or_strict')))
478
492
 
479
493
 
480
- def b64decode(string, encoding='utf-8'):
481
- return to_text(base64.b64decode(to_bytes(string, errors='surrogate_or_strict')), encoding=encoding)
494
+ def b64decode(string, encoding='utf-8', urlsafe=False):
495
+ func = base64.b64decode
496
+ if urlsafe:
497
+ func = base64.urlsafe_b64decode
498
+ return to_text(func(to_bytes(string, errors='surrogate_or_strict')), encoding=encoding)
482
499
 
483
500
 
484
501
  def flatten(mylist, levels=None, skip_nulls=True):
@@ -503,14 +520,14 @@ def flatten(mylist, levels=None, skip_nulls=True):
503
520
 
504
521
 
505
522
  def subelements(obj, subelements, skip_missing=False):
506
- '''Accepts a dict or list of dicts, and a dotted accessor and produces a product
523
+ """Accepts a dict or list of dicts, and a dotted accessor and produces a product
507
524
  of the element and the results of the dotted accessor
508
525
 
509
526
  >>> obj = [{"name": "alice", "groups": ["wheel"], "authorized": ["/tmp/alice/onekey.pub"]}]
510
527
  >>> subelements(obj, 'groups')
511
528
  [({'name': 'alice', 'groups': ['wheel'], 'authorized': ['/tmp/alice/onekey.pub']}, 'wheel')]
512
529
 
513
- '''
530
+ """
514
531
  if isinstance(obj, dict):
515
532
  element_list = list(obj.values())
516
533
  elif isinstance(obj, list):
@@ -523,7 +540,7 @@ def subelements(obj, subelements, skip_missing=False):
523
540
  elif isinstance(subelements, string_types):
524
541
  subelement_list = subelements.split('.')
525
542
  else:
526
- raise AnsibleFilterTypeError('subelements must be a list or a string')
543
+ raise AnsibleTypeError('subelements must be a list or a string')
527
544
 
528
545
  results = []
529
546
 
@@ -537,10 +554,10 @@ def subelements(obj, subelements, skip_missing=False):
537
554
  values = []
538
555
  break
539
556
  raise AnsibleFilterError("could not find %r key in iterated item %r" % (subelement, values))
540
- except TypeError:
541
- raise AnsibleFilterTypeError("the key %s should point to a dictionary, got '%s'" % (subelement, values))
557
+ except TypeError as ex:
558
+ raise AnsibleTypeError("the key %s should point to a dictionary, got '%s'" % (subelement, values)) from ex
542
559
  if not isinstance(values, list):
543
- raise AnsibleFilterTypeError("the key %r should point to a list, got %r" % (subelement, values))
560
+ raise AnsibleTypeError("the key %r should point to a list, got %r" % (subelement, values))
544
561
 
545
562
  for value in values:
546
563
  results.append((element, value))
@@ -549,11 +566,11 @@ def subelements(obj, subelements, skip_missing=False):
549
566
 
550
567
 
551
568
  def dict_to_list_of_dict_key_value_elements(mydict, key_name='key', value_name='value'):
552
- ''' takes a dictionary and transforms it into a list of dictionaries,
553
- with each having a 'key' and 'value' keys that correspond to the keys and values of the original '''
569
+ """ takes a dictionary and transforms it into a list of dictionaries,
570
+ with each having a 'key' and 'value' keys that correspond to the keys and values of the original """
554
571
 
555
572
  if not isinstance(mydict, Mapping):
556
- raise AnsibleFilterTypeError("dict2items requires a dictionary, got %s instead." % type(mydict))
573
+ raise AnsibleTypeError("dict2items requires a dictionary, got %s instead." % type(mydict))
557
574
 
558
575
  ret = []
559
576
  for key in mydict:
@@ -562,31 +579,31 @@ def dict_to_list_of_dict_key_value_elements(mydict, key_name='key', value_name='
562
579
 
563
580
 
564
581
  def list_of_dict_key_value_elements_to_dict(mylist, key_name='key', value_name='value'):
565
- ''' takes a list of dicts with each having a 'key' and 'value' keys, and transforms the list into a dictionary,
566
- effectively as the reverse of dict2items '''
582
+ """ takes a list of dicts with each having a 'key' and 'value' keys, and transforms the list into a dictionary,
583
+ effectively as the reverse of dict2items """
567
584
 
568
585
  if not is_sequence(mylist):
569
- raise AnsibleFilterTypeError("items2dict requires a list, got %s instead." % type(mylist))
586
+ raise AnsibleTypeError("items2dict requires a list, got %s instead." % type(mylist))
570
587
 
571
588
  try:
572
589
  return dict((item[key_name], item[value_name]) for item in mylist)
573
590
  except KeyError:
574
- raise AnsibleFilterTypeError(
591
+ raise AnsibleTypeError(
575
592
  "items2dict requires each dictionary in the list to contain the keys '%s' and '%s', got %s instead."
576
593
  % (key_name, value_name, mylist)
577
594
  )
578
595
  except TypeError:
579
- raise AnsibleFilterTypeError("items2dict requires a list of dictionaries, got %s instead." % mylist)
596
+ raise AnsibleTypeError("items2dict requires a list of dictionaries, got %s instead." % mylist)
580
597
 
581
598
 
582
599
  def path_join(paths):
583
- ''' takes a sequence or a string, and return a concatenation
584
- of the different members '''
600
+ """ takes a sequence or a string, and return a concatenation
601
+ of the different members """
585
602
  if isinstance(paths, string_types):
586
603
  return os.path.join(paths)
587
604
  if is_sequence(paths):
588
605
  return os.path.join(*paths)
589
- raise AnsibleFilterTypeError("|path_join expects string or sequence, got %s instead." % type(paths))
606
+ raise AnsibleTypeError("|path_join expects string or sequence, got %s instead." % type(paths))
590
607
 
591
608
 
592
609
  def commonpath(paths):
@@ -599,13 +616,92 @@ def commonpath(paths):
599
616
  :rtype: str
600
617
  """
601
618
  if not is_sequence(paths):
602
- raise AnsibleFilterTypeError("|commonpath expects sequence, got %s instead." % type(paths))
619
+ raise AnsibleTypeError("|commonpath expects sequence, got %s instead." % type(paths))
603
620
 
604
621
  return os.path.commonpath(paths)
605
622
 
606
623
 
624
+ class GroupTuple(t.NamedTuple):
625
+ """
626
+ Custom named tuple for the groupby filter with a public interface; silently ignored by unknown type checks.
627
+ This matches the internal implementation of the _GroupTuple returned by Jinja's built-in groupby filter.
628
+ """
629
+
630
+ grouper: t.Any
631
+ list: list[t.Any]
632
+
633
+ def __repr__(self) -> str:
634
+ return tuple.__repr__(self)
635
+
636
+
637
+ _lazy_containers.register_known_types(GroupTuple)
638
+
639
+
640
+ @pass_environment
641
+ def _cleansed_groupby(*args, **kwargs):
642
+ res = sync_do_groupby(*args, **kwargs)
643
+ res = [GroupTuple(grouper=g.grouper, list=g.list) for g in res]
644
+
645
+ return res
646
+
647
+ # DTFIX-RELEASE: make these dumb wrappers more dynamic
648
+
649
+
650
+ @accept_args_markers
651
+ def ansible_default(
652
+ value: t.Any,
653
+ default_value: t.Any = '',
654
+ boolean: bool = False,
655
+ ) -> t.Any:
656
+ """Updated `default` filter that only coalesces classic undefined objects; other Undefined-derived types (eg, ErrorMarker) pass through."""
657
+ validate_arg_type('boolean', boolean, bool)
658
+
659
+ if isinstance(value, UndefinedMarker):
660
+ return default_value
661
+
662
+ if boolean and not value:
663
+ return default_value
664
+
665
+ return value
666
+
667
+
668
+ @accept_lazy_markers
669
+ @functools.wraps(do_map)
670
+ def wrapped_map(*args, **kwargs) -> t.Any:
671
+ return do_map(*args, **kwargs)
672
+
673
+
674
+ @accept_lazy_markers
675
+ @functools.wraps(do_select)
676
+ def wrapped_select(*args, **kwargs) -> t.Any:
677
+ return do_select(*args, **kwargs)
678
+
679
+
680
+ @accept_lazy_markers
681
+ @functools.wraps(do_selectattr)
682
+ def wrapped_selectattr(*args, **kwargs) -> t.Any:
683
+ return do_selectattr(*args, **kwargs)
684
+
685
+
686
+ @accept_lazy_markers
687
+ @functools.wraps(do_reject)
688
+ def wrapped_reject(*args, **kwargs) -> t.Any:
689
+ return do_reject(*args, **kwargs)
690
+
691
+
692
+ @accept_lazy_markers
693
+ @functools.wraps(do_rejectattr)
694
+ def wrapped_rejectattr(*args, **kwargs) -> t.Any:
695
+ return do_rejectattr(*args, **kwargs)
696
+
697
+
698
+ @accept_args_markers
699
+ def type_debug(obj: object) -> str:
700
+ return native_type_name(obj)
701
+
702
+
607
703
  class FilterModule(object):
608
- ''' Ansible core jinja2 filters '''
704
+ """ Ansible core jinja2 filters """
609
705
 
610
706
  def filters(self):
611
707
  return {
@@ -619,7 +715,7 @@ class FilterModule(object):
619
715
  # json
620
716
  'to_json': to_json,
621
717
  'to_nice_json': to_nice_json,
622
- 'from_json': json.loads,
718
+ 'from_json': from_json,
623
719
 
624
720
  # yaml
625
721
  'to_yaml': to_yaml,
@@ -686,7 +782,7 @@ class FilterModule(object):
686
782
  'comment': comment,
687
783
 
688
784
  # debug
689
- 'type_debug': lambda o: o.__class__.__name__,
785
+ 'type_debug': type_debug,
690
786
 
691
787
  # Data structures
692
788
  'combine': combine,
@@ -696,4 +792,18 @@ class FilterModule(object):
696
792
  'items2dict': list_of_dict_key_value_elements_to_dict,
697
793
  'subelements': subelements,
698
794
  'split': partial(unicode_wrap, text_type.split),
795
+ # FDI038 - replace this with a standard type compat shim
796
+ 'groupby': _cleansed_groupby,
797
+
798
+ # Jinja builtins that need special arg handling
799
+ # DTFIX-RELEASE: document these now that they're overridden, or hide them so they don't show up as undocumented
800
+ 'd': ansible_default, # replaces the implementation instead of wrapping it
801
+ 'default': ansible_default, # replaces the implementation instead of wrapping it
802
+ 'map': wrapped_map,
803
+ 'select': wrapped_select,
804
+ 'selectattr': wrapped_selectattr,
805
+ 'reject': wrapped_reject,
806
+ 'rejectattr': wrapped_rejectattr,
699
807
  }
808
+
809
+ # DTFIX-RELEASE: document protomatter plugins, or hide them from ansible-doc/galaxy (not related to this code, but needed some place to put this comment)