ansible-core 2.19.0b6__py3-none-any.whl → 2.19.0rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. ansible/_internal/_json/__init__.py +31 -20
  2. ansible/_internal/_json/_profiles/_legacy.py +1 -1
  3. ansible/_internal/_templating/_jinja_bits.py +46 -14
  4. ansible/_internal/_templating/_jinja_common.py +1 -1
  5. ansible/_internal/_templating/_jinja_plugins.py +5 -2
  6. ansible/_internal/_templating/_utils.py +2 -1
  7. ansible/_internal/ansible_collections/ansible/_protomatter/plugins/filter/dump_object.py +9 -0
  8. ansible/cli/__init__.py +2 -2
  9. ansible/cli/_ssh_askpass.py +37 -30
  10. ansible/cli/adhoc.py +6 -3
  11. ansible/cli/console.py +2 -2
  12. ansible/cli/doc.py +2 -2
  13. ansible/config/base.yml +9 -6
  14. ansible/executor/module_common.py +9 -6
  15. ansible/executor/powershell/psrp_put_file.ps1 +1 -1
  16. ansible/executor/task_executor.py +2 -2
  17. ansible/executor/task_queue_manager.py +34 -70
  18. ansible/executor/task_result.py +1 -1
  19. ansible/galaxy/api.py +2 -2
  20. ansible/galaxy/collection/concrete_artifact_manager.py +2 -2
  21. ansible/galaxy/dependency_resolution/providers.py +3 -3
  22. ansible/inventory/group.py +6 -1
  23. ansible/inventory/host.py +6 -1
  24. ansible/module_utils/_internal/_datatag/__init__.py +6 -1
  25. ansible/module_utils/_internal/_deprecator.py +12 -1
  26. ansible/module_utils/ansible_release.py +1 -1
  27. ansible/module_utils/basic.py +14 -16
  28. ansible/module_utils/common/yaml.py +1 -1
  29. ansible/module_utils/csharp/Ansible.Basic.cs +1 -1
  30. ansible/module_utils/csharp/Ansible.Privilege.cs +2 -2
  31. ansible/module_utils/facts/hardware/base.py +1 -1
  32. ansible/module_utils/facts/other/facter.py +1 -1
  33. ansible/module_utils/facts/system/distribution.py +2 -2
  34. ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
  35. ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
  36. ansible/module_utils/powershell/Ansible.ModuleUtils.CommandUtil.psm1 +1 -1
  37. ansible/module_utils/powershell/Ansible.ModuleUtils.WebRequest.psm1 +1 -1
  38. ansible/module_utils/urls.py +1 -1
  39. ansible/modules/apt.py +9 -3
  40. ansible/modules/assemble.py +5 -3
  41. ansible/modules/expect.py +5 -5
  42. ansible/modules/hostname.py +2 -2
  43. ansible/modules/pip.py +9 -11
  44. ansible/modules/raw.py +2 -2
  45. ansible/modules/stat.py +1 -1
  46. ansible/modules/systemd.py +1 -1
  47. ansible/modules/systemd_service.py +1 -1
  48. ansible/modules/wait_for.py +10 -3
  49. ansible/parsing/mod_args.py +38 -20
  50. ansible/parsing/vault/__init__.py +3 -3
  51. ansible/playbook/base.py +0 -2
  52. ansible/playbook/helpers.py +1 -1
  53. ansible/playbook/playbook_include.py +23 -57
  54. ansible/playbook/role/__init__.py +40 -23
  55. ansible/plugins/action/__init__.py +2 -2
  56. ansible/plugins/action/assemble.py +2 -1
  57. ansible/plugins/action/assert.py +2 -2
  58. ansible/plugins/action/script.py +5 -4
  59. ansible/plugins/action/template.py +1 -1
  60. ansible/plugins/callback/__init__.py +77 -87
  61. ansible/plugins/callback/default.py +0 -3
  62. ansible/plugins/callback/junit.py +0 -6
  63. ansible/plugins/connection/ssh.py +13 -6
  64. ansible/plugins/filter/pow.yml +1 -1
  65. ansible/plugins/filter/root.yml +1 -1
  66. ansible/plugins/filter/strftime.yml +3 -3
  67. ansible/plugins/filter/to_uuid.yml +1 -1
  68. ansible/plugins/inventory/script.py +1 -1
  69. ansible/plugins/loader.py +5 -0
  70. ansible/plugins/lookup/password.py +4 -6
  71. ansible/release.py +1 -1
  72. ansible/utils/display.py +16 -26
  73. ansible/utils/path.py +1 -1
  74. ansible/utils/vars.py +6 -2
  75. ansible/vars/manager.py +6 -3
  76. ansible/vars/reserved.py +6 -4
  77. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/METADATA +1 -1
  78. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/RECORD +111 -109
  79. ansible_test/_internal/__init__.py +5 -0
  80. ansible_test/_internal/ansible_util.py +1 -1
  81. ansible_test/_internal/classification/python.py +6 -0
  82. ansible_test/_internal/cli/commands/__init__.py +0 -5
  83. ansible_test/_internal/cli/environments.py +51 -5
  84. ansible_test/_internal/commands/coverage/__init__.py +1 -1
  85. ansible_test/_internal/commands/integration/__init__.py +18 -5
  86. ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
  87. ansible_test/_internal/commands/sanity/__init__.py +3 -1
  88. ansible_test/_internal/commands/sanity/integration_aliases.py +11 -0
  89. ansible_test/_internal/commands/shell/__init__.py +43 -4
  90. ansible_test/_internal/commands/units/__init__.py +4 -1
  91. ansible_test/_internal/config.py +21 -13
  92. ansible_test/_internal/debugging.py +166 -0
  93. ansible_test/_internal/delegation.py +21 -13
  94. ansible_test/_internal/host_profiles.py +197 -6
  95. ansible_test/_internal/inventory.py +4 -0
  96. ansible_test/_internal/metadata.py +94 -4
  97. ansible_test/_internal/processes.py +80 -0
  98. ansible_test/_internal/python_requirements.py +27 -0
  99. ansible_test/_internal/target.py +8 -0
  100. ansible_test/_internal/util_common.py +13 -3
  101. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +2 -1
  102. ansible_test/_util/target/injector/python.py +8 -0
  103. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/WHEEL +0 -0
  104. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/entry_points.txt +0 -0
  105. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/COPYING +0 -0
  106. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  107. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
  108. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  109. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  110. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  111. {ansible_core-2.19.0b6.dist-info → ansible_core-2.19.0rc1.dist-info}/top_level.txt +0 -0
