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
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Lossy best-effort serialization for Ansible variables.
|
|
3
|
+
Default profile for the `to_json` filter.
|
|
4
|
+
Deserialization behavior is identical to JSONDecoder, except known Ansible custom serialization markers will raise an error.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations as _annotations
|
|
8
|
+
|
|
9
|
+
import datetime as _datetime
|
|
10
|
+
import functools as _functools
|
|
11
|
+
|
|
12
|
+
from ... import _datatag
|
|
13
|
+
from .. import _profiles
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class _Profile(_profiles._JSONSerializationProfile["Encoder", "Decoder"]):
|
|
17
|
+
@classmethod
|
|
18
|
+
def post_init(cls) -> None:
|
|
19
|
+
cls.serialize_map = {
|
|
20
|
+
# DTFIX5: support serialization of every type that is supported in the Ansible variable type system
|
|
21
|
+
set: cls.serialize_as_list,
|
|
22
|
+
tuple: cls.serialize_as_list,
|
|
23
|
+
_datetime.date: cls.serialize_as_isoformat,
|
|
24
|
+
_datetime.time: cls.serialize_as_isoformat,
|
|
25
|
+
_datetime.datetime: cls.serialize_as_isoformat,
|
|
26
|
+
# bytes intentionally omitted as they are not a supported variable type, they were not originally supported by the old AnsibleJSONEncoder
|
|
27
|
+
_datatag._AnsibleTaggedDate: cls.discard_tags,
|
|
28
|
+
_datatag._AnsibleTaggedTime: cls.discard_tags,
|
|
29
|
+
_datatag._AnsibleTaggedDateTime: cls.discard_tags,
|
|
30
|
+
_datatag._AnsibleTaggedStr: cls.discard_tags,
|
|
31
|
+
_datatag._AnsibleTaggedInt: cls.discard_tags,
|
|
32
|
+
_datatag._AnsibleTaggedFloat: cls.discard_tags,
|
|
33
|
+
_datatag._AnsibleTaggedSet: cls.discard_tags,
|
|
34
|
+
_datatag._AnsibleTaggedList: cls.discard_tags,
|
|
35
|
+
_datatag._AnsibleTaggedTuple: cls.discard_tags,
|
|
36
|
+
_datatag._AnsibleTaggedDict: cls.discard_tags,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
cls.deserialize_map = {
|
|
40
|
+
'__ansible_unsafe': _functools.partial(cls.unsupported_target_type_error, '__ansible_unsafe'),
|
|
41
|
+
'__ansible_vault': _functools.partial(cls.unsupported_target_type_error, '__ansible_vault'),
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
cls.handle_key = cls._handle_key_str_fallback # type: ignore[method-assign] # legacy stdlib-compatible key behavior
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Encoder(_profiles.AnsibleProfileJSONEncoder):
|
|
48
|
+
_profile = _Profile
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class Decoder(_profiles.AnsibleProfileJSONDecoder):
|
|
52
|
+
_profile = _Profile
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Message contract definitions for various target-side types.
|
|
3
|
+
|
|
4
|
+
These types and the wire format they implement are currently considered provisional and subject to change without notice.
|
|
5
|
+
A future release will remove the provisional status.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations as _annotations
|
|
9
|
+
|
|
10
|
+
import dataclasses as _dataclasses
|
|
11
|
+
import enum as _enum
|
|
12
|
+
import sys as _sys
|
|
13
|
+
import typing as _t
|
|
14
|
+
|
|
15
|
+
from ansible.module_utils._internal import _datatag, _dataclass_validation
|
|
16
|
+
|
|
17
|
+
if _sys.version_info >= (3, 10):
|
|
18
|
+
# Using slots for reduced memory usage and improved performance.
|
|
19
|
+
_dataclass_kwargs = dict(frozen=True, kw_only=True, slots=True)
|
|
20
|
+
else:
|
|
21
|
+
# deprecated: description='always use dataclass slots and keyword-only args' python_version='3.9'
|
|
22
|
+
_dataclass_kwargs = dict(frozen=True)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class PluginType(_datatag.AnsibleSerializableEnum):
|
|
26
|
+
"""Enum of Ansible plugin types."""
|
|
27
|
+
|
|
28
|
+
ACTION = _enum.auto()
|
|
29
|
+
BECOME = _enum.auto()
|
|
30
|
+
CACHE = _enum.auto()
|
|
31
|
+
CALLBACK = _enum.auto()
|
|
32
|
+
CLICONF = _enum.auto()
|
|
33
|
+
CONNECTION = _enum.auto()
|
|
34
|
+
DOC_FRAGMENTS = _enum.auto()
|
|
35
|
+
FILTER = _enum.auto()
|
|
36
|
+
HTTPAPI = _enum.auto()
|
|
37
|
+
INVENTORY = _enum.auto()
|
|
38
|
+
LOOKUP = _enum.auto()
|
|
39
|
+
MODULE = _enum.auto()
|
|
40
|
+
NETCONF = _enum.auto()
|
|
41
|
+
SHELL = _enum.auto()
|
|
42
|
+
STRATEGY = _enum.auto()
|
|
43
|
+
TERMINAL = _enum.auto()
|
|
44
|
+
TEST = _enum.auto()
|
|
45
|
+
VARS = _enum.auto()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@_dataclasses.dataclass(**_dataclass_kwargs)
|
|
49
|
+
class PluginInfo(_datatag.AnsibleSerializableDataclass):
|
|
50
|
+
"""Information about a loaded plugin."""
|
|
51
|
+
|
|
52
|
+
resolved_name: _t.Optional[str]
|
|
53
|
+
"""The resolved canonical plugin name; always fully-qualified for collection plugins."""
|
|
54
|
+
|
|
55
|
+
type: _t.Optional[PluginType]
|
|
56
|
+
"""The plugin type."""
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@_dataclasses.dataclass(**_dataclass_kwargs)
|
|
60
|
+
class EventChain(_datatag.AnsibleSerializableDataclass):
|
|
61
|
+
"""A chain used to link one event to another."""
|
|
62
|
+
|
|
63
|
+
_validation_auto_enabled = False
|
|
64
|
+
|
|
65
|
+
def __post_init__(self): ... # required for deferred dataclass validation
|
|
66
|
+
|
|
67
|
+
msg_reason: str
|
|
68
|
+
traceback_reason: str
|
|
69
|
+
event: Event
|
|
70
|
+
follow: bool = True
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@_dataclasses.dataclass(**_dataclass_kwargs)
|
|
74
|
+
class Event(_datatag.AnsibleSerializableDataclass):
|
|
75
|
+
"""Base class for an error/warning/deprecation event with optional chain (from an exception __cause__ chain) and an optional traceback."""
|
|
76
|
+
|
|
77
|
+
_validation_auto_enabled = False
|
|
78
|
+
|
|
79
|
+
def __post_init__(self): ... # required for deferred dataclass validation
|
|
80
|
+
|
|
81
|
+
msg: str
|
|
82
|
+
formatted_source_context: _t.Optional[str] = None
|
|
83
|
+
formatted_traceback: _t.Optional[str] = None
|
|
84
|
+
help_text: _t.Optional[str] = None
|
|
85
|
+
chain: _t.Optional[EventChain] = None
|
|
86
|
+
events: _t.Optional[_t.Tuple[Event, ...]] = None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
_dataclass_validation.inject_post_init_validation(EventChain, EventChain._validation_allow_subclasses)
|
|
90
|
+
_dataclass_validation.inject_post_init_validation(Event, Event._validation_allow_subclasses)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@_dataclasses.dataclass(**_dataclass_kwargs)
|
|
94
|
+
class SummaryBase(_datatag.AnsibleSerializableDataclass):
|
|
95
|
+
"""Base class for an error/warning/deprecation summary with details (possibly derived from an exception __cause__ chain) and an optional traceback."""
|
|
96
|
+
|
|
97
|
+
event: Event
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@_dataclasses.dataclass(**_dataclass_kwargs)
|
|
101
|
+
class ErrorSummary(SummaryBase):
|
|
102
|
+
"""Error summary with details (possibly derived from an exception __cause__ chain) and an optional traceback."""
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@_dataclasses.dataclass(**_dataclass_kwargs)
|
|
106
|
+
class WarningSummary(SummaryBase):
|
|
107
|
+
"""Warning summary with details (possibly derived from an exception __cause__ chain) and an optional traceback."""
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@_dataclasses.dataclass(**_dataclass_kwargs)
|
|
111
|
+
class DeprecationSummary(WarningSummary):
|
|
112
|
+
"""Deprecation summary with details (possibly derived from an exception __cause__ chain) and an optional traceback."""
|
|
113
|
+
|
|
114
|
+
deprecator: _t.Optional[PluginInfo] = None
|
|
115
|
+
"""
|
|
116
|
+
The identifier for the content which is being deprecated.
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
date: _t.Optional[str] = None
|
|
120
|
+
"""
|
|
121
|
+
The date after which a new release of `deprecator` will remove the feature described by `msg`.
|
|
122
|
+
Ignored if `deprecator` is not provided.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
version: _t.Optional[str] = None
|
|
126
|
+
"""
|
|
127
|
+
The version of `deprecator` which will remove the feature described by `msg`.
|
|
128
|
+
Ignored if `deprecator` is not provided.
|
|
129
|
+
Ignored if `date` is provided.
|
|
130
|
+
"""
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Infrastructure for patching callables with alternative implementations as needed based on patch-specific test criteria."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import abc
|
|
6
|
+
import typing as t
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@t.runtime_checkable
|
|
10
|
+
class PatchedTarget(t.Protocol):
|
|
11
|
+
"""Runtime-checkable protocol that allows identification of a patched function via `isinstance`."""
|
|
12
|
+
|
|
13
|
+
unpatched_implementation: t.Callable
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CallablePatch(abc.ABC):
|
|
17
|
+
"""Base class for patches that provides abstractions for validation of broken behavior, installation of patches, and validation of fixed behavior."""
|
|
18
|
+
|
|
19
|
+
target_container: t.ClassVar
|
|
20
|
+
"""The module object containing the function to be patched."""
|
|
21
|
+
|
|
22
|
+
target_attribute: t.ClassVar[str]
|
|
23
|
+
"""The attribute name on the target module to patch."""
|
|
24
|
+
|
|
25
|
+
unpatched_implementation: t.ClassVar[t.Callable]
|
|
26
|
+
"""The unpatched implementation. Available only after the patch has been applied."""
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
@abc.abstractmethod
|
|
30
|
+
def is_patch_needed(cls) -> bool:
|
|
31
|
+
"""Returns True if the patch is currently needed. Returns False if the original target does not need the patch or the patch has already been applied."""
|
|
32
|
+
|
|
33
|
+
@abc.abstractmethod
|
|
34
|
+
def __call__(self, *args, **kwargs) -> t.Any:
|
|
35
|
+
"""Invoke the patched or original implementation, depending on whether the patch has been applied or not."""
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def is_patched(cls) -> bool:
|
|
39
|
+
"""Returns True if the patch has been applied, otherwise returns False."""
|
|
40
|
+
return isinstance(cls.get_current_implementation(), PatchedTarget) # using a protocol lets us be more resilient to module unload weirdness
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def get_current_implementation(cls) -> t.Any:
|
|
44
|
+
"""Get the current (possibly patched) implementation from the patch target container."""
|
|
45
|
+
return getattr(cls.target_container, cls.target_attribute)
|
|
46
|
+
|
|
47
|
+
@classmethod
|
|
48
|
+
def patch(cls) -> None:
|
|
49
|
+
"""Idempotently apply this patch (if needed)."""
|
|
50
|
+
if cls.is_patched():
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
cls.unpatched_implementation = cls.get_current_implementation()
|
|
54
|
+
|
|
55
|
+
if not cls.is_patch_needed():
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
# __call__ requires an instance (otherwise it'll be __new__)
|
|
59
|
+
setattr(cls.target_container, cls.target_attribute, cls())
|
|
60
|
+
|
|
61
|
+
if not cls.is_patch_needed():
|
|
62
|
+
return
|
|
63
|
+
|
|
64
|
+
setattr(cls.target_container, cls.target_attribute, cls.unpatched_implementation)
|
|
65
|
+
|
|
66
|
+
raise RuntimeError(f"Validation of '{cls.target_container.__name__}.{cls.target_attribute}' failed after patching.")
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Patches for builtin `dataclasses` module."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import dataclasses
|
|
6
|
+
import sys
|
|
7
|
+
import typing as t
|
|
8
|
+
|
|
9
|
+
from . import CallablePatch
|
|
10
|
+
|
|
11
|
+
# trigger the bug by exposing typing.ClassVar via a module reference that is not `typing`
|
|
12
|
+
_ts = sys.modules[__name__]
|
|
13
|
+
ClassVar = t.ClassVar
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DataclassesIsTypePatch(CallablePatch):
|
|
17
|
+
"""Patch broken ClassVar support in dataclasses when ClassVar is accessed via a module other than `typing`."""
|
|
18
|
+
|
|
19
|
+
target_container: t.ClassVar = dataclasses
|
|
20
|
+
target_attribute = '_is_type'
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def is_patch_needed(cls) -> bool:
|
|
24
|
+
@dataclasses.dataclass
|
|
25
|
+
class CheckClassVar:
|
|
26
|
+
# this is the broken case requiring patching: ClassVar dot-referenced from a module that is not `typing` is treated as an instance field
|
|
27
|
+
# DTFIX-FUTURE: file/link CPython bug report, deprecate this patch if/when it's fixed in CPython
|
|
28
|
+
a_classvar: _ts.ClassVar[int] # type: ignore[name-defined]
|
|
29
|
+
a_field: int
|
|
30
|
+
|
|
31
|
+
return len(dataclasses.fields(CheckClassVar)) != 1
|
|
32
|
+
|
|
33
|
+
def __call__(self, annotation, cls, a_module, a_type, is_type_predicate) -> bool:
|
|
34
|
+
"""
|
|
35
|
+
This is a patched copy of `_is_type` from dataclasses.py in Python 3.13.
|
|
36
|
+
It eliminates the redundant source module reference equality check for the ClassVar type that triggers the bug.
|
|
37
|
+
"""
|
|
38
|
+
match = dataclasses._MODULE_IDENTIFIER_RE.match(annotation) # type: ignore[attr-defined]
|
|
39
|
+
if match:
|
|
40
|
+
ns = None
|
|
41
|
+
module_name = match.group(1)
|
|
42
|
+
if not module_name:
|
|
43
|
+
# No module name, assume the class's module did
|
|
44
|
+
# "from dataclasses import InitVar".
|
|
45
|
+
ns = sys.modules.get(cls.__module__).__dict__
|
|
46
|
+
else:
|
|
47
|
+
# Look up module_name in the class's module.
|
|
48
|
+
module = sys.modules.get(cls.__module__)
|
|
49
|
+
if module and module.__dict__.get(module_name): # this is the patched line; removed `is a_module`
|
|
50
|
+
ns = sys.modules.get(a_type.__module__).__dict__
|
|
51
|
+
if ns and is_type_predicate(ns.get(match.group(2)), a_module):
|
|
52
|
+
return True
|
|
53
|
+
return False
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Patches for builtin socket module."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import contextlib
|
|
6
|
+
import socket
|
|
7
|
+
import typing as t
|
|
8
|
+
|
|
9
|
+
from . import CallablePatch
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class _CustomInt(int):
|
|
13
|
+
"""Wrapper around `int` to test if subclasses are accepted."""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class GetAddrInfoPatch(CallablePatch):
|
|
17
|
+
"""Patch `socket.getaddrinfo` so that its `port` arg works with `int` subclasses."""
|
|
18
|
+
|
|
19
|
+
target_container: t.ClassVar = socket
|
|
20
|
+
target_attribute = 'getaddrinfo'
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def is_patch_needed(cls) -> bool:
|
|
24
|
+
with contextlib.suppress(OSError):
|
|
25
|
+
socket.getaddrinfo('127.0.0.1', _CustomInt(22))
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
return True
|
|
29
|
+
|
|
30
|
+
def __call__(self, host, port, *args, **kwargs) -> t.Any:
|
|
31
|
+
if type(port) is not int and isinstance(port, int): # pylint: disable=unidiomatic-typecheck
|
|
32
|
+
port = int(port)
|
|
33
|
+
|
|
34
|
+
return type(self).unpatched_implementation(host, port, *args, **kwargs)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""Patches for the builtin `sys` module."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import contextlib
|
|
6
|
+
import sys
|
|
7
|
+
import typing as t
|
|
8
|
+
|
|
9
|
+
from . import CallablePatch
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class _CustomStr(str):
|
|
13
|
+
"""Wrapper around `str` to test if subclasses are accepted."""
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SysInternPatch(CallablePatch):
|
|
17
|
+
"""Patch `sys.intern` so that subclasses of `str` are accepted."""
|
|
18
|
+
|
|
19
|
+
target_container: t.ClassVar = sys
|
|
20
|
+
target_attribute = 'intern'
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def is_patch_needed(cls) -> bool:
|
|
24
|
+
with contextlib.suppress(TypeError):
|
|
25
|
+
sys.intern(_CustomStr("x"))
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
return True
|
|
29
|
+
|
|
30
|
+
def __call__(self, value: str):
|
|
31
|
+
if type(value) is not str and isinstance(value, str): # pylint: disable=unidiomatic-typecheck
|
|
32
|
+
value = str(value)
|
|
33
|
+
|
|
34
|
+
return type(self).unpatched_implementation(value)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing as t
|
|
4
|
+
|
|
5
|
+
from . import _messages
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class HasPluginInfo(t.Protocol):
|
|
9
|
+
"""Protocol to type-annotate and expose PluginLoader-set values."""
|
|
10
|
+
|
|
11
|
+
@property
|
|
12
|
+
def ansible_name(self) -> str | None:
|
|
13
|
+
"""Fully resolved plugin name."""
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def plugin_type(self) -> str:
|
|
17
|
+
"""Plugin type name."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_plugin_info(value: HasPluginInfo) -> _messages.PluginInfo:
|
|
21
|
+
"""Utility method that returns a `PluginInfo` from an object implementing the `HasPluginInfo` protocol."""
|
|
22
|
+
return _messages.PluginInfo(
|
|
23
|
+
resolved_name=value.ansible_name,
|
|
24
|
+
type=normalize_plugin_type(value.plugin_type),
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def normalize_plugin_type(value: str) -> _messages.PluginType | None:
|
|
29
|
+
"""Normalize value and return it as a PluginType, or None if the value does match any known plugin type."""
|
|
30
|
+
value = value.lower()
|
|
31
|
+
|
|
32
|
+
if value == 'modules':
|
|
33
|
+
value = 'module'
|
|
34
|
+
|
|
35
|
+
try:
|
|
36
|
+
return _messages.PluginType(value)
|
|
37
|
+
except ValueError:
|
|
38
|
+
return None
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from __future__ import annotations as _annotations
|
|
2
|
+
|
|
3
|
+
import inspect as _inspect
|
|
4
|
+
import typing as _t
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def caller_frame() -> _inspect.FrameInfo | None:
|
|
8
|
+
"""Return the caller stack frame, skipping any marked with the `_skip_stackwalk` local."""
|
|
9
|
+
_skip_stackwalk = True
|
|
10
|
+
|
|
11
|
+
return next(iter_stack(), None)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def iter_stack() -> _t.Generator[_inspect.FrameInfo]:
|
|
15
|
+
"""Iterate over stack frames, skipping any marked with the `_skip_stackwalk` local."""
|
|
16
|
+
_skip_stackwalk = True
|
|
17
|
+
|
|
18
|
+
for frame_info in _inspect.stack():
|
|
19
|
+
if '_skip_stackwalk' in frame_info.frame.f_locals:
|
|
20
|
+
continue
|
|
21
|
+
|
|
22
|
+
yield frame_info
|
|
File without changes
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Copyright (c) 2024 Ansible Project
|
|
2
|
+
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
|
|
3
|
+
|
|
4
|
+
"""Internal utility code for supporting traceback reporting."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import enum
|
|
9
|
+
import traceback
|
|
10
|
+
|
|
11
|
+
from . import _stack
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TracebackEvent(enum.Enum):
|
|
15
|
+
"""The events for which tracebacks can be enabled."""
|
|
16
|
+
|
|
17
|
+
ERROR = enum.auto()
|
|
18
|
+
WARNING = enum.auto()
|
|
19
|
+
DEPRECATED = enum.auto()
|
|
20
|
+
DEPRECATED_VALUE = enum.auto() # implies DEPRECATED
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def traceback_for() -> list[str]:
|
|
24
|
+
"""Return a list of traceback event names (not enums) which are enabled."""
|
|
25
|
+
return [value.name.lower() for value in TracebackEvent if is_traceback_enabled(value)]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def is_traceback_enabled(event: TracebackEvent) -> bool:
|
|
29
|
+
"""Return True if tracebacks are enabled for the specified event, otherwise return False."""
|
|
30
|
+
return _is_traceback_enabled(event)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def maybe_capture_traceback(msg: str, event: TracebackEvent) -> str | None:
|
|
34
|
+
"""
|
|
35
|
+
Optionally capture a traceback for the current call stack, formatted as a string, if the specified traceback event is enabled.
|
|
36
|
+
Frames marked with the `_skip_stackwalk` local are omitted.
|
|
37
|
+
"""
|
|
38
|
+
_skip_stackwalk = True
|
|
39
|
+
|
|
40
|
+
if not is_traceback_enabled(event):
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
tb_lines = []
|
|
44
|
+
|
|
45
|
+
if frame_info := _stack.caller_frame():
|
|
46
|
+
# DTFIX-FUTURE: rewrite target-side tracebacks to point at controller-side paths?
|
|
47
|
+
tb_lines.append('Traceback (most recent call last):\n')
|
|
48
|
+
tb_lines.extend(traceback.format_stack(frame_info.frame))
|
|
49
|
+
tb_lines.append(f'Message: {msg}\n')
|
|
50
|
+
else:
|
|
51
|
+
tb_lines.append('(frame not found)\n') # pragma: nocover
|
|
52
|
+
|
|
53
|
+
return ''.join(tb_lines)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def maybe_extract_traceback(exception: BaseException, event: TracebackEvent) -> str | None:
|
|
57
|
+
"""Optionally extract a formatted traceback from the given exception, if the specified traceback event is enabled."""
|
|
58
|
+
|
|
59
|
+
if not is_traceback_enabled(event):
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
# deprecated: description='use the single-arg version of format_traceback' python_version='3.9'
|
|
63
|
+
tb_lines = traceback.format_exception(type(exception), exception, exception.__traceback__)
|
|
64
|
+
|
|
65
|
+
return ''.join(tb_lines)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
_module_tracebacks_enabled_events: frozenset[TracebackEvent] | None = None
|
|
69
|
+
"""Cached enabled TracebackEvent values extracted from `_ansible_tracebacks_for` module arg."""
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _is_module_traceback_enabled(event: TracebackEvent) -> bool:
|
|
73
|
+
"""Module utility function to lazily load traceback config and determine if traceback collection is enabled for the specified event."""
|
|
74
|
+
global _module_tracebacks_enabled_events
|
|
75
|
+
|
|
76
|
+
if _module_tracebacks_enabled_events is None:
|
|
77
|
+
try:
|
|
78
|
+
# Suboptimal error handling, but since import order can matter, and this is a critical error path, better to fail silently
|
|
79
|
+
# than to mask the triggering error by issuing a new error/warning here.
|
|
80
|
+
from ..basic import _PARSED_MODULE_ARGS
|
|
81
|
+
|
|
82
|
+
_module_tracebacks_enabled_events = frozenset(
|
|
83
|
+
TracebackEvent[value.upper()] for value in _PARSED_MODULE_ARGS.get('_ansible_tracebacks_for')
|
|
84
|
+
) # type: ignore[union-attr]
|
|
85
|
+
except BaseException:
|
|
86
|
+
return True # if things failed early enough that we can't figure this out, assume we want a traceback for troubleshooting
|
|
87
|
+
|
|
88
|
+
return event in _module_tracebacks_enabled_events
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
_is_traceback_enabled = _is_module_traceback_enabled
|
|
92
|
+
"""Callable to determine if tracebacks are enabled. Overridden on the controller by display. Use `is_traceback_enabled` instead of calling this directly."""
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import keyword
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def validate_collection_name(collection_name: object, name: str = 'collection_name') -> None:
|
|
7
|
+
"""Validate a collection name."""
|
|
8
|
+
if not isinstance(collection_name, str):
|
|
9
|
+
raise TypeError(f"{name} must be {str} instead of {type(collection_name)}")
|
|
10
|
+
|
|
11
|
+
parts = collection_name.split('.')
|
|
12
|
+
|
|
13
|
+
if len(parts) != 2 or not all(part.isidentifier() and not keyword.iskeyword(part) for part in parts):
|
|
14
|
+
raise ValueError(f"{name} must consist of two non-keyword identifiers separated by '.'")
|