ansible-core 2.19.0b3__py3-none-any.whl → 2.19.0b5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ansible/_internal/__init__.py +2 -2
- ansible/_internal/_collection_proxy.py +1 -1
- ansible/_internal/_errors/_alarm_timeout.py +66 -0
- ansible/_internal/_errors/_captured.py +25 -30
- ansible/_internal/_errors/_error_factory.py +89 -0
- ansible/_internal/_errors/_error_utils.py +240 -0
- ansible/_internal/_errors/_task_timeout.py +28 -0
- ansible/_internal/_event_formatting.py +127 -0
- ansible/_internal/_json/__init__.py +6 -6
- ansible/_internal/_json/_profiles/_cache_persistence.py +2 -0
- ansible/_internal/_json/_profiles/_inventory_legacy.py +1 -1
- ansible/_internal/_json/_profiles/_legacy.py +3 -11
- ansible/_internal/_ssh/__init__.py +0 -0
- ansible/_internal/_ssh/_agent_launch.py +91 -0
- ansible/{utils → _internal/_ssh}/_ssh_agent.py +55 -93
- ansible/_internal/_templating/__init__.py +5 -3
- ansible/_internal/_templating/_datatag.py +2 -1
- ansible/_internal/_templating/_engine.py +3 -4
- ansible/_internal/_templating/_jinja_bits.py +21 -16
- ansible/_internal/_templating/_jinja_common.py +18 -27
- ansible/_internal/_templating/_jinja_plugins.py +31 -3
- ansible/_internal/_templating/_lazy_containers.py +5 -5
- ansible/_internal/_templating/_transform.py +20 -19
- ansible/_internal/_templating/_utils.py +1 -1
- ansible/_internal/_testing.py +26 -0
- ansible/_internal/_yaml/_dumper.py +1 -1
- ansible/_internal/_yaml/_errors.py +7 -7
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/true_type.py +1 -1
- ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/unmask.py +1 -1
- ansible/cli/__init__.py +5 -82
- ansible/cli/arguments/option_helpers.py +8 -5
- ansible/cli/doc.py +84 -28
- ansible/cli/inventory.py +1 -1
- ansible/compat/importlib_resources.py +9 -12
- ansible/config/base.yml +27 -23
- ansible/config/manager.py +142 -101
- ansible/constants.py +1 -1
- ansible/errors/__init__.py +96 -49
- ansible/executor/module_common.py +8 -10
- ansible/executor/powershell/async_watchdog.ps1 +2 -2
- ansible/executor/powershell/async_wrapper.ps1 +3 -3
- ansible/executor/powershell/become_wrapper.ps1 +20 -2
- ansible/executor/powershell/bootstrap_wrapper.ps1 +28 -6
- ansible/executor/powershell/coverage_wrapper.ps1 +15 -6
- ansible/executor/powershell/exec_wrapper.ps1 +219 -6
- ansible/executor/powershell/module_manifest.py +52 -0
- ansible/executor/powershell/module_wrapper.ps1 +47 -21
- ansible/executor/powershell/powershell_expand_user.ps1 +20 -0
- ansible/executor/powershell/powershell_mkdtemp.ps1 +17 -0
- ansible/executor/process/worker.py +38 -113
- ansible/executor/task_executor.py +26 -61
- ansible/executor/task_result.py +2 -4
- ansible/galaxy/collection/__init__.py +1 -4
- ansible/inventory/manager.py +1 -0
- ansible/module_utils/_internal/__init__.py +0 -3
- ansible/module_utils/_internal/_ambient_context.py +3 -3
- ansible/module_utils/_internal/_ansiballz.py +4 -2
- ansible/module_utils/_internal/_datatag/__init__.py +20 -14
- ansible/module_utils/_internal/_datatag/_tags.py +2 -2
- ansible/module_utils/_internal/_deprecator.py +66 -48
- ansible/module_utils/_internal/_errors.py +88 -17
- ansible/module_utils/_internal/_event_utils.py +61 -0
- ansible/module_utils/_internal/_json/_profiles/__init__.py +21 -4
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_c2m.py +2 -0
- ansible/module_utils/_internal/_json/_profiles/_module_legacy_m2c.py +2 -0
- ansible/module_utils/_internal/_json/_profiles/_tagless.py +3 -1
- ansible/module_utils/{common/messages.py → _internal/_messages.py} +28 -47
- ansible/module_utils/_internal/_patches/_dataclass_annotation_patch.py +1 -3
- ansible/module_utils/_internal/_plugin_info.py +1 -1
- ansible/module_utils/_internal/_stack.py +22 -0
- ansible/module_utils/_internal/_text_utils.py +6 -0
- ansible/module_utils/_internal/_traceback.py +11 -8
- ansible/module_utils/ansible_release.py +1 -1
- ansible/module_utils/basic.py +49 -15
- ansible/module_utils/common/arg_spec.py +2 -2
- ansible/module_utils/common/collections.py +6 -0
- ansible/module_utils/common/json.py +2 -2
- ansible/module_utils/common/text/converters.py +3 -3
- ansible/module_utils/common/validation.py +1 -1
- ansible/module_utils/common/warnings.py +80 -23
- ansible/module_utils/common/yaml.py +1 -1
- ansible/module_utils/datatag.py +5 -2
- ansible/module_utils/facts/system/distribution.py +16 -3
- ansible/module_utils/facts/virtual/linux.py +2 -2
- ansible/module_utils/parsing/convert_bool.py +6 -0
- ansible/module_utils/service.py +2 -9
- ansible/modules/apt_repository.py +7 -29
- ansible/modules/assemble.py +4 -4
- ansible/modules/async_status.py +13 -11
- ansible/modules/async_wrapper.py +5 -5
- ansible/modules/cron.py +3 -5
- ansible/modules/dnf5.py +15 -22
- ansible/modules/git.py +1 -6
- ansible/modules/hostname.py +0 -1
- ansible/modules/pip.py +2 -4
- ansible/modules/service.py +3 -9
- ansible/modules/sysvinit.py +3 -3
- ansible/parsing/ajson.py +3 -5
- ansible/parsing/dataloader.py +4 -4
- ansible/parsing/mod_args.py +1 -1
- ansible/parsing/plugin_docs.py +2 -2
- ansible/parsing/utils/yaml.py +3 -3
- ansible/parsing/vault/__init__.py +4 -4
- ansible/playbook/playbook_include.py +1 -1
- ansible/playbook/taggable.py +0 -3
- ansible/plugins/__init__.py +0 -25
- ansible/plugins/action/__init__.py +9 -32
- ansible/plugins/action/add_host.py +1 -1
- ansible/plugins/action/assemble.py +8 -16
- ansible/plugins/action/async_status.py +7 -2
- ansible/plugins/action/copy.py +8 -7
- ansible/plugins/action/gather_facts.py +8 -8
- ansible/plugins/action/package.py +5 -8
- ansible/plugins/action/script.py +8 -15
- ansible/plugins/action/service.py +3 -7
- ansible/plugins/action/template.py +6 -8
- ansible/plugins/action/unarchive.py +5 -15
- ansible/plugins/action/uri.py +9 -20
- ansible/plugins/callback/__init__.py +4 -6
- ansible/plugins/callback/junit.py +4 -2
- ansible/plugins/connection/local.py +2 -2
- ansible/plugins/connection/ssh.py +17 -9
- ansible/plugins/connection/winrm.py +5 -2
- ansible/plugins/doc_fragments/constructed.py +2 -2
- ansible/plugins/filter/core.py +13 -6
- ansible/plugins/filter/encryption.py +4 -4
- ansible/plugins/inventory/__init__.py +11 -10
- ansible/plugins/inventory/script.py +1 -1
- ansible/plugins/list.py +69 -16
- ansible/plugins/loader.py +10 -9
- ansible/plugins/lookup/csvfile.py +16 -71
- ansible/plugins/lookup/first_found.py +2 -1
- ansible/plugins/shell/__init__.py +56 -2
- ansible/plugins/shell/powershell.py +66 -9
- ansible/plugins/shell/sh.py +9 -5
- ansible/plugins/test/core.py +21 -15
- ansible/plugins/test/finished.yml +1 -1
- ansible/plugins/test/uri.py +2 -5
- ansible/release.py +1 -1
- ansible/template/__init__.py +30 -2
- ansible/utils/collection_loader/__init__.py +2 -0
- ansible/utils/display.py +107 -128
- ansible/utils/hashing.py +0 -1
- ansible/utils/listify.py +6 -4
- ansible/utils/plugin_docs.py +2 -1
- ansible/utils/unsafe_proxy.py +1 -1
- ansible/vars/hostvars.py +1 -1
- {ansible_core-2.19.0b3.dist-info → ansible_core-2.19.0b5.dist-info}/METADATA +3 -2
- {ansible_core-2.19.0b3.dist-info → ansible_core-2.19.0b5.dist-info}/RECORD +173 -161
- {ansible_core-2.19.0b3.dist-info → ansible_core-2.19.0b5.dist-info}/WHEEL +1 -1
- ansible_test/_data/completion/docker.txt +3 -3
- ansible_test/_data/completion/remote.txt +1 -0
- ansible_test/_data/requirements/sanity.ansible-doc.txt +1 -1
- ansible_test/_data/requirements/sanity.changelog.txt +2 -2
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +4 -4
- ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
- ansible_test/_internal/util.py +20 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg +1 -0
- ansible_test/_util/controller/sanity/pylint/config/ansible-test.cfg +1 -0
- ansible_test/_util/controller/sanity/pylint/config/code-smell.cfg +1 -0
- ansible_test/_util/controller/sanity/pylint/config/collection.cfg +1 -0
- ansible_test/_util/controller/sanity/pylint/config/default.cfg +1 -0
- ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +73 -8
- ansible_test/_util/target/setup/bootstrap.sh +31 -0
- ansible/_internal/_errors/_utils.py +0 -310
- {ansible_core-2.19.0b3.dist-info → ansible_core-2.19.0b5.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.19.0b3.dist-info → ansible_core-2.19.0b5.dist-info/licenses}/COPYING +0 -0
- {ansible_core-2.19.0b3.dist-info → ansible_core-2.19.0b5.dist-info/licenses/licenses}/Apache-License.txt +0 -0
- {ansible_core-2.19.0b3.dist-info → ansible_core-2.19.0b5.dist-info/licenses/licenses}/BSD-3-Clause.txt +0 -0
- {ansible_core-2.19.0b3.dist-info → ansible_core-2.19.0b5.dist-info/licenses/licenses}/MIT-license.txt +0 -0
- {ansible_core-2.19.0b3.dist-info → ansible_core-2.19.0b5.dist-info/licenses/licenses}/PSF-license.txt +0 -0
- {ansible_core-2.19.0b3.dist-info → ansible_core-2.19.0b5.dist-info/licenses/licenses}/simplified_bsd.txt +0 -0
- {ansible_core-2.19.0b3.dist-info → ansible_core-2.19.0b5.dist-info}/top_level.txt +0 -0
ansible/utils/display.py
CHANGED
@@ -51,13 +51,14 @@ from struct import unpack, pack
|
|
51
51
|
from ansible import constants as C
|
52
52
|
from ansible.constants import config
|
53
53
|
from ansible.errors import AnsibleAssertionError, AnsiblePromptInterrupt, AnsiblePromptNoninteractive, AnsibleError
|
54
|
-
from ansible._internal._errors import
|
55
|
-
from ansible.
|
54
|
+
from ansible._internal._errors import _error_utils, _error_factory
|
55
|
+
from ansible._internal import _event_formatting
|
56
|
+
from ansible.module_utils._internal import _ambient_context, _deprecator, _messages
|
56
57
|
from ansible.module_utils.common.text.converters import to_bytes, to_text
|
58
|
+
from ansible.module_utils.datatag import deprecator_from_collection_name
|
57
59
|
from ansible._internal._datatag._tags import TrustedAsTemplate
|
58
|
-
from ansible.module_utils.common.messages import ErrorSummary, WarningSummary, DeprecationSummary, Detail, SummaryBase, PluginInfo
|
59
60
|
from ansible.module_utils.six import text_type
|
60
|
-
from ansible.module_utils._internal import _traceback
|
61
|
+
from ansible.module_utils._internal import _traceback, _errors
|
61
62
|
from ansible.utils.color import stringc
|
62
63
|
from ansible.utils.multiprocessing import context as multiprocessing_context
|
63
64
|
from ansible.utils.singleton import Singleton
|
@@ -90,6 +91,9 @@ def _is_controller_traceback_enabled(event: _traceback.TracebackEvent) -> bool:
|
|
90
91
|
if 'never' in flag_values:
|
91
92
|
return False
|
92
93
|
|
94
|
+
if _traceback.TracebackEvent.DEPRECATED_VALUE.name.lower() in flag_values:
|
95
|
+
flag_values.add(_traceback.TracebackEvent.DEPRECATED.name.lower()) # DEPRECATED_VALUE implies DEPRECATED
|
96
|
+
|
93
97
|
return event.name.lower() in flag_values
|
94
98
|
|
95
99
|
|
@@ -433,6 +437,10 @@ class Display(metaclass=Singleton):
|
|
433
437
|
if not isinstance(msg, str):
|
434
438
|
raise TypeError(f'Display message must be str, not: {msg.__class__.__name__}')
|
435
439
|
|
440
|
+
# Convert Windows newlines to Unix newlines.
|
441
|
+
# Some environments, such as Azure Pipelines, render `\r` as an additional `\n`.
|
442
|
+
msg = msg.replace('\r\n', '\n')
|
443
|
+
|
436
444
|
nocolor = msg
|
437
445
|
|
438
446
|
if not log_only:
|
@@ -568,7 +576,7 @@ class Display(metaclass=Singleton):
|
|
568
576
|
version=version,
|
569
577
|
removed=removed,
|
570
578
|
date=date,
|
571
|
-
deprecator=
|
579
|
+
deprecator=deprecator_from_collection_name(collection_name),
|
572
580
|
)
|
573
581
|
|
574
582
|
if removed:
|
@@ -585,10 +593,10 @@ class Display(metaclass=Singleton):
|
|
585
593
|
version: str | None,
|
586
594
|
removed: bool = False,
|
587
595
|
date: str | None,
|
588
|
-
deprecator: PluginInfo | None,
|
596
|
+
deprecator: _messages.PluginInfo | None,
|
589
597
|
) -> str:
|
590
598
|
"""Internal use only. Return a deprecation message and help text for display."""
|
591
|
-
# DTFIX-
|
599
|
+
# DTFIX-FUTURE: the logic for omitting date/version doesn't apply to the payload, so it shows up in vars in some cases when it should not
|
592
600
|
|
593
601
|
if removed:
|
594
602
|
removal_fragment = 'This feature was removed'
|
@@ -598,13 +606,13 @@ class Display(metaclass=Singleton):
|
|
598
606
|
if not deprecator or deprecator.type == _deprecator.INDETERMINATE_DEPRECATOR.type:
|
599
607
|
collection = None
|
600
608
|
plugin_fragment = ''
|
601
|
-
elif deprecator.type == _deprecator.
|
609
|
+
elif deprecator.type == _deprecator._COLLECTION_ONLY_TYPE:
|
602
610
|
collection = deprecator.resolved_name
|
603
611
|
plugin_fragment = ''
|
604
612
|
else:
|
605
613
|
parts = deprecator.resolved_name.split('.')
|
606
614
|
plugin_name = parts[-1]
|
607
|
-
#
|
615
|
+
# DTFIX1: normalize 'modules' -> 'module' before storing it so we can eliminate the normalization here
|
608
616
|
plugin_type = "module" if deprecator.type in ("module", "modules") else f'{deprecator.type} plugin'
|
609
617
|
|
610
618
|
collection = '.'.join(parts[:2]) if len(parts) > 2 else None
|
@@ -668,7 +676,7 @@ class Display(metaclass=Singleton):
|
|
668
676
|
date: str | None = None,
|
669
677
|
collection_name: str | None = None,
|
670
678
|
*,
|
671
|
-
deprecator: PluginInfo | None = None,
|
679
|
+
deprecator: _messages.PluginInfo | None = None,
|
672
680
|
help_text: str | None = None,
|
673
681
|
obj: t.Any = None,
|
674
682
|
) -> None:
|
@@ -678,8 +686,8 @@ class Display(metaclass=Singleton):
|
|
678
686
|
Specify `version` or `date`, but not both.
|
679
687
|
If `date` is a string, it must be in the form `YYYY-MM-DD`.
|
680
688
|
"""
|
681
|
-
#
|
682
|
-
#
|
689
|
+
# DTFIX3: are there any deprecation calls where the feature is switching from enabled to disabled, rather than being removed entirely?
|
690
|
+
# DTFIX3: are there deprecated features which should going through deferred deprecation instead?
|
683
691
|
|
684
692
|
_skip_stackwalk = True
|
685
693
|
|
@@ -691,6 +699,7 @@ class Display(metaclass=Singleton):
|
|
691
699
|
help_text=help_text,
|
692
700
|
obj=obj,
|
693
701
|
deprecator=_deprecator.get_best_deprecator(deprecator=deprecator, collection_name=collection_name),
|
702
|
+
formatted_traceback=_traceback.maybe_capture_traceback(msg, _traceback.TracebackEvent.DEPRECATED),
|
694
703
|
)
|
695
704
|
|
696
705
|
def _deprecated_with_plugin_info(
|
@@ -702,7 +711,8 @@ class Display(metaclass=Singleton):
|
|
702
711
|
date: str | None,
|
703
712
|
help_text: str | None,
|
704
713
|
obj: t.Any,
|
705
|
-
deprecator: PluginInfo | None,
|
714
|
+
deprecator: _messages.PluginInfo | None,
|
715
|
+
formatted_traceback: str | None = None,
|
706
716
|
) -> None:
|
707
717
|
"""
|
708
718
|
This is the internal pre-proxy half of the `deprecated` implementation.
|
@@ -721,23 +731,21 @@ class Display(metaclass=Singleton):
|
|
721
731
|
|
722
732
|
raise AnsibleError(formatted_msg)
|
723
733
|
|
724
|
-
if source_context :=
|
734
|
+
if source_context := _error_utils.SourceContext.from_value(obj):
|
725
735
|
formatted_source_context = str(source_context)
|
726
736
|
else:
|
727
737
|
formatted_source_context = None
|
728
738
|
|
729
|
-
deprecation = DeprecationSummary(
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
),
|
739
|
+
deprecation = _messages.DeprecationSummary(
|
740
|
+
event=_messages.Event(
|
741
|
+
msg=msg,
|
742
|
+
formatted_source_context=formatted_source_context,
|
743
|
+
help_text=help_text,
|
744
|
+
formatted_traceback=formatted_traceback,
|
736
745
|
),
|
737
746
|
version=version,
|
738
747
|
date=date,
|
739
748
|
deprecator=deprecator,
|
740
|
-
formatted_traceback=_traceback.maybe_capture_traceback(_traceback.TracebackEvent.DEPRECATED),
|
741
749
|
)
|
742
750
|
|
743
751
|
if warning_ctx := _DeferredWarningContext.current(optional=True):
|
@@ -747,7 +755,7 @@ class Display(metaclass=Singleton):
|
|
747
755
|
self._deprecated(deprecation)
|
748
756
|
|
749
757
|
@_proxy
|
750
|
-
def _deprecated(self, warning: DeprecationSummary) -> None:
|
758
|
+
def _deprecated(self, warning: _messages.DeprecationSummary) -> None:
|
751
759
|
"""Internal implementation detail, use `deprecated` instead."""
|
752
760
|
|
753
761
|
# This is the post-proxy half of the `deprecated` implementation.
|
@@ -758,10 +766,10 @@ class Display(metaclass=Singleton):
|
|
758
766
|
|
759
767
|
self.warning('Deprecation warnings can be disabled by setting `deprecation_warnings=False` in ansible.cfg.')
|
760
768
|
|
761
|
-
msg =
|
769
|
+
msg = _format_message(warning, _traceback.is_traceback_enabled(_traceback.TracebackEvent.DEPRECATED))
|
762
770
|
msg = f'[DEPRECATION WARNING]: {msg}'
|
763
771
|
|
764
|
-
#
|
772
|
+
# DTFIX3: what should we do with wrap_message?
|
765
773
|
msg = self._wrap_message(msg=msg, wrap_text=True)
|
766
774
|
|
767
775
|
if self._deduplicate(msg, self._deprecations):
|
@@ -778,47 +786,46 @@ class Display(metaclass=Singleton):
|
|
778
786
|
obj: t.Any = None
|
779
787
|
) -> None:
|
780
788
|
"""Display a warning message."""
|
789
|
+
_skip_stackwalk = True
|
781
790
|
|
782
791
|
# This is the pre-proxy half of the `warning` implementation.
|
783
792
|
# Any logic that must occur on workers needs to be implemented here.
|
784
793
|
|
785
|
-
if source_context :=
|
794
|
+
if source_context := _error_utils.SourceContext.from_value(obj):
|
786
795
|
formatted_source_context = str(source_context)
|
787
796
|
else:
|
788
797
|
formatted_source_context = None
|
789
798
|
|
790
|
-
warning = WarningSummary(
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
),
|
799
|
+
warning = _messages.WarningSummary(
|
800
|
+
event=_messages.Event(
|
801
|
+
msg=msg,
|
802
|
+
help_text=help_text,
|
803
|
+
formatted_source_context=formatted_source_context,
|
804
|
+
formatted_traceback=_traceback.maybe_capture_traceback(msg, _traceback.TracebackEvent.WARNING),
|
797
805
|
),
|
798
|
-
formatted_traceback=_traceback.maybe_capture_traceback(_traceback.TracebackEvent.WARNING),
|
799
806
|
)
|
800
807
|
|
801
808
|
if warning_ctx := _DeferredWarningContext.current(optional=True):
|
802
809
|
warning_ctx.capture(warning)
|
803
|
-
#
|
810
|
+
# DTFIX3: what to do about propagating wrap_text?
|
804
811
|
return
|
805
812
|
|
806
813
|
self._warning(warning, wrap_text=not formatted)
|
807
814
|
|
808
815
|
@_proxy
|
809
|
-
def _warning(self, warning: WarningSummary, wrap_text: bool) -> None:
|
816
|
+
def _warning(self, warning: _messages.WarningSummary, wrap_text: bool) -> None:
|
810
817
|
"""Internal implementation detail, use `warning` instead."""
|
811
818
|
|
812
819
|
# This is the post-proxy half of the `warning` implementation.
|
813
820
|
# Any logic that must occur in the primary controller process needs to be implemented here.
|
814
821
|
|
815
|
-
msg =
|
822
|
+
msg = _format_message(warning, _traceback.is_traceback_enabled(_traceback.TracebackEvent.WARNING))
|
816
823
|
msg = f"[WARNING]: {msg}"
|
817
824
|
|
818
825
|
if self._deduplicate(msg, self._warns):
|
819
826
|
return
|
820
827
|
|
821
|
-
#
|
828
|
+
# DTFIX3: what should we do with wrap_message?
|
822
829
|
msg = self._wrap_message(msg=msg, wrap_text=wrap_text)
|
823
830
|
|
824
831
|
self.display(msg, color=C.config.get_config_value('COLOR_WARN'), stderr=True, caplevel=-2)
|
@@ -870,17 +877,39 @@ class Display(metaclass=Singleton):
|
|
870
877
|
(out, err) = cmd.communicate()
|
871
878
|
self.display(u"%s\n" % to_text(out), color=color)
|
872
879
|
|
873
|
-
def error_as_warning(
|
880
|
+
def error_as_warning(
|
881
|
+
self,
|
882
|
+
msg: str | None,
|
883
|
+
exception: BaseException,
|
884
|
+
*,
|
885
|
+
help_text: str | None = None,
|
886
|
+
obj: t.Any = None,
|
887
|
+
) -> None:
|
874
888
|
"""Display an exception as a warning."""
|
889
|
+
_skip_stackwalk = True
|
875
890
|
|
876
|
-
|
891
|
+
event = _error_factory.ControllerEventFactory.from_exception(exception, _traceback.is_traceback_enabled(_traceback.TracebackEvent.WARNING))
|
877
892
|
|
878
893
|
if msg:
|
879
|
-
|
894
|
+
if source_context := _error_utils.SourceContext.from_value(obj):
|
895
|
+
formatted_source_context = str(source_context)
|
896
|
+
else:
|
897
|
+
formatted_source_context = None
|
898
|
+
|
899
|
+
event = _messages.Event(
|
900
|
+
msg=msg,
|
901
|
+
help_text=help_text,
|
902
|
+
formatted_source_context=formatted_source_context,
|
903
|
+
formatted_traceback=_traceback.maybe_capture_traceback(msg, _traceback.TracebackEvent.WARNING),
|
904
|
+
chain=_messages.EventChain(
|
905
|
+
msg_reason=_errors.MSG_REASON_DIRECT_CAUSE,
|
906
|
+
traceback_reason=_errors.TRACEBACK_REASON_EXCEPTION_DIRECT_WARNING,
|
907
|
+
event=event,
|
908
|
+
),
|
909
|
+
)
|
880
910
|
|
881
|
-
warning = WarningSummary(
|
882
|
-
|
883
|
-
formatted_traceback=error.formatted_traceback,
|
911
|
+
warning = _messages.WarningSummary(
|
912
|
+
event=event,
|
884
913
|
)
|
885
914
|
|
886
915
|
if warning_ctx := _DeferredWarningContext.current(optional=True):
|
@@ -891,32 +920,41 @@ class Display(metaclass=Singleton):
|
|
891
920
|
|
892
921
|
def error(self, msg: str | BaseException, wrap_text: bool = True, stderr: bool = True) -> None:
|
893
922
|
"""Display an error message."""
|
923
|
+
_skip_stackwalk = True
|
894
924
|
|
895
925
|
# This is the pre-proxy half of the `error` implementation.
|
896
926
|
# Any logic that must occur on workers needs to be implemented here.
|
897
927
|
|
898
928
|
if isinstance(msg, BaseException):
|
899
|
-
|
929
|
+
event = _error_factory.ControllerEventFactory.from_exception(msg, _traceback.is_traceback_enabled(_traceback.TracebackEvent.ERROR))
|
930
|
+
|
900
931
|
wrap_text = False
|
901
932
|
else:
|
902
|
-
|
933
|
+
event = _messages.Event(
|
934
|
+
msg=msg,
|
935
|
+
formatted_traceback=_traceback.maybe_capture_traceback(msg, _traceback.TracebackEvent.ERROR),
|
936
|
+
)
|
937
|
+
|
938
|
+
error = _messages.ErrorSummary(
|
939
|
+
event=event,
|
940
|
+
)
|
903
941
|
|
904
942
|
self._error(error, wrap_text=wrap_text, stderr=stderr)
|
905
943
|
|
906
944
|
@_proxy
|
907
|
-
def _error(self, error: ErrorSummary, wrap_text: bool, stderr: bool) -> None:
|
945
|
+
def _error(self, error: _messages.ErrorSummary, wrap_text: bool, stderr: bool) -> None:
|
908
946
|
"""Internal implementation detail, use `error` instead."""
|
909
947
|
|
910
948
|
# This is the post-proxy half of the `error` implementation.
|
911
949
|
# Any logic that must occur in the primary controller process needs to be implemented here.
|
912
950
|
|
913
|
-
msg =
|
951
|
+
msg = _format_message(error, _traceback.is_traceback_enabled(_traceback.TracebackEvent.ERROR))
|
914
952
|
msg = f'[ERROR]: {msg}'
|
915
953
|
|
916
954
|
if self._deduplicate(msg, self._errors):
|
917
955
|
return
|
918
956
|
|
919
|
-
#
|
957
|
+
# DTFIX3: what should we do with wrap_message?
|
920
958
|
msg = self._wrap_message(msg=msg, wrap_text=wrap_text)
|
921
959
|
|
922
960
|
self.display(msg, color=C.config.get_config_value('COLOR_ERROR'), stderr=stderr, caplevel=-1)
|
@@ -1146,9 +1184,9 @@ class _DeferredWarningContext(_ambient_context.AmbientContextBase):
|
|
1146
1184
|
|
1147
1185
|
def __init__(self, *, variables: dict[str, object]) -> None:
|
1148
1186
|
self._variables = variables # DTFIX-FUTURE: move this to an AmbientContext-derived TaskContext (once it exists)
|
1149
|
-
self._deprecation_warnings: list[DeprecationSummary] = []
|
1150
|
-
self._warnings: list[WarningSummary] = []
|
1151
|
-
self._seen: set[WarningSummary] = set()
|
1187
|
+
self._deprecation_warnings: list[_messages.DeprecationSummary] = []
|
1188
|
+
self._warnings: list[_messages.WarningSummary] = []
|
1189
|
+
self._seen: set[_messages.WarningSummary] = set()
|
1152
1190
|
|
1153
1191
|
@classmethod
|
1154
1192
|
def deprecation_warnings_enabled(cls) -> bool:
|
@@ -1161,82 +1199,29 @@ class _DeferredWarningContext(_ambient_context.AmbientContextBase):
|
|
1161
1199
|
|
1162
1200
|
return C.config.get_config_value('DEPRECATION_WARNINGS', variables=variables)
|
1163
1201
|
|
1164
|
-
def capture(self, warning: WarningSummary) -> None:
|
1202
|
+
def capture(self, warning: _messages.WarningSummary) -> None:
|
1165
1203
|
"""Add the warning/deprecation to the context if it has not already been seen by this context."""
|
1166
1204
|
if warning in self._seen:
|
1167
1205
|
return
|
1168
1206
|
|
1169
1207
|
self._seen.add(warning)
|
1170
1208
|
|
1171
|
-
if isinstance(warning, DeprecationSummary):
|
1209
|
+
if isinstance(warning, _messages.DeprecationSummary):
|
1172
1210
|
self._deprecation_warnings.append(warning)
|
1173
1211
|
else:
|
1174
1212
|
self._warnings.append(warning)
|
1175
1213
|
|
1176
|
-
def get_warnings(self) -> list[WarningSummary]:
|
1214
|
+
def get_warnings(self) -> list[_messages.WarningSummary]:
|
1177
1215
|
"""Return a list of the captured non-deprecation warnings."""
|
1178
1216
|
# DTFIX-FUTURE: return a read-only list proxy instead
|
1179
1217
|
return self._warnings
|
1180
1218
|
|
1181
|
-
def get_deprecation_warnings(self) -> list[DeprecationSummary]:
|
1219
|
+
def get_deprecation_warnings(self) -> list[_messages.DeprecationSummary]:
|
1182
1220
|
"""Return a list of the captured deprecation warnings."""
|
1183
1221
|
# DTFIX-FUTURE: return a read-only list proxy instead
|
1184
1222
|
return self._deprecation_warnings
|
1185
1223
|
|
1186
1224
|
|
1187
|
-
def _format_error_details(details: t.Sequence[Detail], formatted_tb: str | None = None) -> str:
|
1188
|
-
details = _utils._collapse_error_details(details)
|
1189
|
-
|
1190
|
-
message_lines: list[str] = []
|
1191
|
-
|
1192
|
-
if len(details) > 1:
|
1193
|
-
message_lines.append(_utils._dedupe_and_concat_message_chain([md.msg for md in details]))
|
1194
|
-
message_lines.append('')
|
1195
|
-
|
1196
|
-
for idx, edc in enumerate(details):
|
1197
|
-
if idx:
|
1198
|
-
message_lines.extend((
|
1199
|
-
'',
|
1200
|
-
'<<< caused by >>>',
|
1201
|
-
'',
|
1202
|
-
))
|
1203
|
-
|
1204
|
-
message_lines.extend(_get_message_lines(edc.msg, edc.help_text, edc.formatted_source_context))
|
1205
|
-
|
1206
|
-
message_lines = [f'{line}\n' for line in message_lines]
|
1207
|
-
|
1208
|
-
if formatted_tb:
|
1209
|
-
message_lines.append('\n')
|
1210
|
-
message_lines.append(formatted_tb)
|
1211
|
-
|
1212
|
-
msg = "".join(message_lines).strip()
|
1213
|
-
|
1214
|
-
if '\n' in msg:
|
1215
|
-
msg += '\n\n'
|
1216
|
-
else:
|
1217
|
-
msg += '\n'
|
1218
|
-
|
1219
|
-
return msg
|
1220
|
-
|
1221
|
-
|
1222
|
-
def _get_message_lines(message: str, help_text: str | None, formatted_source_context: str | None) -> list[str]:
|
1223
|
-
"""Return a list of error/warning message lines constructed from the given message, help text and source context."""
|
1224
|
-
|
1225
|
-
if help_text and not formatted_source_context and '\n' not in message and '\n' not in help_text:
|
1226
|
-
return [f'{message} {help_text}'] # prefer a single-line message with help text when there is no source context
|
1227
|
-
|
1228
|
-
message_lines = [message]
|
1229
|
-
|
1230
|
-
if formatted_source_context:
|
1231
|
-
message_lines.append(formatted_source_context)
|
1232
|
-
|
1233
|
-
if help_text:
|
1234
|
-
message_lines.append('')
|
1235
|
-
message_lines.append(help_text)
|
1236
|
-
|
1237
|
-
return message_lines
|
1238
|
-
|
1239
|
-
|
1240
1225
|
def _join_sentences(first: str | None, second: str | None) -> str:
|
1241
1226
|
"""Join two sentences together."""
|
1242
1227
|
first = (first or '').strip()
|
@@ -1257,34 +1242,28 @@ def _join_sentences(first: str | None, second: str | None) -> str:
|
|
1257
1242
|
return ' '.join((first, second))
|
1258
1243
|
|
1259
1244
|
|
1260
|
-
def
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
# augment the first detail element for deprecations to include additional diagnostic info and help text
|
1265
|
-
detail_list = list(details)
|
1266
|
-
detail = detail_list[0]
|
1267
|
-
|
1268
|
-
deprecation_msg = _display._get_deprecation_message_with_plugin_info(
|
1269
|
-
msg=detail.msg,
|
1245
|
+
def _format_message(summary: _messages.SummaryBase, include_traceback: bool) -> str:
|
1246
|
+
if isinstance(summary, _messages.DeprecationSummary):
|
1247
|
+
deprecation_message = _display._get_deprecation_message_with_plugin_info(
|
1248
|
+
msg=summary.event.msg,
|
1270
1249
|
version=summary.version,
|
1271
1250
|
date=summary.date,
|
1272
1251
|
deprecator=summary.deprecator,
|
1273
1252
|
)
|
1274
1253
|
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
help_text=detail.help_text,
|
1279
|
-
)
|
1280
|
-
|
1281
|
-
details = detail_list
|
1254
|
+
event = dataclasses.replace(summary.event, msg=deprecation_message)
|
1255
|
+
else:
|
1256
|
+
event = summary.event
|
1282
1257
|
|
1283
|
-
return
|
1258
|
+
return _event_formatting.format_event(event, include_traceback)
|
1284
1259
|
|
1285
1260
|
|
1286
|
-
def _report_config_warnings(deprecator: PluginInfo) -> None:
|
1261
|
+
def _report_config_warnings(deprecator: _messages.PluginInfo) -> None:
|
1287
1262
|
"""Called by config to report warnings/deprecations collected during a config parse."""
|
1263
|
+
while config._errors:
|
1264
|
+
msg, exception = config._errors.pop()
|
1265
|
+
_display.error_as_warning(msg=msg, exception=exception)
|
1266
|
+
|
1288
1267
|
while config.WARNINGS:
|
1289
1268
|
warn = config.WARNINGS.pop()
|
1290
1269
|
_display.warning(warn)
|
ansible/utils/hashing.py
CHANGED
ansible/utils/listify.py
CHANGED
@@ -26,10 +26,12 @@ __all__ = ['listify_lookup_plugin_terms']
|
|
26
26
|
|
27
27
|
|
28
28
|
def listify_lookup_plugin_terms(terms, templar=None, fail_on_undefined=True):
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
# deprecated: description="Calling listify_lookup_plugin_terms function is not necessary; the function should be deprecated." core_version="2.23"
|
30
|
+
# display.deprecated(
|
31
|
+
# msg='The "listify_lookup_plugin_terms" function is not required for lookup terms to be templated.',
|
32
|
+
# version='2.27',
|
33
|
+
# help_text='If needed, implement custom `strip` or list-wrapping in the caller.',
|
34
|
+
# )
|
33
35
|
|
34
36
|
if isinstance(terms, str):
|
35
37
|
terms = terms.strip()
|
ansible/utils/plugin_docs.py
CHANGED
@@ -154,7 +154,8 @@ def add_fragments(doc, filename, fragment_loader, is_module=False):
|
|
154
154
|
unknown_fragments.append(fragment_slug)
|
155
155
|
continue
|
156
156
|
|
157
|
-
|
157
|
+
# trust-tagged source propagates to loaded values; expressions and templates in config require trust
|
158
|
+
fragment_yaml = _tags.TrustedAsTemplate().tag(getattr(fragment_class, fragment_var, None))
|
158
159
|
if fragment_yaml is None:
|
159
160
|
if fragment_var != 'DOCUMENTATION':
|
160
161
|
# if it's asking for something specific that's missing, that's an error
|
ansible/utils/unsafe_proxy.py
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
3
|
|
4
4
|
# deprecated: description="deprecate unsafe_proxy module" core_version="2.23"
|
5
|
-
#
|
5
|
+
# DTFIX5: add full unit test coverage
|
6
6
|
from __future__ import annotations
|
7
7
|
|
8
8
|
from collections.abc import Mapping, Set
|
ansible/vars/hostvars.py
CHANGED
@@ -113,5 +113,5 @@ class HostVarsVars(c.Mapping):
|
|
113
113
|
return self
|
114
114
|
|
115
115
|
|
116
|
-
# DTFIX-
|
116
|
+
# DTFIX-FUTURE: is there a better way to add this to the ignorable types in the module_utils code
|
117
117
|
_datatag._untaggable_types.update({HostVars, HostVarsVars})
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: ansible-core
|
3
|
-
Version: 2.19.
|
3
|
+
Version: 2.19.0b5
|
4
4
|
Summary: Radically simple IT automation
|
5
5
|
Author: Ansible Project
|
6
6
|
Project-URL: Homepage, https://ansible.com/
|
@@ -38,6 +38,7 @@ Requires-Dist: PyYAML>=5.1
|
|
38
38
|
Requires-Dist: cryptography
|
39
39
|
Requires-Dist: packaging
|
40
40
|
Requires-Dist: resolvelib<2.0.0,>=0.5.3
|
41
|
+
Dynamic: license-file
|
41
42
|
|
42
43
|
[](https://pypi.org/project/ansible-core)
|
43
44
|
[](https://docs.ansible.com/ansible/latest/)
|