ansible/utils/display.py CHANGED
@@ -40,7 +40,6 @@ import secrets
40
40
  import subprocess
41
41
  import sys
42
42
  import termios
43
- import textwrap
44
43
  import threading
45
44
  import time
46
45
  import tty
@@ -329,7 +328,6 @@ class Display(metaclass=Singleton):
329
328
  self.noncow = C.ANSIBLE_COW_SELECTION
330
329
 
331
330
  self.set_cowsay_info()
332
- self._wrap_stderr = C.WRAP_STDERR
333
331
 
334
332
  if self.b_cowsay:
335
333
  try:
@@ -621,6 +619,12 @@ class Display(metaclass=Singleton):
621
619
  # collections have a resolved_name but no type
622
620
  collection = deprecator.resolved_name if deprecator else None
623
621
  plugin_fragment = ''
622
+ elif deprecator.resolved_name == 'ansible.builtin':
623
+ # core deprecations from base classes (the API) have no plugin name, only 'ansible.builtin'
624
+ plugin_type_name = str(deprecator.type) if deprecator.type is _messages.PluginType.MODULE else f'{deprecator.type} plugin'
625
+
626
+ collection = deprecator.resolved_name
627
+ plugin_fragment = f'the {plugin_type_name} API'
624
628
  else:
625
629
  parts = deprecator.resolved_name.split('.')
626
630
  plugin_name = parts[-1]
@@ -657,13 +661,6 @@ class Display(metaclass=Singleton):
657
661
 
658
662
  return _join_sentences(msg, deprecation_msg)
659
663
 
660
- def _wrap_message(self, msg: str, wrap_text: bool) -> str:
661
- if wrap_text and self._wrap_stderr:
662
- wrapped = textwrap.wrap(msg, self.columns, drop_whitespace=False)
663
- msg = "\n".join(wrapped) + "\n"
664
-
665
- return msg
666
-
667
664
  @staticmethod
668
665
  def _deduplicate(msg: str, messages: set[str]) -> bool:
