ansible-core 2.18.5rc1__py3-none-any.whl → 2.19.0b2__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.
- ansible/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz.py +265 -0
- ansible/_internal/_collection_proxy.py +47 -0
- ansible/_internal/_datatag/__init__.py +0 -0
- ansible/_internal/_datatag/_tags.py +130 -0
- ansible/_internal/_datatag/_utils.py +19 -0
- ansible/_internal/_datatag/_wrappers.py +33 -0
- ansible/_internal/_errors/__init__.py +0 -0
- ansible/_internal/_errors/_captured.py +128 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_utils.py +310 -0
- ansible/_internal/_json/__init__.py +203 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +55 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +197 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +10 -0
- ansible/_internal/_templating/_access.py +86 -0
- ansible/_internal/_templating/_chain_templar.py +63 -0
- ansible/_internal/_templating/_datatag.py +95 -0
- ansible/_internal/_templating/_engine.py +588 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1066 -0
- ansible/_internal/_templating/_jinja_common.py +332 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +345 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_transform.py +63 -0
- ansible/_internal/_templating/_utils.py +107 -0
- ansible/_internal/_wrapt.py +1052 -0
- ansible/_internal/_yaml/__init__.py +0 -0
- ansible/_internal/_yaml/_constructor.py +240 -0
- ansible/_internal/_yaml/_dumper.py +62 -0
- ansible/_internal/_yaml/_errors.py +166 -0
- ansible/_internal/_yaml/_loader.py +66 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/README.md +11 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/action/debug.py +36 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/apply_trust.py +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/finalize.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/origin.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.py +24 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/python_literal_eval.yml +33 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/tag_names.py +16 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +17 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +49 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.py +21 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/lookup/config.yml +2 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.py +15 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged.yml +19 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.py +18 -0
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/test/tagged_with.yml +19 -0
- ansible/cli/__init__.py +159 -89
- ansible/cli/_ssh_askpass.py +47 -0
- ansible/cli/adhoc.py +14 -7
- ansible/cli/arguments/option_helpers.py +154 -7
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +10 -8
- ansible/cli/doc.py +62 -53
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -26
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +51 -11
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/config/base.yml +166 -112
- ansible/config/manager.py +52 -49
- ansible/constants.py +3 -4
- ansible/errors/__init__.py +277 -235
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +426 -493
- ansible/executor/play_iterator.py +22 -27
- ansible/executor/playbook_executor.py +11 -11
- ansible/executor/powershell/async_watchdog.ps1 +97 -102
- ansible/executor/powershell/async_wrapper.ps1 +202 -151
- ansible/executor/powershell/become_wrapper.ps1 +89 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +24 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +82 -135
- ansible/executor/powershell/exec_wrapper.ps1 +462 -196
- ansible/executor/powershell/module_manifest.py +417 -265
- ansible/executor/powershell/module_wrapper.ps1 +169 -186
- ansible/executor/powershell/psrp_fetch_file.ps1 +41 -0
- ansible/executor/powershell/psrp_put_file.ps1 +122 -0
- ansible/executor/powershell/winrm_fetch_file.ps1 +46 -0
- ansible/executor/powershell/winrm_put_file.ps1 +36 -0
- ansible/executor/process/worker.py +161 -96
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +268 -258
- ansible/executor/task_queue_manager.py +124 -90
- ansible/executor/task_result.py +183 -78
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +22 -18
- ansible/galaxy/collection/__init__.py +1 -1
- ansible/galaxy/collection/concrete_artifact_manager.py +8 -11
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +1 -1
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +4 -8
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +44 -72
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +32 -54
- ansible/inventory/manager.py +78 -34
- ansible/keyword_desc.yml +1 -1
- ansible/module_utils/_internal/__init__.py +55 -0
- ansible/module_utils/_internal/_ambient_context.py +58 -0
- ansible/module_utils/_internal/_ansiballz.py +133 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_annotation_patch.py +64 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +928 -0
- ansible/module_utils/_internal/_datatag/_tags.py +38 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_errors.py +30 -0
- ansible/module_utils/_internal/_json/__init__.py +63 -0
- ansible/module_utils/_internal/_json/_legacy_encoder.py +26 -0
- ansible/module_utils/_internal/_json/_profiles/__init__.py +410 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +31 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_c2m.py +35 -0
- ansible/module_utils/_internal/_json/_profiles/_module_modern_m2c.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_tagless.py +50 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +55 -0
- ansible/module_utils/_internal/_patches/_socket_patch.py +34 -0
- ansible/module_utils/_internal/_patches/_sys_intern_patch.py +34 -0
- ansible/module_utils/_internal/_plugin_exec_context.py +49 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_traceback.py +89 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +152 -120
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/collections.py +1 -2
- ansible/module_utils/common/dict_transformations.py +2 -2
- ansible/module_utils/common/file.py +2 -2
- ansible/module_utils/common/json.py +90 -84
- ansible/module_utils/common/locale.py +2 -2
- ansible/module_utils/common/messages.py +108 -0
- ansible/module_utils/common/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -2
- ansible/module_utils/common/respawn.py +41 -19
- ansible/module_utils/common/sentinel.py +66 -0
- ansible/module_utils/common/sys_info.py +8 -8
- ansible/module_utils/common/text/converters.py +16 -37
- ansible/module_utils/common/validation.py +35 -24
- ansible/module_utils/common/warnings.py +86 -25
- ansible/module_utils/common/yaml.py +29 -3
- ansible/module_utils/compat/datetime.py +33 -21
- ansible/module_utils/compat/paramiko.py +21 -10
- ansible/module_utils/compat/typing.py +6 -5
- ansible/module_utils/connection.py +2 -2
- ansible/module_utils/csharp/Ansible.Basic.cs +14 -11
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +46 -0
- ansible/module_utils/distro/__init__.py +2 -2
- ansible/module_utils/facts/ansible_collector.py +4 -5
- ansible/module_utils/facts/collector.py +13 -14
- ansible/module_utils/facts/compat.py +4 -4
- ansible/module_utils/facts/default_collectors.py +1 -1
- ansible/module_utils/facts/hardware/aix.py +34 -0
- ansible/module_utils/facts/hardware/base.py +1 -1
- ansible/module_utils/facts/hardware/darwin.py +1 -3
- ansible/module_utils/facts/hardware/freebsd.py +2 -2
- ansible/module_utils/facts/hardware/linux.py +4 -4
- ansible/module_utils/facts/namespace.py +1 -1
- ansible/module_utils/facts/network/base.py +1 -1
- ansible/module_utils/facts/network/fc_wwn.py +1 -2
- ansible/module_utils/facts/network/iscsi.py +1 -2
- ansible/module_utils/facts/network/nvme.py +1 -2
- ansible/module_utils/facts/other/facter.py +1 -2
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +1 -1
- ansible/module_utils/facts/system/chroot.py +1 -2
- ansible/module_utils/facts/system/cmdline.py +1 -2
- ansible/module_utils/facts/system/date_time.py +5 -3
- ansible/module_utils/facts/system/distribution.py +9 -8
- ansible/module_utils/facts/system/dns.py +1 -1
- ansible/module_utils/facts/system/env.py +1 -2
- ansible/module_utils/facts/system/fips.py +7 -20
- ansible/module_utils/facts/system/loadavg.py +1 -2
- ansible/module_utils/facts/system/local.py +1 -2
- ansible/module_utils/facts/system/lsb.py +1 -2
- ansible/module_utils/facts/system/pkg_mgr.py +1 -2
- ansible/module_utils/facts/system/platform.py +1 -2
- ansible/module_utils/facts/system/python.py +1 -2
- ansible/module_utils/facts/system/selinux.py +1 -1
- ansible/module_utils/facts/system/service_mgr.py +1 -2
- ansible/module_utils/facts/system/ssh_pub_keys.py +1 -1
- ansible/module_utils/facts/system/systemd.py +1 -1
- ansible/module_utils/facts/system/user.py +1 -2
- ansible/module_utils/facts/utils.py +3 -3
- ansible/module_utils/facts/virtual/base.py +1 -1
- ansible/module_utils/facts/virtual/sunos.py +3 -15
- ansible/module_utils/facts/virtual/sysctl.py +3 -16
- ansible/module_utils/json_utils.py +2 -2
- ansible/module_utils/parsing/convert_bool.py +1 -1
- ansible/module_utils/service.py +18 -21
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +60 -31
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +60 -46
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +19 -16
- ansible/modules/assemble.py +6 -6
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +10 -12
- ansible/modules/async_wrapper.py +8 -3
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +10 -17
- ansible/modules/copy.py +57 -144
- ansible/modules/cron.py +20 -15
- ansible/modules/deb822_repository.py +8 -9
- ansible/modules/debconf.py +5 -5
- ansible/modules/debug.py +4 -4
- ansible/modules/dnf.py +8 -8
- ansible/modules/dnf5.py +39 -13
- ansible/modules/dpkg_selections.py +4 -4
- ansible/modules/expect.py +8 -10
- ansible/modules/fail.py +4 -4
- ansible/modules/fetch.py +4 -4
- ansible/modules/file.py +174 -133
- ansible/modules/find.py +19 -17
- ansible/modules/gather_facts.py +3 -3
- ansible/modules/get_url.py +59 -53
- ansible/modules/getent.py +7 -9
- ansible/modules/git.py +28 -25
- ansible/modules/group.py +6 -6
- ansible/modules/group_by.py +4 -4
- ansible/modules/hostname.py +13 -29
- ansible/modules/import_playbook.py +6 -6
- ansible/modules/import_role.py +6 -6
- ansible/modules/import_tasks.py +6 -6
- ansible/modules/include_role.py +6 -6
- ansible/modules/include_tasks.py +6 -6
- ansible/modules/include_vars.py +6 -6
- ansible/modules/iptables.py +86 -73
- ansible/modules/known_hosts.py +10 -10
- ansible/modules/lineinfile.py +5 -5
- ansible/modules/meta.py +4 -4
- ansible/modules/mount_facts.py +2 -2
- ansible/modules/package.py +4 -4
- ansible/modules/package_facts.py +22 -10
- ansible/modules/pause.py +6 -6
- ansible/modules/ping.py +6 -6
- ansible/modules/pip.py +10 -11
- ansible/modules/raw.py +4 -4
- ansible/modules/reboot.py +6 -6
- ansible/modules/replace.py +9 -13
- ansible/modules/rpm_key.py +7 -8
- ansible/modules/script.py +4 -4
- ansible/modules/service.py +7 -8
- ansible/modules/service_facts.py +87 -10
- ansible/modules/set_fact.py +5 -5
- ansible/modules/set_stats.py +4 -4
- ansible/modules/setup.py +2 -2
- ansible/modules/shell.py +6 -6
- ansible/modules/slurp.py +6 -6
- ansible/modules/stat.py +9 -23
- ansible/modules/subversion.py +15 -15
- ansible/modules/systemd.py +6 -6
- ansible/modules/systemd_service.py +6 -6
- ansible/modules/sysvinit.py +6 -6
- ansible/modules/tempfile.py +5 -6
- ansible/modules/template.py +6 -6
- ansible/modules/unarchive.py +32 -11
- ansible/modules/uri.py +33 -26
- ansible/modules/user.py +53 -34
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +32 -27
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +6 -6
- ansible/parsing/ajson.py +14 -32
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +28 -44
- ansible/parsing/plugin_docs.py +21 -86
- ansible/parsing/quoting.py +1 -1
- ansible/parsing/splitter.py +27 -12
- ansible/parsing/utils/addresses.py +24 -24
- ansible/parsing/utils/jsonify.py +5 -1
- ansible/parsing/utils/yaml.py +32 -61
- ansible/parsing/vault/__init__.py +319 -87
- ansible/parsing/yaml/__init__.py +0 -18
- ansible/parsing/yaml/dumper.py +6 -120
- ansible/parsing/yaml/loader.py +6 -39
- ansible/parsing/yaml/objects.py +43 -335
- ansible/playbook/__init__.py +1 -1
- ansible/playbook/attribute.py +8 -3
- ansible/playbook/base.py +182 -132
- ansible/playbook/block.py +26 -24
- ansible/playbook/collectionsearch.py +1 -15
- ansible/playbook/conditional.py +3 -77
- ansible/playbook/handler.py +8 -2
- ansible/playbook/helpers.py +41 -53
- ansible/playbook/included_file.py +31 -27
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +12 -17
- ansible/playbook/playbook_include.py +14 -15
- ansible/playbook/role/__init__.py +24 -26
- ansible/playbook/role/definition.py +15 -17
- ansible/playbook/role/include.py +2 -4
- ansible/playbook/role/metadata.py +10 -11
- ansible/playbook/role_include.py +3 -3
- ansible/playbook/taggable.py +13 -8
- ansible/playbook/task.py +188 -118
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +68 -21
- ansible/plugins/action/__init__.py +209 -176
- ansible/plugins/action/add_host.py +1 -1
- ansible/plugins/action/assemble.py +1 -1
- ansible/plugins/action/assert.py +54 -66
- ansible/plugins/action/copy.py +7 -11
- ansible/plugins/action/debug.py +37 -31
- ansible/plugins/action/dnf.py +3 -4
- ansible/plugins/action/fail.py +1 -1
- ansible/plugins/action/fetch.py +4 -5
- ansible/plugins/action/gather_facts.py +7 -6
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +3 -6
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +15 -8
- ansible/plugins/action/service.py +6 -11
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +35 -59
- ansible/plugins/action/unarchive.py +1 -1
- ansible/plugins/action/validate_argument_spec.py +5 -5
- ansible/plugins/action/wait_for_connection.py +1 -1
- ansible/plugins/become/__init__.py +31 -8
- ansible/plugins/become/runas.py +71 -0
- ansible/plugins/become/su.py +13 -8
- ansible/plugins/become/sudo.py +19 -0
- ansible/plugins/cache/__init__.py +35 -44
- ansible/plugins/cache/base.py +8 -0
- ansible/plugins/cache/jsonfile.py +10 -16
- ansible/plugins/cache/memory.py +6 -12
- ansible/plugins/callback/__init__.py +284 -179
- ansible/plugins/callback/default.py +99 -92
- ansible/plugins/callback/junit.py +44 -39
- ansible/plugins/callback/minimal.py +28 -25
- ansible/plugins/callback/oneline.py +28 -21
- ansible/plugins/callback/tree.py +16 -11
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +150 -54
- ansible/plugins/connection/paramiko_ssh.py +21 -18
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +301 -78
- ansible/plugins/connection/winrm.py +58 -140
- ansible/plugins/doc_fragments/action_common_attributes.py +14 -14
- ansible/plugins/doc_fragments/action_core.py +6 -6
- ansible/plugins/doc_fragments/backup.py +2 -2
- ansible/plugins/doc_fragments/checksum_common.py +27 -0
- ansible/plugins/doc_fragments/constructed.py +6 -2
- ansible/plugins/doc_fragments/decrypt.py +2 -2
- ansible/plugins/doc_fragments/default_callback.py +2 -2
- ansible/plugins/doc_fragments/files.py +2 -2
- ansible/plugins/doc_fragments/inventory_cache.py +2 -2
- ansible/plugins/doc_fragments/result_format_callback.py +2 -2
- ansible/plugins/doc_fragments/return_common.py +2 -2
- ansible/plugins/doc_fragments/template_common.py +4 -4
- ansible/plugins/doc_fragments/url.py +17 -1
- ansible/plugins/doc_fragments/url_windows.py +2 -2
- ansible/plugins/doc_fragments/validate.py +2 -2
- ansible/plugins/doc_fragments/vars_plugin_staging.py +2 -2
- ansible/plugins/filter/__init__.py +6 -2
- ansible/plugins/filter/b64decode.yml +22 -0
- ansible/plugins/filter/b64encode.yml +22 -0
- ansible/plugins/filter/bool.yml +11 -4
- ansible/plugins/filter/core.py +225 -108
- ansible/plugins/filter/encryption.py +32 -32
- ansible/plugins/filter/flatten.yml +3 -2
- ansible/plugins/filter/human_to_bytes.yml +1 -1
- ansible/plugins/filter/mathstuff.py +30 -37
- ansible/plugins/filter/password_hash.yml +8 -0
- ansible/plugins/filter/regex_search.yml +1 -4
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- ansible/plugins/filter/to_yaml.yml +0 -4
- ansible/plugins/filter/unvault.yml +1 -1
- ansible/plugins/filter/urls.py +1 -1
- ansible/plugins/filter/urlsplit.py +8 -9
- ansible/plugins/filter/vault.yml +14 -9
- ansible/plugins/filter/win_basename.yml +6 -1
- ansible/plugins/filter/win_dirname.yml +5 -0
- ansible/plugins/inventory/__init__.py +97 -77
- ansible/plugins/inventory/advanced_host_list.py +7 -5
- ansible/plugins/inventory/auto.py +11 -4
- ansible/plugins/inventory/constructed.py +21 -24
- ansible/plugins/inventory/generator.py +16 -11
- ansible/plugins/inventory/host_list.py +7 -5
- ansible/plugins/inventory/ini.py +78 -44
- ansible/plugins/inventory/script.py +189 -119
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +3 -3
- ansible/plugins/loader.py +197 -82
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +3 -2
- ansible/plugins/lookup/dict.py +1 -6
- ansible/plugins/lookup/env.py +12 -9
- ansible/plugins/lookup/file.py +5 -8
- ansible/plugins/lookup/first_found.py +86 -55
- ansible/plugins/lookup/indexed_items.py +1 -10
- ansible/plugins/lookup/ini.py +14 -13
- ansible/plugins/lookup/items.py +1 -1
- ansible/plugins/lookup/lines.py +8 -1
- ansible/plugins/lookup/list.py +1 -1
- ansible/plugins/lookup/nested.py +2 -18
- ansible/plugins/lookup/password.py +5 -5
- ansible/plugins/lookup/pipe.py +5 -7
- ansible/plugins/lookup/sequence.py +18 -8
- ansible/plugins/lookup/subelements.py +1 -4
- ansible/plugins/lookup/template.py +42 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +2 -8
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +2 -2
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +39 -22
- ansible/plugins/shell/sh.py +3 -2
- ansible/plugins/strategy/__init__.py +159 -184
- ansible/plugins/strategy/debug.py +2 -2
- ansible/plugins/strategy/free.py +16 -31
- ansible/plugins/strategy/host_pinned.py +2 -2
- ansible/plugins/strategy/linear.py +41 -41
- ansible/plugins/terminal/__init__.py +4 -4
- ansible/plugins/test/__init__.py +7 -2
- ansible/plugins/test/core.py +55 -21
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +3 -3
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +370 -944
- ansible/utils/__init__.py +0 -18
- ansible/utils/_ssh_agent.py +657 -0
- ansible/utils/collection_loader/__init__.py +52 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +79 -93
- ansible/utils/collection_loader/_collection_meta.py +13 -8
- ansible/utils/display.py +433 -63
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/hashing.py +2 -2
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +8 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +4 -4
- ansible/utils/plugin_docs.py +14 -13
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +1 -1
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +51 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +5 -5
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +206 -282
- ansible/vars/reserved.py +8 -9
- ansible_core-2.19.0b2.dist-info/BSD-3-Clause.txt +28 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/METADATA +5 -4
- ansible_core-2.19.0b2.dist-info/RECORD +1072 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/WHEEL +1 -1
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/remote.txt +6 -6
- ansible_test/_data/completion/windows.txt +1 -0
- ansible_test/_data/requirements/ansible.txt +2 -2
- ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
- ansible_test/_data/requirements/sanity.changelog.txt +1 -1
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pylint.txt +4 -4
- ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_data/requirements/units.txt +1 -0
- ansible_test/_internal/__init__.py +1 -0
- ansible_test/_internal/ansible_util.py +2 -0
- ansible_test/_internal/become.py +1 -0
- ansible_test/_internal/bootstrap.py +1 -0
- ansible_test/_internal/cache.py +1 -0
- ansible_test/_internal/cgroup.py +1 -0
- ansible_test/_internal/ci/__init__.py +1 -0
- ansible_test/_internal/ci/azp.py +1 -0
- ansible_test/_internal/ci/local.py +1 -0
- ansible_test/_internal/classification/__init__.py +1 -0
- ansible_test/_internal/classification/common.py +1 -0
- ansible_test/_internal/classification/csharp.py +1 -0
- ansible_test/_internal/classification/powershell.py +1 -0
- ansible_test/_internal/classification/python.py +1 -0
- ansible_test/_internal/cli/__init__.py +1 -0
- ansible_test/_internal/cli/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/__init__.py +1 -0
- ansible_test/_internal/cli/argparsing/actions.py +1 -0
- ansible_test/_internal/cli/argparsing/argcompletion.py +1 -0
- ansible_test/_internal/cli/argparsing/parsers.py +1 -0
- ansible_test/_internal/cli/commands/__init__.py +11 -0
- ansible_test/_internal/cli/commands/coverage/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/cli/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/cli/commands/coverage/combine.py +1 -0
- ansible_test/_internal/cli/commands/coverage/erase.py +1 -0
- ansible_test/_internal/cli/commands/coverage/html.py +1 -0
- ansible_test/_internal/cli/commands/coverage/report.py +1 -0
- ansible_test/_internal/cli/commands/coverage/xml.py +1 -0
- ansible_test/_internal/cli/commands/env.py +1 -0
- ansible_test/_internal/cli/commands/integration/__init__.py +1 -0
- ansible_test/_internal/cli/commands/integration/network.py +1 -0
- ansible_test/_internal/cli/commands/integration/posix.py +1 -0
- ansible_test/_internal/cli/commands/integration/windows.py +1 -0
- ansible_test/_internal/cli/commands/sanity.py +9 -0
- ansible_test/_internal/cli/commands/shell.py +1 -0
- ansible_test/_internal/cli/commands/units.py +1 -0
- ansible_test/_internal/cli/compat.py +1 -0
- ansible_test/_internal/cli/completers.py +1 -0
- ansible_test/_internal/cli/converters.py +1 -0
- ansible_test/_internal/cli/environments.py +1 -0
- ansible_test/_internal/cli/epilog.py +1 -0
- ansible_test/_internal/cli/parsers/__init__.py +1 -0
- ansible_test/_internal/cli/parsers/base_argument_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/helpers.py +1 -0
- ansible_test/_internal/cli/parsers/host_config_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/key_value_parsers.py +1 -0
- ansible_test/_internal/cli/parsers/value_parsers.py +1 -0
- ansible_test/_internal/commands/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/__init__.py +2 -1
- ansible_test/_internal/commands/coverage/analyze/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/__init__.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/combine.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/expand.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/filter.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/generate.py +1 -0
- ansible_test/_internal/commands/coverage/analyze/targets/missing.py +1 -0
- ansible_test/_internal/commands/coverage/combine.py +2 -1
- ansible_test/_internal/commands/coverage/erase.py +1 -0
- ansible_test/_internal/commands/coverage/html.py +1 -0
- ansible_test/_internal/commands/coverage/report.py +1 -0
- ansible_test/_internal/commands/coverage/xml.py +1 -0
- ansible_test/_internal/commands/env/__init__.py +2 -0
- ansible_test/_internal/commands/integration/__init__.py +4 -0
- ansible_test/_internal/commands/integration/cloud/__init__.py +1 -0
- ansible_test/_internal/commands/integration/cloud/acme.py +2 -1
- ansible_test/_internal/commands/integration/cloud/aws.py +1 -0
- ansible_test/_internal/commands/integration/cloud/azure.py +1 -0
- ansible_test/_internal/commands/integration/cloud/cs.py +1 -0
- ansible_test/_internal/commands/integration/cloud/digitalocean.py +1 -0
- ansible_test/_internal/commands/integration/cloud/galaxy.py +3 -2
- ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -0
- ansible_test/_internal/commands/integration/cloud/httptester.py +2 -1
- ansible_test/_internal/commands/integration/cloud/nios.py +2 -1
- ansible_test/_internal/commands/integration/cloud/opennebula.py +1 -0
- ansible_test/_internal/commands/integration/cloud/openshift.py +1 -0
- ansible_test/_internal/commands/integration/cloud/scaleway.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vcenter.py +1 -0
- ansible_test/_internal/commands/integration/cloud/vultr.py +1 -0
- ansible_test/_internal/commands/integration/coverage.py +1 -0
- ansible_test/_internal/commands/integration/filters.py +1 -0
- ansible_test/_internal/commands/integration/network.py +1 -0
- ansible_test/_internal/commands/integration/posix.py +1 -0
- ansible_test/_internal/commands/integration/windows.py +1 -0
- ansible_test/_internal/commands/sanity/__init__.py +16 -1
- ansible_test/_internal/commands/sanity/ansible_doc.py +1 -0
- ansible_test/_internal/commands/sanity/bin_symlinks.py +1 -0
- ansible_test/_internal/commands/sanity/compile.py +1 -0
- ansible_test/_internal/commands/sanity/ignores.py +1 -0
- ansible_test/_internal/commands/sanity/import.py +1 -0
- ansible_test/_internal/commands/sanity/integration_aliases.py +1 -0
- ansible_test/_internal/commands/sanity/pep8.py +1 -0
- ansible_test/_internal/commands/sanity/pslint.py +1 -0
- ansible_test/_internal/commands/sanity/pylint.py +24 -26
- ansible_test/_internal/commands/sanity/shellcheck.py +1 -0
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -0
- ansible_test/_internal/commands/sanity/yamllint.py +1 -0
- ansible_test/_internal/commands/shell/__init__.py +1 -0
- ansible_test/_internal/commands/units/__init__.py +1 -0
- ansible_test/_internal/compat/__init__.py +1 -0
- ansible_test/_internal/compat/packaging.py +1 -0
- ansible_test/_internal/compat/yaml.py +1 -0
- ansible_test/_internal/completion.py +1 -0
- ansible_test/_internal/config.py +2 -0
- ansible_test/_internal/connections.py +1 -0
- ansible_test/_internal/constants.py +1 -0
- ansible_test/_internal/containers.py +1 -0
- ansible_test/_internal/content_config.py +1 -0
- ansible_test/_internal/core_ci.py +1 -0
- ansible_test/_internal/coverage_util.py +11 -10
- ansible_test/_internal/data.py +1 -0
- ansible_test/_internal/delegation.py +1 -0
- ansible_test/_internal/dev/__init__.py +1 -0
- ansible_test/_internal/dev/container_probe.py +1 -0
- ansible_test/_internal/diff.py +3 -2
- ansible_test/_internal/docker_util.py +2 -1
- ansible_test/_internal/encoding.py +1 -0
- ansible_test/_internal/executor.py +1 -0
- ansible_test/_internal/git.py +1 -0
- ansible_test/_internal/host_configs.py +1 -0
- ansible_test/_internal/host_profiles.py +1 -0
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +35 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +1 -0
- ansible_test/_internal/payload.py +1 -0
- ansible_test/_internal/provider/__init__.py +1 -0
- ansible_test/_internal/provider/layout/__init__.py +1 -0
- ansible_test/_internal/provider/layout/ansible.py +1 -0
- ansible_test/_internal/provider/layout/collection.py +1 -0
- ansible_test/_internal/provider/layout/unsupported.py +1 -0
- ansible_test/_internal/provider/source/__init__.py +1 -0
- ansible_test/_internal/provider/source/git.py +1 -0
- ansible_test/_internal/provider/source/installed.py +1 -0
- ansible_test/_internal/provider/source/unsupported.py +1 -0
- ansible_test/_internal/provider/source/unversioned.py +1 -0
- ansible_test/_internal/provisioning.py +1 -0
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +1 -0
- ansible_test/_internal/ssh.py +1 -0
- ansible_test/_internal/target.py +1 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +1 -0
- ansible_test/_internal/timeout.py +1 -0
- ansible_test/_internal/util.py +1 -0
- ansible_test/_internal/util_common.py +5 -2
- ansible_test/_internal/venv.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog/sphinx.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/changelog.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/empty-init.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/line-endings.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-assert.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-get-exception.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-illegal-filenames.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/no-smart-quotes.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/replace-urlopen.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +28 -1
- ansible_test/_util/controller/sanity/code-smell/shebang.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/symlinks.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-argspec-type-path.py +1 -0
- ansible_test/_util/controller/sanity/code-smell/use-compat-six.py +1 -0
- ansible_test/_util/controller/sanity/integration-aliases/yaml_to_json.py +2 -1
- ansible_test/_util/controller/sanity/pep8/current-ignore.txt +4 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +7 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +3 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +7 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -13
- ansible_test/_util/controller/sanity/pylint/plugins/hide_unraisable.py +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +1 -8
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +1 -8
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +55 -28
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +12 -5
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +13 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -0
- ansible_test/_util/controller/sanity/yamllint/yamllinter.py +35 -17
- ansible_test/_util/controller/tools/collection_detail.py +1 -0
- ansible_test/_util/controller/tools/yaml_to_json.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_forked.py +6 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_collections.py +2 -1
- ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +1 -0
- ansible_test/_util/target/sanity/compile/compile.py +1 -0
- ansible_test/_util/target/sanity/import/importer.py +15 -16
- ansible_test/_util/target/setup/bootstrap.sh +9 -20
- ansible_test/_util/target/setup/probe_cgroups.py +1 -0
- ansible_test/_util/target/setup/quiet_pip.py +1 -0
- ansible_test/_util/target/setup/requirements.py +35 -27
- ansible_test/_util/target/tools/virtualenvcheck.py +2 -1
- ansible_test/_util/target/tools/yamlcheck.py +2 -1
- ansible/compat/selectors.py +0 -32
- ansible/errors/yaml_strings.py +0 -138
- ansible/executor/action_write_locks.py +0 -44
- ansible/executor/discovery/python_target.py +0 -47
- ansible/executor/powershell/module_powershell_wrapper.ps1 +0 -86
- ansible/executor/powershell/module_script_wrapper.ps1 +0 -22
- ansible/module_utils/compat/importlib.py +0 -26
- ansible/module_utils/compat/selectors.py +0 -32
- ansible/module_utils/pycompat24.py +0 -73
- ansible/parsing/yaml/constructor.py +0 -178
- ansible/template/native_helpers.py +0 -251
- ansible/template/template.py +0 -43
- ansible/template/vars.py +0 -77
- ansible/utils/native_jinja.py +0 -11
- ansible/vars/fact_cache.py +0 -71
- ansible_core-2.18.5rc1.dist-info/RECORD +0 -992
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/Apache-License.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/COPYING +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/MIT-license.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/PSF-license.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/simplified_bsd.txt +0 -0
- {ansible_core-2.18.5rc1.dist-info → ansible_core-2.19.0b2.dist-info}/top_level.txt +0 -0
ansible/plugins/filter/core.py
CHANGED
@@ -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.
|
27
|
-
from ansible.
|
28
|
+
from ansible._internal._templating import _lazy_containers
|
29
|
+
from ansible.errors import AnsibleFilterError, AnsibleTypeError, AnsibleTemplatePluginError
|
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.
|
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, *
|
47
|
-
|
48
|
-
|
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
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
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,
|
66
|
-
|
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
|
-
|
69
|
-
|
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
|
-
|
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
|
-
|
78
|
-
|
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
|
-
|
81
|
-
return to_json(a, indent=indent, sort_keys=sort_keys, separators=(',', ': '),
|
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
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
if isinstance(
|
89
|
-
|
90
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
335
|
+
@accept_args_markers
|
336
|
+
def mandatory(a: object, msg: str | None = None) -> object:
|
328
337
|
"""Make a variable mandatory."""
|
329
|
-
|
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 =
|
345
|
+
name = f'{to_text(a._undefined_name)!r} '
|
334
346
|
else:
|
335
347
|
name = ''
|
336
348
|
|
337
|
-
|
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
|
|
@@ -398,6 +405,13 @@ def comment(text, style='plain', **kw):
|
|
398
405
|
}
|
399
406
|
}
|
400
407
|
|
408
|
+
if style not in comment_styles:
|
409
|
+
raise AnsibleTemplatePluginError(
|
410
|
+
message=f"Invalid style {style!r}.",
|
411
|
+
help_text=f"Available styles: {', '.join(comment_styles)}",
|
412
|
+
obj=style,
|
413
|
+
)
|
414
|
+
|
401
415
|
# Pointer to the right comment type
|
402
416
|
style_params = comment_styles[style]
|
403
417
|
|
@@ -458,7 +472,7 @@ def comment(text, style='plain', **kw):
|
|
458
472
|
|
459
473
|
|
460
474
|
@pass_environment
|
461
|
-
def extract(environment, item, container, morekeys=None):
|
475
|
+
def extract(environment: Environment, item, container, morekeys=None):
|
462
476
|
if morekeys is None:
|
463
477
|
keys = [item]
|
464
478
|
elif isinstance(morekeys, list):
|
@@ -467,18 +481,28 @@ def extract(environment, item, container, morekeys=None):
|
|
467
481
|
keys = [item, morekeys]
|
468
482
|
|
469
483
|
value = container
|
484
|
+
|
470
485
|
for key in keys:
|
471
|
-
|
486
|
+
try:
|
487
|
+
value = environment.getitem(value, key)
|
488
|
+
except MarkerError as ex:
|
489
|
+
value = ex.source
|
472
490
|
|
473
491
|
return value
|
474
492
|
|
475
493
|
|
476
|
-
def b64encode(string, encoding='utf-8'):
|
477
|
-
|
494
|
+
def b64encode(string, encoding='utf-8', urlsafe=False):
|
495
|
+
func = base64.b64encode
|
496
|
+
if urlsafe:
|
497
|
+
func = base64.urlsafe_b64encode
|
498
|
+
return to_text(func(to_bytes(string, encoding=encoding, errors='surrogate_or_strict')))
|
478
499
|
|
479
500
|
|
480
|
-
def b64decode(string, encoding='utf-8'):
|
481
|
-
|
501
|
+
def b64decode(string, encoding='utf-8', urlsafe=False):
|
502
|
+
func = base64.b64decode
|
503
|
+
if urlsafe:
|
504
|
+
func = base64.urlsafe_b64decode
|
505
|
+
return to_text(func(to_bytes(string, errors='surrogate_or_strict')), encoding=encoding)
|
482
506
|
|
483
507
|
|
484
508
|
def flatten(mylist, levels=None, skip_nulls=True):
|
@@ -503,14 +527,14 @@ def flatten(mylist, levels=None, skip_nulls=True):
|
|
503
527
|
|
504
528
|
|
505
529
|
def subelements(obj, subelements, skip_missing=False):
|
506
|
-
|
530
|
+
"""Accepts a dict or list of dicts, and a dotted accessor and produces a product
|
507
531
|
of the element and the results of the dotted accessor
|
508
532
|
|
509
533
|
>>> obj = [{"name": "alice", "groups": ["wheel"], "authorized": ["/tmp/alice/onekey.pub"]}]
|
510
534
|
>>> subelements(obj, 'groups')
|
511
535
|
[({'name': 'alice', 'groups': ['wheel'], 'authorized': ['/tmp/alice/onekey.pub']}, 'wheel')]
|
512
536
|
|
513
|
-
|
537
|
+
"""
|
514
538
|
if isinstance(obj, dict):
|
515
539
|
element_list = list(obj.values())
|
516
540
|
elif isinstance(obj, list):
|
@@ -523,7 +547,7 @@ def subelements(obj, subelements, skip_missing=False):
|
|
523
547
|
elif isinstance(subelements, string_types):
|
524
548
|
subelement_list = subelements.split('.')
|
525
549
|
else:
|
526
|
-
raise
|
550
|
+
raise AnsibleTypeError('subelements must be a list or a string')
|
527
551
|
|
528
552
|
results = []
|
529
553
|
|
@@ -537,10 +561,10 @@ def subelements(obj, subelements, skip_missing=False):
|
|
537
561
|
values = []
|
538
562
|
break
|
539
563
|
raise AnsibleFilterError("could not find %r key in iterated item %r" % (subelement, values))
|
540
|
-
except TypeError:
|
541
|
-
raise
|
564
|
+
except TypeError as ex:
|
565
|
+
raise AnsibleTypeError("the key %s should point to a dictionary, got '%s'" % (subelement, values)) from ex
|
542
566
|
if not isinstance(values, list):
|
543
|
-
raise
|
567
|
+
raise AnsibleTypeError("the key %r should point to a list, got %r" % (subelement, values))
|
544
568
|
|
545
569
|
for value in values:
|
546
570
|
results.append((element, value))
|
@@ -549,11 +573,11 @@ def subelements(obj, subelements, skip_missing=False):
|
|
549
573
|
|
550
574
|
|
551
575
|
def dict_to_list_of_dict_key_value_elements(mydict, key_name='key', value_name='value'):
|
552
|
-
|
553
|
-
with each having a 'key' and 'value' keys that correspond to the keys and values of the original
|
576
|
+
""" takes a dictionary and transforms it into a list of dictionaries,
|
577
|
+
with each having a 'key' and 'value' keys that correspond to the keys and values of the original """
|
554
578
|
|
555
579
|
if not isinstance(mydict, Mapping):
|
556
|
-
raise
|
580
|
+
raise AnsibleTypeError("dict2items requires a dictionary, got %s instead." % type(mydict))
|
557
581
|
|
558
582
|
ret = []
|
559
583
|
for key in mydict:
|
@@ -562,31 +586,31 @@ def dict_to_list_of_dict_key_value_elements(mydict, key_name='key', value_name='
|
|
562
586
|
|
563
587
|
|
564
588
|
def list_of_dict_key_value_elements_to_dict(mylist, key_name='key', value_name='value'):
|
565
|
-
|
566
|
-
effectively as the reverse of dict2items
|
589
|
+
""" takes a list of dicts with each having a 'key' and 'value' keys, and transforms the list into a dictionary,
|
590
|
+
effectively as the reverse of dict2items """
|
567
591
|
|
568
592
|
if not is_sequence(mylist):
|
569
|
-
raise
|
593
|
+
raise AnsibleTypeError("items2dict requires a list, got %s instead." % type(mylist))
|
570
594
|
|
571
595
|
try:
|
572
596
|
return dict((item[key_name], item[value_name]) for item in mylist)
|
573
597
|
except KeyError:
|
574
|
-
raise
|
598
|
+
raise AnsibleTypeError(
|
575
599
|
"items2dict requires each dictionary in the list to contain the keys '%s' and '%s', got %s instead."
|
576
600
|
% (key_name, value_name, mylist)
|
577
601
|
)
|
578
602
|
except TypeError:
|
579
|
-
raise
|
603
|
+
raise AnsibleTypeError("items2dict requires a list of dictionaries, got %s instead." % mylist)
|
580
604
|
|
581
605
|
|
582
606
|
def path_join(paths):
|
583
|
-
|
584
|
-
of the different members
|
607
|
+
""" takes a sequence or a string, and return a concatenation
|
608
|
+
of the different members """
|
585
609
|
if isinstance(paths, string_types):
|
586
610
|
return os.path.join(paths)
|
587
611
|
if is_sequence(paths):
|
588
612
|
return os.path.join(*paths)
|
589
|
-
raise
|
613
|
+
raise AnsibleTypeError("|path_join expects string or sequence, got %s instead." % type(paths))
|
590
614
|
|
591
615
|
|
592
616
|
def commonpath(paths):
|
@@ -599,13 +623,92 @@ def commonpath(paths):
|
|
599
623
|
:rtype: str
|
600
624
|
"""
|
601
625
|
if not is_sequence(paths):
|
602
|
-
raise
|
626
|
+
raise AnsibleTypeError("|commonpath expects sequence, got %s instead." % type(paths))
|
603
627
|
|
604
628
|
return os.path.commonpath(paths)
|
605
629
|
|
606
630
|
|
631
|
+
class GroupTuple(t.NamedTuple):
|
632
|
+
"""
|
633
|
+
Custom named tuple for the groupby filter with a public interface; silently ignored by unknown type checks.
|
634
|
+
This matches the internal implementation of the _GroupTuple returned by Jinja's built-in groupby filter.
|
635
|
+
"""
|
636
|
+
|
637
|
+
grouper: t.Any
|
638
|
+
list: list[t.Any]
|
639
|
+
|
640
|
+
def __repr__(self) -> str:
|
641
|
+
return tuple.__repr__(self)
|
642
|
+
|
643
|
+
|
644
|
+
_lazy_containers.register_known_types(GroupTuple)
|
645
|
+
|
646
|
+
|
647
|
+
@pass_environment
|
648
|
+
def _cleansed_groupby(*args, **kwargs):
|
649
|
+
res = sync_do_groupby(*args, **kwargs)
|
650
|
+
res = [GroupTuple(grouper=g.grouper, list=g.list) for g in res]
|
651
|
+
|
652
|
+
return res
|
653
|
+
|
654
|
+
# DTFIX-RELEASE: make these dumb wrappers more dynamic
|
655
|
+
|
656
|
+
|
657
|
+
@accept_args_markers
|
658
|
+
def ansible_default(
|
659
|
+
value: t.Any,
|
660
|
+
default_value: t.Any = '',
|
661
|
+
boolean: bool = False,
|
662
|
+
) -> t.Any:
|
663
|
+
"""Updated `default` filter that only coalesces classic undefined objects; other Undefined-derived types (eg, ErrorMarker) pass through."""
|
664
|
+
validate_arg_type('boolean', boolean, bool)
|
665
|
+
|
666
|
+
if isinstance(value, UndefinedMarker):
|
667
|
+
return default_value
|
668
|
+
|
669
|
+
if boolean and not value:
|
670
|
+
return default_value
|
671
|
+
|
672
|
+
return value
|
673
|
+
|
674
|
+
|
675
|
+
@accept_lazy_markers
|
676
|
+
@functools.wraps(do_map)
|
677
|
+
def wrapped_map(*args, **kwargs) -> t.Any:
|
678
|
+
return do_map(*args, **kwargs)
|
679
|
+
|
680
|
+
|
681
|
+
@accept_lazy_markers
|
682
|
+
@functools.wraps(do_select)
|
683
|
+
def wrapped_select(*args, **kwargs) -> t.Any:
|
684
|
+
return do_select(*args, **kwargs)
|
685
|
+
|
686
|
+
|
687
|
+
@accept_lazy_markers
|
688
|
+
@functools.wraps(do_selectattr)
|
689
|
+
def wrapped_selectattr(*args, **kwargs) -> t.Any:
|
690
|
+
return do_selectattr(*args, **kwargs)
|
691
|
+
|
692
|
+
|
693
|
+
@accept_lazy_markers
|
694
|
+
@functools.wraps(do_reject)
|
695
|
+
def wrapped_reject(*args, **kwargs) -> t.Any:
|
696
|
+
return do_reject(*args, **kwargs)
|
697
|
+
|
698
|
+
|
699
|
+
@accept_lazy_markers
|
700
|
+
@functools.wraps(do_rejectattr)
|
701
|
+
def wrapped_rejectattr(*args, **kwargs) -> t.Any:
|
702
|
+
return do_rejectattr(*args, **kwargs)
|
703
|
+
|
704
|
+
|
705
|
+
@accept_args_markers
|
706
|
+
def type_debug(obj: object) -> str:
|
707
|
+
return native_type_name(obj)
|
708
|
+
|
709
|
+
|
607
710
|
class FilterModule(object):
|
608
|
-
|
711
|
+
""" Ansible core jinja2 filters """
|
609
712
|
|
610
713
|
def filters(self):
|
611
714
|
return {
|
@@ -619,7 +722,7 @@ class FilterModule(object):
|
|
619
722
|
# json
|
620
723
|
'to_json': to_json,
|
621
724
|
'to_nice_json': to_nice_json,
|
622
|
-
'from_json':
|
725
|
+
'from_json': from_json,
|
623
726
|
|
624
727
|
# yaml
|
625
728
|
'to_yaml': to_yaml,
|
@@ -686,7 +789,7 @@ class FilterModule(object):
|
|
686
789
|
'comment': comment,
|
687
790
|
|
688
791
|
# debug
|
689
|
-
'type_debug':
|
792
|
+
'type_debug': type_debug,
|
690
793
|
|
691
794
|
# Data structures
|
692
795
|
'combine': combine,
|
@@ -696,4 +799,18 @@ class FilterModule(object):
|
|
696
799
|
'items2dict': list_of_dict_key_value_elements_to_dict,
|
697
800
|
'subelements': subelements,
|
698
801
|
'split': partial(unicode_wrap, text_type.split),
|
802
|
+
# FDI038 - replace this with a standard type compat shim
|
803
|
+
'groupby': _cleansed_groupby,
|
804
|
+
|
805
|
+
# Jinja builtins that need special arg handling
|
806
|
+
# DTFIX-RELEASE: document these now that they're overridden, or hide them so they don't show up as undocumented
|
807
|
+
'd': ansible_default, # replaces the implementation instead of wrapping it
|
808
|
+
'default': ansible_default, # replaces the implementation instead of wrapping it
|
809
|
+
'map': wrapped_map,
|
810
|
+
'select': wrapped_select,
|
811
|
+
'selectattr': wrapped_selectattr,
|
812
|
+
'reject': wrapped_reject,
|
813
|
+
'rejectattr': wrapped_rejectattr,
|
699
814
|
}
|
815
|
+
|
816
|
+
# 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)
|