ansible-core 2.18.7rc1__py3-none-any.whl → 2.19.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ansible-core might be problematic. Click here for more details.
- ansible/_internal/__init__.py +53 -0
- ansible/_internal/_ansiballz/__init__.py +0 -0
- ansible/_internal/_ansiballz/_builder.py +101 -0
- ansible/_internal/_ansiballz/_wrapper.py +262 -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/_alarm_timeout.py +66 -0
- ansible/_internal/_errors/_captured.py +123 -0
- ansible/_internal/_errors/_error_factory.py +89 -0
- ansible/_internal/_errors/_error_utils.py +240 -0
- ansible/_internal/_errors/_handler.py +91 -0
- ansible/_internal/_errors/_task_timeout.py +28 -0
- ansible/_internal/_event_formatting.py +127 -0
- ansible/_internal/_json/__init__.py +214 -0
- ansible/_internal/_json/_legacy_encoder.py +34 -0
- ansible/_internal/_json/_profiles/__init__.py +0 -0
- ansible/_internal/_json/_profiles/_cache_persistence.py +57 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +40 -0
- ansible/_internal/_json/_profiles/_legacy.py +189 -0
- ansible/_internal/_locking.py +21 -0
- ansible/_internal/_plugins/__init__.py +0 -0
- ansible/_internal/_plugins/_cache.py +57 -0
- ansible/_internal/_ssh/__init__.py +0 -0
- ansible/_internal/_ssh/_agent_launch.py +91 -0
- ansible/_internal/_ssh/_ssh_agent.py +619 -0
- ansible/_internal/_task.py +78 -0
- ansible/_internal/_templating/__init__.py +12 -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 +592 -0
- ansible/_internal/_templating/_errors.py +28 -0
- ansible/_internal/_templating/_jinja_bits.py +1106 -0
- ansible/_internal/_templating/_jinja_common.py +323 -0
- ansible/_internal/_templating/_jinja_patches.py +44 -0
- ansible/_internal/_templating/_jinja_plugins.py +375 -0
- ansible/_internal/_templating/_lazy_containers.py +633 -0
- ansible/_internal/_templating/_marker_behaviors.py +103 -0
- ansible/_internal/_templating/_template_vars.py +72 -0
- ansible/_internal/_templating/_transform.py +70 -0
- ansible/_internal/_templating/_utils.py +108 -0
- ansible/_internal/_testing.py +26 -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 +70 -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 +27 -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 +93 -104
- ansible/cli/_ssh_askpass.py +54 -0
- ansible/cli/adhoc.py +20 -10
- ansible/cli/arguments/option_helpers.py +163 -10
- ansible/cli/config.py +43 -68
- ansible/cli/console.py +13 -11
- ansible/cli/doc.py +134 -77
- ansible/cli/galaxy.py +27 -20
- ansible/cli/inventory.py +28 -28
- ansible/cli/playbook.py +4 -12
- ansible/cli/pull.py +6 -3
- ansible/cli/scripts/ansible_connection_cli_stub.py +7 -7
- ansible/cli/vault.py +12 -11
- ansible/compat/__init__.py +2 -2
- ansible/compat/importlib_resources.py +9 -12
- ansible/config/base.yml +218 -133
- ansible/config/manager.py +220 -159
- ansible/constants.py +2 -65
- ansible/errors/__init__.py +350 -256
- ansible/executor/interpreter_discovery.py +28 -149
- ansible/executor/module_common.py +480 -514
- 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 +204 -153
- ansible/executor/powershell/become_wrapper.ps1 +107 -144
- ansible/executor/powershell/bootstrap_wrapper.ps1 +46 -9
- ansible/executor/powershell/coverage_wrapper.ps1 +91 -135
- ansible/executor/powershell/exec_wrapper.ps1 +675 -196
- ansible/executor/powershell/module_manifest.py +469 -265
- ansible/executor/powershell/module_wrapper.ps1 +195 -186
- ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
- ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
- 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 +139 -149
- ansible/executor/stats.py +5 -5
- ansible/executor/task_executor.py +270 -297
- ansible/executor/task_queue_manager.py +135 -137
- ansible/executor/task_result.py +182 -79
- ansible/galaxy/__init__.py +2 -2
- ansible/galaxy/api.py +26 -25
- ansible/galaxy/collection/__init__.py +6 -14
- ansible/galaxy/collection/concrete_artifact_manager.py +12 -21
- ansible/galaxy/dependency_resolution/dataclasses.py +14 -4
- ansible/galaxy/dependency_resolution/providers.py +4 -4
- ansible/galaxy/dependency_resolution/reporters.py +81 -0
- ansible/galaxy/role.py +6 -10
- ansible/galaxy/token.py +28 -21
- ansible/inventory/data.py +47 -57
- ansible/inventory/group.py +50 -73
- ansible/inventory/helpers.py +9 -0
- ansible/inventory/host.py +37 -54
- ansible/inventory/manager.py +79 -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/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
- ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
- ansible/module_utils/_internal/_ansiballz/_loader.py +81 -0
- ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
- ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
- ansible/module_utils/_internal/_concurrent/_daemon_threading.py +1 -0
- ansible/module_utils/_internal/_dataclass_validation.py +217 -0
- ansible/module_utils/_internal/_datatag/__init__.py +961 -0
- ansible/module_utils/_internal/_datatag/_tags.py +16 -0
- ansible/module_utils/_internal/_debugging.py +31 -0
- ansible/module_utils/_internal/_deprecator.py +157 -0
- ansible/module_utils/_internal/_errors.py +101 -0
- ansible/module_utils/_internal/_event_utils.py +61 -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 +428 -0
- ansible/module_utils/_internal/_json/_profiles/_fallback_to_str.py +73 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +33 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +37 -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 +52 -0
- ansible/module_utils/_internal/_messages.py +130 -0
- ansible/module_utils/_internal/_patches/__init__.py +66 -0
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +53 -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_info.py +38 -0
- ansible/module_utils/_internal/_stack.py +22 -0
- ansible/module_utils/_internal/_testing.py +0 -0
- ansible/module_utils/_internal/_text_utils.py +6 -0
- ansible/module_utils/_internal/_traceback.py +92 -0
- ansible/module_utils/_internal/_validation.py +14 -0
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/api.py +1 -2
- ansible/module_utils/basic.py +303 -202
- ansible/module_utils/common/_utils.py +24 -28
- ansible/module_utils/common/arg_spec.py +8 -3
- ansible/module_utils/common/collections.py +7 -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/parameters.py +27 -24
- ansible/module_utils/common/process.py +2 -3
- ansible/module_utils/common/respawn.py +11 -33
- 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 +143 -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 +10 -13
- ansible/module_utils/csharp/Ansible.Basic.cs +15 -12
- ansible/module_utils/csharp/Ansible.Become.cs +1 -0
- ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
- ansible/module_utils/csharp/Ansible._Async.cs +517 -0
- ansible/module_utils/datatag.py +49 -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 +2 -2
- 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 +5 -5
- 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 +2 -3
- ansible/module_utils/facts/other/ohai.py +2 -3
- ansible/module_utils/facts/sysctl.py +4 -6
- ansible/module_utils/facts/system/apparmor.py +1 -2
- ansible/module_utils/facts/system/caps.py +3 -3
- 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 +27 -13
- 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 +2 -3
- 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/linux.py +3 -3
- 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 +7 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
- ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
- ansible/module_utils/service.py +21 -31
- ansible/module_utils/splitter.py +7 -7
- ansible/module_utils/testing.py +31 -0
- ansible/module_utils/urls.py +64 -35
- ansible/modules/add_host.py +4 -4
- ansible/modules/apt.py +69 -49
- ansible/modules/apt_key.py +19 -12
- ansible/modules/apt_repository.py +32 -51
- ansible/modules/assemble.py +16 -14
- ansible/modules/assert.py +4 -4
- ansible/modules/async_status.py +24 -24
- ansible/modules/async_wrapper.py +20 -25
- ansible/modules/blockinfile.py +6 -7
- ansible/modules/command.py +13 -20
- ansible/modules/copy.py +60 -147
- ansible/modules/cron.py +24 -21
- 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 +13 -15
- ansible/modules/fail.py +4 -4
- ansible/modules/fetch.py +4 -4
- ansible/modules/file.py +184 -144
- ansible/modules/find.py +22 -20
- ansible/modules/gather_facts.py +3 -3
- ansible/modules/get_url.py +77 -54
- ansible/modules/getent.py +7 -9
- ansible/modules/git.py +38 -38
- ansible/modules/group.py +6 -6
- ansible/modules/group_by.py +4 -4
- ansible/modules/hostname.py +15 -32
- 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 +22 -24
- ansible/modules/lineinfile.py +5 -5
- ansible/modules/meta.py +4 -4
- ansible/modules/mount_facts.py +2 -2
- ansible/modules/package.py +10 -4
- ansible/modules/package_facts.py +22 -10
- ansible/modules/pause.py +6 -6
- ansible/modules/ping.py +6 -6
- ansible/modules/pip.py +21 -26
- ansible/modules/raw.py +6 -6
- ansible/modules/reboot.py +6 -6
- ansible/modules/replace.py +10 -14
- ansible/modules/rpm_key.py +7 -8
- ansible/modules/script.py +4 -4
- ansible/modules/service.py +10 -17
- 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 +16 -19
- ansible/modules/stat.py +15 -31
- ansible/modules/subversion.py +15 -15
- ansible/modules/systemd.py +7 -7
- ansible/modules/systemd_service.py +7 -7
- ansible/modules/sysvinit.py +9 -9
- ansible/modules/tempfile.py +5 -6
- ansible/modules/template.py +6 -6
- ansible/modules/unarchive.py +38 -17
- ansible/modules/uri.py +33 -26
- ansible/modules/user.py +45 -32
- ansible/modules/validate_argument_spec.py +10 -7
- ansible/modules/wait_for.py +70 -60
- ansible/modules/wait_for_connection.py +6 -6
- ansible/modules/yum_repository.py +10 -9
- ansible/parsing/ajson.py +17 -37
- ansible/parsing/dataloader.py +99 -54
- ansible/parsing/mod_args.py +62 -60
- 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 +327 -99
- 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 +187 -134
- 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 +32 -26
- ansible/playbook/loop_control.py +2 -2
- ansible/playbook/play.py +85 -44
- ansible/playbook/play_context.py +14 -17
- ansible/playbook/playbook_include.py +27 -62
- ansible/playbook/role/__init__.py +64 -49
- 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 +28 -12
- ansible/playbook/task.py +192 -121
- ansible/playbook/task_include.py +5 -5
- ansible/plugins/__init__.py +58 -26
- ansible/plugins/action/__init__.py +188 -186
- ansible/plugins/action/add_host.py +2 -2
- ansible/plugins/action/assemble.py +11 -18
- ansible/plugins/action/assert.py +55 -67
- ansible/plugins/action/async_status.py +7 -2
- ansible/plugins/action/copy.py +14 -17
- 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 +7 -8
- ansible/plugins/action/gather_facts.py +13 -14
- ansible/plugins/action/group_by.py +1 -1
- ansible/plugins/action/include_vars.py +10 -11
- ansible/plugins/action/package.py +8 -14
- ansible/plugins/action/pause.py +2 -2
- ansible/plugins/action/script.py +27 -38
- ansible/plugins/action/service.py +9 -18
- ansible/plugins/action/set_fact.py +3 -12
- ansible/plugins/action/set_stats.py +3 -8
- ansible/plugins/action/template.py +47 -67
- ansible/plugins/action/unarchive.py +6 -16
- ansible/plugins/action/uri.py +9 -20
- 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 +52 -63
- 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 +294 -201
- ansible/plugins/callback/default.py +99 -95
- ansible/plugins/callback/junit.py +44 -43
- ansible/plugins/callback/minimal.py +28 -25
- ansible/plugins/callback/oneline.py +34 -21
- ansible/plugins/callback/tree.py +27 -16
- ansible/plugins/connection/__init__.py +47 -34
- ansible/plugins/connection/local.py +156 -60
- ansible/plugins/connection/paramiko_ssh.py +34 -24
- ansible/plugins/connection/psrp.py +76 -165
- ansible/plugins/connection/ssh.py +326 -86
- ansible/plugins/connection/winrm.py +62 -141
- 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 +8 -4
- 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 +245 -120
- ansible/plugins/filter/encryption.py +42 -34
- 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/pow.yml +1 -1
- ansible/plugins/filter/regex_search.yml +1 -4
- ansible/plugins/filter/root.yml +1 -1
- ansible/plugins/filter/split.yml +1 -1
- ansible/plugins/filter/strftime.yml +3 -3
- ansible/plugins/filter/to_nice_yaml.yml +0 -4
- ansible/plugins/filter/to_uuid.yml +1 -1
- 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 +107 -86
- 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 +190 -120
- ansible/plugins/inventory/toml.py +16 -126
- ansible/plugins/inventory/yaml.py +10 -8
- ansible/plugins/list.py +72 -19
- ansible/plugins/loader.py +383 -198
- ansible/plugins/lookup/__init__.py +21 -4
- ansible/plugins/lookup/config.py +21 -35
- ansible/plugins/lookup/csvfile.py +19 -73
- 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 +87 -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 +47 -36
- ansible/plugins/lookup/together.py +0 -12
- ansible/plugins/lookup/unvault.py +1 -5
- ansible/plugins/lookup/url.py +4 -10
- ansible/plugins/lookup/vars.py +16 -24
- ansible/plugins/shell/__init__.py +58 -4
- ansible/plugins/shell/cmd.py +2 -2
- ansible/plugins/shell/powershell.py +106 -31
- ansible/plugins/shell/sh.py +13 -7
- ansible/plugins/strategy/__init__.py +168 -193
- 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 +75 -35
- ansible/plugins/test/files.py +1 -1
- ansible/plugins/test/finished.yml +1 -1
- ansible/plugins/test/mathstuff.py +3 -3
- ansible/plugins/test/uri.py +5 -8
- ansible/plugins/vars/host_group_vars.py +7 -14
- ansible/release.py +2 -2
- ansible/template/__init__.py +353 -943
- ansible/utils/__init__.py +0 -18
- ansible/utils/collection_loader/__init__.py +54 -5
- ansible/utils/collection_loader/_collection_config.py +5 -6
- ansible/utils/collection_loader/_collection_finder.py +82 -96
- ansible/utils/collection_loader/_collection_meta.py +15 -8
- ansible/utils/display.py +485 -73
- ansible/utils/encrypt.py +27 -19
- ansible/utils/fqcn.py +2 -2
- ansible/utils/galaxy.py +2 -2
- ansible/utils/hashing.py +8 -10
- ansible/utils/helpers.py +2 -2
- ansible/utils/listify.py +10 -8
- ansible/utils/lock.py +2 -2
- ansible/utils/path.py +10 -12
- ansible/utils/plugin_docs.py +16 -14
- ansible/utils/py3compat.py +2 -7
- ansible/utils/sentinel.py +4 -62
- ansible/utils/singleton.py +2 -0
- ansible/utils/ssh_functions.py +6 -2
- ansible/utils/unsafe_proxy.py +23 -332
- ansible/utils/vars.py +55 -8
- ansible/utils/version.py +2 -2
- ansible/vars/clean.py +5 -5
- ansible/vars/hostvars.py +60 -90
- ansible/vars/manager.py +220 -285
- ansible/vars/plugins.py +4 -4
- ansible/vars/reserved.py +13 -12
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/METADATA +4 -3
- ansible_core-2.19.0.dist-info/RECORD +1097 -0
- ansible_core-2.19.0.dist-info/licenses/licenses/BSD-3-Clause.txt +28 -0
- 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 +2 -2
- ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +5 -5
- 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 +6 -0
- ansible_test/_internal/ansible_util.py +3 -1
- 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 -5
- 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 +52 -5
- 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 +3 -2
- 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 +22 -5
- 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 +3 -2
- 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 +8 -2
- 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 +19 -2
- 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 +12 -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 +25 -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 +44 -4
- ansible_test/_internal/commands/units/__init__.py +5 -1
- 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 +23 -13
- 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/debugging.py +166 -0
- ansible_test/_internal/delegation.py +22 -13
- 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 +260 -16
- ansible_test/_internal/http.py +1 -0
- ansible_test/_internal/init.py +1 -0
- ansible_test/_internal/inventory.py +39 -3
- ansible_test/_internal/io.py +1 -0
- ansible_test/_internal/metadata.py +95 -4
- ansible_test/_internal/payload.py +1 -0
- ansible_test/_internal/processes.py +80 -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 +11 -4
- ansible_test/_internal/pypi_proxy.py +6 -5
- ansible_test/_internal/python_requirements.py +28 -0
- ansible_test/_internal/ssh.py +2 -5
- ansible_test/_internal/target.py +9 -0
- ansible_test/_internal/test.py +3 -2
- ansible_test/_internal/thread.py +3 -1
- ansible_test/_internal/timeout.py +2 -1
- ansible_test/_internal/util.py +41 -12
- ansible_test/_internal/util_common.py +18 -5
- 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 +8 -5
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +8 -5
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +4 -5
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +8 -7
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +541 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_comment.py +137 -0
- 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/injector/python.py +8 -0
- 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 +38 -36
- 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.7rc1.dist-info/RECORD +0 -992
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +0 -411
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/WHEEL +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.18.7rc1.dist-info → ansible_core-2.19.0.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
|
-
from ansible.module_utils.common.yaml import yaml_load, yaml_load_all
|
|
31
|
-
from ansible.parsing.ajson import AnsibleJSONEncoder
|
|
32
35
|
from ansible.parsing.yaml.dumper import AnsibleDumper
|
|
33
|
-
from ansible.template import
|
|
36
|
+
from ansible.template import accept_args_markers, accept_lazy_markers
|
|
37
|
+
from ansible._internal._templating._jinja_common import MarkerError, UndefinedMarker, validate_arg_type
|
|
38
|
+
from ansible._internal._yaml import _loader as _yaml_loader
|
|
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,84 @@ display = Display()
|
|
|
43
47
|
UUID_NAMESPACE_ANSIBLE = uuid.UUID('361E6D51-FAEC-444A-9079-341386DA8E2E')
|
|
44
48
|
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
+
@accept_lazy_markers
|
|
51
|
+
def to_yaml(a, *_args, default_flow_style: bool | None = None, **kwargs) -> str:
|
|
52
|
+
"""Serialize input as terse flow-style YAML."""
|
|
53
|
+
return yaml.dump(a, Dumper=AnsibleDumper, allow_unicode=True, default_flow_style=default_flow_style, **kwargs)
|
|
54
54
|
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
@accept_lazy_markers
|
|
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)
|
|
67
|
+
|
|
68
|
+
|
|
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."""
|
|
63
71
|
|
|
72
|
+
if profile and vault_to_text is not ...:
|
|
73
|
+
raise ValueError("Only one of `vault_to_text` or `profile` can be specified.")
|
|
64
74
|
|
|
65
|
-
|
|
66
|
-
|
|
75
|
+
if profile and preprocess_unsafe is not ...:
|
|
76
|
+
raise ValueError("Only one of `preprocess_unsafe` or `profile` can be specified.")
|
|
67
77
|
|
|
68
|
-
#
|
|
69
|
-
|
|
70
|
-
kw['vault_to_text'] = True
|
|
71
|
-
if 'preprocess_unsafe' not in kw:
|
|
72
|
-
kw['preprocess_unsafe'] = False
|
|
78
|
+
# deprecated: description='deprecate vault_to_text' core_version='2.23'
|
|
79
|
+
# deprecated: description='deprecate preprocess_unsafe' core_version='2.23'
|
|
73
80
|
|
|
74
|
-
|
|
81
|
+
cls = get_encoder(profile or "tagless")
|
|
75
82
|
|
|
83
|
+
return json.dumps(a, cls=cls, **kwargs)
|
|
76
84
|
|
|
77
|
-
|
|
78
|
-
|
|
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
|
+
|
|
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'}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def to_bool(value: object) -> bool:
|
|
99
|
+
"""Convert well-known input values to a boolean value."""
|
|
100
|
+
value_to_check: object
|
|
101
|
+
|
|
102
|
+
if isinstance(value, str):
|
|
103
|
+
value_to_check = value.lower() # accept mixed case variants
|
|
104
|
+
elif isinstance(value, int): # bool is also an int
|
|
105
|
+
value_to_check = str(value).lower() # accept int (0, 1) and bool (True, False) -- not just string versions
|
|
106
|
+
else:
|
|
107
|
+
value_to_check = value
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
if value_to_check in _valid_bool_true:
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
if value_to_check in _valid_bool_false:
|
|
114
|
+
return False
|
|
82
115
|
|
|
116
|
+
# if we're still here, the value is unsupported- always fire a deprecation warning
|
|
117
|
+
result = value_to_check == 1 # backwards compatibility with the old code which checked: value in ('yes', 'on', '1', 'true', 1)
|
|
118
|
+
except TypeError:
|
|
119
|
+
result = False
|
|
83
120
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return True
|
|
92
|
-
return False
|
|
121
|
+
# NB: update the doc string to reflect reality once this fallback is removed
|
|
122
|
+
display.deprecated(
|
|
123
|
+
msg=f'The `bool` filter coerced invalid value {value!r} ({native_type_name(value)}) to {result!r}.',
|
|
124
|
+
version='2.23',
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
return result
|
|
93
128
|
|
|
94
129
|
|
|
95
130
|
def to_datetime(string, format="%Y-%m-%d %H:%M:%S"):
|
|
@@ -97,7 +132,7 @@ def to_datetime(string, format="%Y-%m-%d %H:%M:%S"):
|
|
|
97
132
|
|
|
98
133
|
|
|
99
134
|
def strftime(string_format, second=None, utc=False):
|
|
100
|
-
|
|
135
|
+
""" return a date string using string. See https://docs.python.org/3/library/time.html#time.strftime for format """
|
|
101
136
|
if utc:
|
|
102
137
|
timefn = time.gmtime
|
|
103
138
|
else:
|
|
@@ -111,19 +146,19 @@ def strftime(string_format, second=None, utc=False):
|
|
|
111
146
|
|
|
112
147
|
|
|
113
148
|
def quote(a):
|
|
114
|
-
|
|
149
|
+
""" return its argument quoted for shell usage """
|
|
115
150
|
if a is None:
|
|
116
151
|
a = u''
|
|
117
152
|
return shlex.quote(to_text(a))
|
|
118
153
|
|
|
119
154
|
|
|
120
155
|
def fileglob(pathname):
|
|
121
|
-
|
|
156
|
+
""" return list of matched regular files for glob """
|
|
122
157
|
return [g for g in glob.glob(pathname) if os.path.isfile(g)]
|
|
123
158
|
|
|
124
159
|
|
|
125
160
|
def regex_replace(value='', pattern='', replacement='', ignorecase=False, multiline=False, count=0, mandatory_count=0):
|
|
126
|
-
|
|
161
|
+
""" Perform a `re.sub` returning a string """
|
|
127
162
|
|
|
128
163
|
value = to_text(value, errors='surrogate_or_strict', nonstring='simplerepr')
|
|
129
164
|
|
|
@@ -141,7 +176,7 @@ def regex_replace(value='', pattern='', replacement='', ignorecase=False, multil
|
|
|
141
176
|
|
|
142
177
|
|
|
143
178
|
def regex_findall(value, regex, multiline=False, ignorecase=False):
|
|
144
|
-
|
|
179
|
+
""" Perform re.findall and return the list of matches """
|
|
145
180
|
|
|
146
181
|
value = to_text(value, errors='surrogate_or_strict', nonstring='simplerepr')
|
|
147
182
|
|
|
@@ -154,7 +189,7 @@ def regex_findall(value, regex, multiline=False, ignorecase=False):
|
|
|
154
189
|
|
|
155
190
|
|
|
156
191
|
def regex_search(value, regex, *args, **kwargs):
|
|
157
|
-
|
|
192
|
+
""" Perform re.search and return the list of matches or a backref """
|
|
158
193
|
|
|
159
194
|
value = to_text(value, errors='surrogate_or_strict', nonstring='simplerepr')
|
|
160
195
|
|
|
@@ -187,7 +222,7 @@ def regex_search(value, regex, *args, **kwargs):
|
|
|
187
222
|
|
|
188
223
|
|
|
189
224
|
def ternary(value, true_val, false_val, none_val=None):
|
|
190
|
-
|
|
225
|
+
""" value ? true_val : false_val """
|
|
191
226
|
if value is None and none_val is not None:
|
|
192
227
|
return none_val
|
|
193
228
|
elif bool(value):
|
|
@@ -216,24 +251,24 @@ def regex_escape(string, re_type='python'):
|
|
|
216
251
|
|
|
217
252
|
|
|
218
253
|
def from_yaml(data):
|
|
219
|
-
if
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
254
|
+
if data is None:
|
|
255
|
+
return None
|
|
256
|
+
|
|
257
|
+
if isinstance(data, str):
|
|
258
|
+
return yaml.load(data, Loader=_yaml_loader.AnsibleInstrumentedLoader) # type: ignore[arg-type]
|
|
259
|
+
|
|
260
|
+
display.deprecated(f"The from_yaml filter ignored non-string input of type {native_type_name(data)!r}.", version='2.23', obj=data)
|
|
226
261
|
return data
|
|
227
262
|
|
|
228
263
|
|
|
229
264
|
def from_yaml_all(data):
|
|
230
|
-
if
|
|
231
|
-
#
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
265
|
+
if data is None:
|
|
266
|
+
return [] # backward compatibility; ensure consistent result between classic/native Jinja for None/empty string input
|
|
267
|
+
|
|
268
|
+
if isinstance(data, str):
|
|
269
|
+
return yaml.load_all(data, Loader=_yaml_loader.AnsibleInstrumentedLoader) # type: ignore[arg-type]
|
|
270
|
+
|
|
271
|
+
display.deprecated(f"The from_yaml_all filter ignored non-string input of type {native_type_name(data)!r}.", version='2.23', obj=data)
|
|
237
272
|
return data
|
|
238
273
|
|
|
239
274
|
|
|
@@ -291,26 +326,10 @@ def get_encrypted_password(password, hashtype='sha512', salt=None, salt_size=Non
|
|
|
291
326
|
|
|
292
327
|
hashtype = passlib_mapping.get(hashtype, hashtype)
|
|
293
328
|
|
|
294
|
-
unknown_passlib_hashtype = False
|
|
295
329
|
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
|
-
)
|
|
330
|
+
raise AnsibleFilterError(f"{hashtype} is not in the list of supported passlib algorithms: {', '.join(passlib_mapping)}")
|
|
302
331
|
|
|
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
|
|
332
|
+
return do_encrypt(password, hashtype, salt=salt, salt_size=salt_size, rounds=rounds, ident=ident)
|
|
314
333
|
|
|
315
334
|
|
|
316
335
|
def to_uuid(string, namespace=UUID_NAMESPACE_ANSIBLE):
|
|
@@ -324,19 +343,21 @@ def to_uuid(string, namespace=UUID_NAMESPACE_ANSIBLE):
|
|
|
324
343
|
return to_text(uuid.uuid5(uuid_namespace, to_native(string, errors='surrogate_or_strict')))
|
|
325
344
|
|
|
326
345
|
|
|
327
|
-
|
|
346
|
+
@accept_args_markers
|
|
347
|
+
def mandatory(a: object, msg: str | None = None) -> object:
|
|
328
348
|
"""Make a variable mandatory."""
|
|
329
|
-
|
|
349
|
+
# DTFIX-FUTURE: deprecate this filter; there are much better ways via undef, etc...
|
|
350
|
+
# also remember to remove unit test checking for _undefined_name
|
|
351
|
+
if isinstance(a, UndefinedMarker):
|
|
352
|
+
if msg is not None:
|
|
353
|
+
raise AnsibleFilterError(to_text(msg))
|
|
330
354
|
|
|
331
|
-
if isinstance(a, Undefined):
|
|
332
355
|
if a._undefined_name is not None:
|
|
333
|
-
name =
|
|
356
|
+
name = f'{to_text(a._undefined_name)!r} '
|
|
334
357
|
else:
|
|
335
358
|
name = ''
|
|
336
359
|
|
|
337
|
-
|
|
338
|
-
raise AnsibleFilterError(to_native(msg))
|
|
339
|
-
raise AnsibleFilterError("Mandatory variable %s not defined." % name)
|
|
360
|
+
raise AnsibleFilterError(f"Mandatory variable {name}not defined.")
|
|
340
361
|
|
|
341
362
|
return a
|
|
342
363
|
|
|
@@ -350,9 +371,6 @@ def combine(*terms, **kwargs):
|
|
|
350
371
|
# allow the user to do `[dict1, dict2, ...] | combine`
|
|
351
372
|
dictionaries = flatten(terms, levels=1)
|
|
352
373
|
|
|
353
|
-
# recursively check that every elements are defined (for jinja2)
|
|
354
|
-
recursive_check_defined(dictionaries)
|
|
355
|
-
|
|
356
374
|
if not dictionaries:
|
|
357
375
|
return {}
|
|
358
376
|
|
|
@@ -398,6 +416,13 @@ def comment(text, style='plain', **kw):
|
|
|
398
416
|
}
|
|
399
417
|
}
|
|
400
418
|
|
|
419
|
+
if style not in comment_styles:
|
|
420
|
+
raise AnsibleTemplatePluginError(
|
|
421
|
+
message=f"Invalid style {style!r}.",
|
|
422
|
+
help_text=f"Available styles: {', '.join(comment_styles)}",
|
|
423
|
+
obj=style,
|
|
424
|
+
)
|
|
425
|
+
|
|
401
426
|
# Pointer to the right comment type
|
|
402
427
|
style_params = comment_styles[style]
|
|
403
428
|
|
|
@@ -458,7 +483,7 @@ def comment(text, style='plain', **kw):
|
|
|
458
483
|
|
|
459
484
|
|
|
460
485
|
@pass_environment
|
|
461
|
-
def extract(environment, item, container, morekeys=None):
|
|
486
|
+
def extract(environment: Environment, item, container, morekeys=None):
|
|
462
487
|
if morekeys is None:
|
|
463
488
|
keys = [item]
|
|
464
489
|
elif isinstance(morekeys, list):
|
|
@@ -467,18 +492,28 @@ def extract(environment, item, container, morekeys=None):
|
|
|
467
492
|
keys = [item, morekeys]
|
|
468
493
|
|
|
469
494
|
value = container
|
|
495
|
+
|
|
470
496
|
for key in keys:
|
|
471
|
-
|
|
497
|
+
try:
|
|
498
|
+
value = environment.getitem(value, key)
|
|
499
|
+
except MarkerError as ex:
|
|
500
|
+
value = ex.source
|
|
472
501
|
|
|
473
502
|
return value
|
|
474
503
|
|
|
475
504
|
|
|
476
|
-
def b64encode(string, encoding='utf-8'):
|
|
477
|
-
|
|
505
|
+
def b64encode(string, encoding='utf-8', urlsafe=False):
|
|
506
|
+
func = base64.b64encode
|
|
507
|
+
if urlsafe:
|
|
508
|
+
func = base64.urlsafe_b64encode
|
|
509
|
+
return to_text(func(to_bytes(string, encoding=encoding, errors='surrogate_or_strict')))
|
|
478
510
|
|
|
479
511
|
|
|
480
|
-
def b64decode(string, encoding='utf-8'):
|
|
481
|
-
|
|
512
|
+
def b64decode(string, encoding='utf-8', urlsafe=False):
|
|
513
|
+
func = base64.b64decode
|
|
514
|
+
if urlsafe:
|
|
515
|
+
func = base64.urlsafe_b64decode
|
|
516
|
+
return to_text(func(to_bytes(string, errors='surrogate_or_strict')), encoding=encoding)
|
|
482
517
|
|
|
483
518
|
|
|
484
519
|
def flatten(mylist, levels=None, skip_nulls=True):
|
|
@@ -503,14 +538,14 @@ def flatten(mylist, levels=None, skip_nulls=True):
|
|
|
503
538
|
|
|
504
539
|
|
|
505
540
|
def subelements(obj, subelements, skip_missing=False):
|
|
506
|
-
|
|
541
|
+
"""Accepts a dict or list of dicts, and a dotted accessor and produces a product
|
|
507
542
|
of the element and the results of the dotted accessor
|
|
508
543
|
|
|
509
544
|
>>> obj = [{"name": "alice", "groups": ["wheel"], "authorized": ["/tmp/alice/onekey.pub"]}]
|
|
510
545
|
>>> subelements(obj, 'groups')
|
|
511
546
|
[({'name': 'alice', 'groups': ['wheel'], 'authorized': ['/tmp/alice/onekey.pub']}, 'wheel')]
|
|
512
547
|
|
|
513
|
-
|
|
548
|
+
"""
|
|
514
549
|
if isinstance(obj, dict):
|
|
515
550
|
element_list = list(obj.values())
|
|
516
551
|
elif isinstance(obj, list):
|
|
@@ -523,7 +558,7 @@ def subelements(obj, subelements, skip_missing=False):
|
|
|
523
558
|
elif isinstance(subelements, string_types):
|
|
524
559
|
subelement_list = subelements.split('.')
|
|
525
560
|
else:
|
|
526
|
-
raise
|
|
561
|
+
raise AnsibleTypeError('subelements must be a list or a string')
|
|
527
562
|
|
|
528
563
|
results = []
|
|
529
564
|
|
|
@@ -537,10 +572,10 @@ def subelements(obj, subelements, skip_missing=False):
|
|
|
537
572
|
values = []
|
|
538
573
|
break
|
|
539
574
|
raise AnsibleFilterError("could not find %r key in iterated item %r" % (subelement, values))
|
|
540
|
-
except TypeError:
|
|
541
|
-
raise
|
|
575
|
+
except TypeError as ex:
|
|
576
|
+
raise AnsibleTypeError("the key %s should point to a dictionary, got '%s'" % (subelement, values)) from ex
|
|
542
577
|
if not isinstance(values, list):
|
|
543
|
-
raise
|
|
578
|
+
raise AnsibleTypeError("the key %r should point to a list, got %r" % (subelement, values))
|
|
544
579
|
|
|
545
580
|
for value in values:
|
|
546
581
|
results.append((element, value))
|
|
@@ -549,11 +584,11 @@ def subelements(obj, subelements, skip_missing=False):
|
|
|
549
584
|
|
|
550
585
|
|
|
551
586
|
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
|
|
587
|
+
""" takes a dictionary and transforms it into a list of dictionaries,
|
|
588
|
+
with each having a 'key' and 'value' keys that correspond to the keys and values of the original """
|
|
554
589
|
|
|
555
590
|
if not isinstance(mydict, Mapping):
|
|
556
|
-
raise
|
|
591
|
+
raise AnsibleTypeError("dict2items requires a dictionary, got %s instead." % type(mydict))
|
|
557
592
|
|
|
558
593
|
ret = []
|
|
559
594
|
for key in mydict:
|
|
@@ -562,31 +597,31 @@ def dict_to_list_of_dict_key_value_elements(mydict, key_name='key', value_name='
|
|
|
562
597
|
|
|
563
598
|
|
|
564
599
|
def list_of_dict_key_value_elements_to_dict(mylist, key_name='key', value_name='value'):
|
|
565
|
-
|
|
566
|
-
effectively as the reverse of dict2items
|
|
600
|
+
""" takes a list of dicts with each having a 'key' and 'value' keys, and transforms the list into a dictionary,
|
|
601
|
+
effectively as the reverse of dict2items """
|
|
567
602
|
|
|
568
603
|
if not is_sequence(mylist):
|
|
569
|
-
raise
|
|
604
|
+
raise AnsibleTypeError("items2dict requires a list, got %s instead." % type(mylist))
|
|
570
605
|
|
|
571
606
|
try:
|
|
572
607
|
return dict((item[key_name], item[value_name]) for item in mylist)
|
|
573
608
|
except KeyError:
|
|
574
|
-
raise
|
|
609
|
+
raise AnsibleTypeError(
|
|
575
610
|
"items2dict requires each dictionary in the list to contain the keys '%s' and '%s', got %s instead."
|
|
576
611
|
% (key_name, value_name, mylist)
|
|
577
612
|
)
|
|
578
613
|
except TypeError:
|
|
579
|
-
raise
|
|
614
|
+
raise AnsibleTypeError("items2dict requires a list of dictionaries, got %s instead." % mylist)
|
|
580
615
|
|
|
581
616
|
|
|
582
617
|
def path_join(paths):
|
|
583
|
-
|
|
584
|
-
of the different members
|
|
618
|
+
""" takes a sequence or a string, and return a concatenation
|
|
619
|
+
of the different members """
|
|
585
620
|
if isinstance(paths, string_types):
|
|
586
621
|
return os.path.join(paths)
|
|
587
622
|
if is_sequence(paths):
|
|
588
623
|
return os.path.join(*paths)
|
|
589
|
-
raise
|
|
624
|
+
raise AnsibleTypeError("|path_join expects string or sequence, got %s instead." % type(paths))
|
|
590
625
|
|
|
591
626
|
|
|
592
627
|
def commonpath(paths):
|
|
@@ -599,13 +634,92 @@ def commonpath(paths):
|
|
|
599
634
|
:rtype: str
|
|
600
635
|
"""
|
|
601
636
|
if not is_sequence(paths):
|
|
602
|
-
raise
|
|
637
|
+
raise AnsibleTypeError("|commonpath expects sequence, got %s instead." % type(paths))
|
|
603
638
|
|
|
604
639
|
return os.path.commonpath(paths)
|
|
605
640
|
|
|
606
641
|
|
|
642
|
+
class GroupTuple(t.NamedTuple):
|
|
643
|
+
"""
|
|
644
|
+
Custom named tuple for the groupby filter with a public interface; silently ignored by unknown type checks.
|
|
645
|
+
This matches the internal implementation of the _GroupTuple returned by Jinja's built-in groupby filter.
|
|
646
|
+
"""
|
|
647
|
+
|
|
648
|
+
grouper: t.Any
|
|
649
|
+
list: list[t.Any]
|
|
650
|
+
|
|
651
|
+
def __repr__(self) -> str:
|
|
652
|
+
return tuple.__repr__(self)
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
_lazy_containers.register_known_types(GroupTuple)
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
@pass_environment
|
|
659
|
+
def _cleansed_groupby(*args, **kwargs):
|
|
660
|
+
res = sync_do_groupby(*args, **kwargs)
|
|
661
|
+
res = [GroupTuple(grouper=g.grouper, list=g.list) for g in res]
|
|
662
|
+
|
|
663
|
+
return res
|
|
664
|
+
|
|
665
|
+
# DTFIX-FUTURE: make these dumb wrappers more dynamic
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
@accept_args_markers
|
|
669
|
+
def ansible_default(
|
|
670
|
+
value: t.Any,
|
|
671
|
+
default_value: t.Any = '',
|
|
672
|
+
boolean: bool = False,
|
|
673
|
+
) -> t.Any:
|
|
674
|
+
"""Updated `default` filter that only coalesces classic undefined objects; other Undefined-derived types (eg, ErrorMarker) pass through."""
|
|
675
|
+
validate_arg_type('boolean', boolean, bool)
|
|
676
|
+
|
|
677
|
+
if isinstance(value, UndefinedMarker):
|
|
678
|
+
return default_value
|
|
679
|
+
|
|
680
|
+
if boolean and not value:
|
|
681
|
+
return default_value
|
|
682
|
+
|
|
683
|
+
return value
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
@accept_lazy_markers
|
|
687
|
+
@functools.wraps(do_map)
|
|
688
|
+
def wrapped_map(*args, **kwargs) -> t.Any:
|
|
689
|
+
return do_map(*args, **kwargs)
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
@accept_lazy_markers
|
|
693
|
+
@functools.wraps(do_select)
|
|
694
|
+
def wrapped_select(*args, **kwargs) -> t.Any:
|
|
695
|
+
return do_select(*args, **kwargs)
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
@accept_lazy_markers
|
|
699
|
+
@functools.wraps(do_selectattr)
|
|
700
|
+
def wrapped_selectattr(*args, **kwargs) -> t.Any:
|
|
701
|
+
return do_selectattr(*args, **kwargs)
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
@accept_lazy_markers
|
|
705
|
+
@functools.wraps(do_reject)
|
|
706
|
+
def wrapped_reject(*args, **kwargs) -> t.Any:
|
|
707
|
+
return do_reject(*args, **kwargs)
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
@accept_lazy_markers
|
|
711
|
+
@functools.wraps(do_rejectattr)
|
|
712
|
+
def wrapped_rejectattr(*args, **kwargs) -> t.Any:
|
|
713
|
+
return do_rejectattr(*args, **kwargs)
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
@accept_args_markers
|
|
717
|
+
def type_debug(obj: object) -> str:
|
|
718
|
+
return native_type_name(obj)
|
|
719
|
+
|
|
720
|
+
|
|
607
721
|
class FilterModule(object):
|
|
608
|
-
|
|
722
|
+
""" Ansible core jinja2 filters """
|
|
609
723
|
|
|
610
724
|
def filters(self):
|
|
611
725
|
return {
|
|
@@ -619,7 +733,7 @@ class FilterModule(object):
|
|
|
619
733
|
# json
|
|
620
734
|
'to_json': to_json,
|
|
621
735
|
'to_nice_json': to_nice_json,
|
|
622
|
-
'from_json':
|
|
736
|
+
'from_json': from_json,
|
|
623
737
|
|
|
624
738
|
# yaml
|
|
625
739
|
'to_yaml': to_yaml,
|
|
@@ -686,7 +800,7 @@ class FilterModule(object):
|
|
|
686
800
|
'comment': comment,
|
|
687
801
|
|
|
688
802
|
# debug
|
|
689
|
-
'type_debug':
|
|
803
|
+
'type_debug': type_debug,
|
|
690
804
|
|
|
691
805
|
# Data structures
|
|
692
806
|
'combine': combine,
|
|
@@ -696,4 +810,15 @@ class FilterModule(object):
|
|
|
696
810
|
'items2dict': list_of_dict_key_value_elements_to_dict,
|
|
697
811
|
'subelements': subelements,
|
|
698
812
|
'split': partial(unicode_wrap, text_type.split),
|
|
813
|
+
# FDI038 - replace this with a standard type compat shim
|
|
814
|
+
'groupby': _cleansed_groupby,
|
|
815
|
+
|
|
816
|
+
# Jinja builtins that need special arg handling
|
|
817
|
+
'd': ansible_default, # replaces the implementation instead of wrapping it
|
|
818
|
+
'default': ansible_default, # replaces the implementation instead of wrapping it
|
|
819
|
+
'map': wrapped_map,
|
|
820
|
+
'select': wrapped_select,
|
|
821
|
+
'selectattr': wrapped_selectattr,
|
|
822
|
+
'reject': wrapped_reject,
|
|
823
|
+
'rejectattr': wrapped_rejectattr,
|
|
699
824
|
}
|