669
666
  """
@@ -780,9 +777,6 @@ class Display(metaclass=Singleton):
780
777
  msg = _format_message(warning, _traceback.is_traceback_enabled(_traceback.TracebackEvent.DEPRECATED))
781
778
  msg = f'[DEPRECATION WARNING]: {msg}'
782
779
 
783
- # DTFIX3: what should we do with wrap_message?
784
- msg = self._wrap_message(msg=msg, wrap_text=True)
785
-
786
780
  if self._deduplicate(msg, self._deprecations):
787
781
  return
788
782
 
@@ -799,6 +793,8 @@ class Display(metaclass=Singleton):
799
793
  """Display a warning message."""
800
794
  _skip_stackwalk = True
801
795
 
796
+ # deprecated: description='The formatted argument has no effect.' core_version='2.23'
797
+
802
798
  # This is the pre-proxy half of the `warning` implementation.
803
799
  # Any logic that must occur on workers needs to be implemented here.
804
800
 
@@ -818,13 +814,12 @@ class Display(metaclass=Singleton):
818
814
 
819
815
  if warning_ctx := _DeferredWarningContext.current(optional=True):
820
816
  warning_ctx.capture(warning)
821
- # DTFIX3: what to do about propagating wrap_text?
822
817
  return
823
818
 
824
- self._warning(warning, wrap_text=not formatted)
819
+ self._warning(warning)
825
820
 
826
821
  @_proxy
827
- def _warning(self, warning: _messages.WarningSummary, wrap_text: bool) -> None:
822
+ def _warning(self, warning: _messages.WarningSummary) -> None:
828
823
  """Internal implementation detail, use `warning` instead."""
829
824
 
830
825
  # This is the post-proxy half of the `warning` implementation.
@@ -836,9 +831,6 @@ class Display(metaclass=Singleton):
836
831
  if self._deduplicate(msg, self._warns):
837
832
  return
838
833
 
839
- # DTFIX3: what should we do with wrap_message?
840
- msg = self._wrap_message(msg=msg, wrap_text=wrap_text)
841
-
842
834
  self.display(msg, color=C.config.get_config_value('COLOR_WARN'), stderr=True, caplevel=-2)
843
835
 
844
836
  @_proxy
@@ -927,19 +919,20 @@ class Display(metaclass=Singleton):
927
919
  warning_ctx.capture(warning)
928
920
  return
929
921
 
930
- self._warning(warning, wrap_text=False)
922
+ self._warning(warning)
931
923
 
932
924
  def error(self, msg: str | BaseException, wrap_text: bool = True, stderr: bool = True) -> None:
933
925
  """Display an error message."""
934
926
  _skip_stackwalk = True
935
927
 
928
+ # deprecated: description='The wrap_text argument has no effect.' core_version='2.23'
929
+ # deprecated: description='The stderr argument has no effect.' core_version='2.23'
930
+
936
931
  # This is the pre-proxy half of the `error` implementation.
937
932
  # Any logic that must occur on workers needs to be implemented here.
938
933
 
939
934
  if isinstance(msg, BaseException):
940
935
  event = _error_factory.ControllerEventFactory.from_exception(msg, _traceback.is_traceback_enabled(_traceback.TracebackEvent.ERROR))
941
-
942
- wrap_text = False
943
936
  else:
944
937
  event = _messages.Event(
945
938
  msg=msg,
@@ -950,10 +943,10 @@ class Display(metaclass=Singleton):
950
943
  event=event,
951
944
  )
952
945
 
953
- self._error(error, wrap_text=wrap_text, stderr=stderr)
946
+ self._error(error, stderr=True)
954
947
 
955
948
  @_proxy
956
- def _error(self, error: _messages.ErrorSummary, wrap_text: bool, stderr: bool) -> None:
949
+ def _error(self, error: _messages.ErrorSummary, stderr: bool) -> None:
957
950
  """Internal implementation detail, use `error` instead."""
958
951
 
959
952
  # This is the post-proxy half of the `error` implementation.
@@ -965,9 +958,6 @@ class Display(metaclass=Singleton):
965
958
  if self._deduplicate(msg, self._errors):
966
959
  return
967
960
 
968
- # DTFIX3: what should we do with wrap_message?
969
- msg = self._wrap_message(msg=msg, wrap_text=wrap_text)
970
-
971
961
  self.display(msg, color=C.config.get_config_value('COLOR_ERROR'), stderr=stderr, caplevel=-1)
972
962
 
973
963
  @staticmethod
ansible/utils/path.py CHANGED
@@ -102,7 +102,7 @@ def basedir(source):
102
102
  dname = os.path.dirname(source)
103
103
 
104
104
  if dname:
105
- # don't follow symlinks for basedir, enables source re-use
105
+ # don't follow symlinks for basedir, enables source reuse
106
106
  dname = os.path.abspath(dname)
107
107
 
108
108
  return to_text(dname, errors='surrogate_or_strict')
ansible/utils/vars.py CHANGED
@@ -28,6 +28,7 @@ from json import dumps
28
28
  from ansible import constants as C
29
29
  from ansible import context
30
30
  from ansible._internal import _json
31
+ from ansible._internal._templating import _jinja_bits
31
32
  from ansible.errors import AnsibleError, AnsibleOptionsError
32
33
  from ansible.module_utils.datatag import native_type_name
33
34
  from ansible.module_utils.common.text.converters import to_native, to_text
@@ -252,6 +253,8 @@ def isidentifier(ident):
252
253
 
253
254
  Originally posted at https://stackoverflow.com/a/29586366
254
255
  """
256
+ # deprecated: description='Use validate_variable_name instead.' core_version='2.23'
257
+
255
258
  if not isinstance(ident, str):
256
259
  return False
257
260
 
@@ -269,7 +272,7 @@ def isidentifier(ident):
269
272
 
270
273
  def validate_variable_name(name: object) -> None:
271
274
  """Validate the given variable name is valid, raising an AnsibleError if it is not."""
272
- if isinstance(name, str) and isidentifier(name):
275
+ if isinstance(name, str) and name.isidentifier() and name.isascii() and name not in _jinja_bits.JINJA_KEYWORDS:
273
276
  return
274
277
 
275
278
  if isinstance(name, (str, int, float, bool, type(None))):
@@ -290,7 +293,7 @@ def validate_variable_name(name: object) -> None:
290
293
  def transform_to_native_types(
291
294
  value: object,
292
295
  redact: bool = True,
293
- ) -> object:
296
+ ) -> t.Any:
294
297
  """
295
298
  Recursively transform the given value to Python native types.
296
299
  Potentially sensitive values such as individually vaulted variables will be redacted unless ``redact=False`` is passed.
@@ -303,6 +306,7 @@ def transform_to_native_types(
303
306
  convert_custom_scalars=True,
304
307
  convert_to_native_values=True,
305
308
  apply_transforms=True,
309
+ visit_keys=True, # ensure that keys are also converted
306
310
  encrypted_string_behavior=_json.EncryptedStringBehavior.REDACT if redact else _json.EncryptedStringBehavior.DECRYPT,
307
311
  )
308
312
 
ansible/vars/manager.py CHANGED
@@ -407,7 +407,7 @@ class VariableManager:
407
407
  all_vars = _combine_and_track(all_vars, self._extra_vars, "extra vars")
408
408
 
409
409
  # before we add 'reserved vars', check we didn't add any reserved vars
410
- warn_if_reserved(all_vars.keys())
410
+ warn_if_reserved(all_vars)
411
411
 
412
412
  # magic variables
413
413
  all_vars = _combine_and_track(all_vars, magic_variables, "magic vars")
@@ -563,7 +563,8 @@ class VariableManager:
563
563
  if not isinstance(facts, Mapping):
564
564
  raise AnsibleAssertionError("the type of 'facts' to set for host_facts should be a Mapping but is a %s" % type(facts))
565
565
 
566
- warn_if_reserved(facts.keys())
566
+ warn_if_reserved(facts)
567
+
567
568
  try:
568
569
  host_cache = self._fact_cache.get(host)
569
570
  except KeyError:
@@ -587,7 +588,8 @@ class VariableManager:
587
588
  if not isinstance(facts, Mapping):
588
589
  raise AnsibleAssertionError("the type of 'facts' to set for nonpersistent_facts should be a Mapping but is a %s" % type(facts))
589
590
 
590
- warn_if_reserved(facts.keys())
591
+ warn_if_reserved(facts)
592
+
591
593
  try:
592
594
  self._nonpersistent_fact_cache[host] |= facts
593
595
  except KeyError:
@@ -599,6 +601,7 @@ class VariableManager:
599
601
  """
600
602
 
601
603
  warn_if_reserved([varname])
604
+
602
605
  if host not in self._vars_cache:
603
606
  self._vars_cache[host] = dict()
604
607
 
ansible/vars/reserved.py CHANGED
@@ -66,8 +66,7 @@ def get_reserved_names(include_private: bool = True) -> set[str]:
66
66
 
67
67
 
68
68
  def warn_if_reserved(myvars: c.Iterable[str], additional: c.Iterable[str] | None = None) -> None:
69
- """ this function warns if any variable passed conflicts with internally reserved names """
70
-
69
+ """Issue a warning for any variable which conflicts with an internally reserved name."""
71
70
  if additional is None:
72
71
  reserved = _RESERVED_NAMES
73
72
  else:
@@ -76,8 +75,11 @@ def warn_if_reserved(myvars: c.Iterable[str], additional: c.Iterable[str] | None
76
75
  varnames = set(myvars)
77
76
  varnames.discard('vars') # we add this one internally, so safe to ignore
78
77
 
79
- for varname in varnames.intersection(reserved):
80
- display.warning(f'Found variable using reserved name {varname!r}.')
78
+ if conflicts := varnames.intersection(reserved):
79
+ # Ensure the varname used for obj is the tagged one from myvars and not the untagged one from reserved.
80
+ # This can occur because tags do not affect value equality, and intersection can return values from either the left or right side.
81
+ for varname in (name for name in myvars if name in conflicts):
82
+ display.warning(f'Found variable using reserved name {varname!r}.', obj=varname)
81
83
 
82
84
 
83
85
  def is_reserved_name(name: str) -> bool:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ansible-core
3
- Version: 2.19.0b6
3
+ Version: 2.19.0rc1
4
4
  Summary: Radically simple IT automation
5
5
  Author: Ansible Project
6
6
  Project-URL: Homepage, https://ansible.com/