ansible-core 2.19.2__py3-none-any.whl → 2.20.0b1__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.

Files changed (202) hide show
  1. ansible/_internal/__init__.py +1 -4
  2. ansible/_internal/_ansiballz/_builder.py +1 -3
  3. ansible/_internal/_collection_proxy.py +7 -9
  4. ansible/_internal/_display_utils.py +145 -0
  5. ansible/_internal/_json/__init__.py +3 -4
  6. ansible/_internal/_templating/_engine.py +1 -1
  7. ansible/_internal/_templating/_jinja_plugins.py +1 -2
  8. ansible/_internal/_wrapt.py +105 -301
  9. ansible/cli/__init__.py +11 -10
  10. ansible/cli/adhoc.py +1 -2
  11. ansible/cli/arguments/option_helpers.py +1 -1
  12. ansible/cli/config.py +5 -6
  13. ansible/cli/doc.py +67 -67
  14. ansible/cli/galaxy.py +15 -24
  15. ansible/cli/inventory.py +0 -1
  16. ansible/cli/playbook.py +0 -1
  17. ansible/cli/pull.py +0 -1
  18. ansible/cli/scripts/ansible_connection_cli_stub.py +1 -1
  19. ansible/config/base.yml +1 -25
  20. ansible/config/manager.py +0 -2
  21. ansible/executor/play_iterator.py +42 -20
  22. ansible/executor/playbook_executor.py +0 -9
  23. ansible/executor/powershell/async_watchdog.ps1 +24 -4
  24. ansible/executor/task_executor.py +32 -22
  25. ansible/executor/task_queue_manager.py +1 -3
  26. ansible/galaxy/api.py +33 -80
  27. ansible/galaxy/collection/__init__.py +4 -17
  28. ansible/galaxy/dependency_resolution/dataclasses.py +0 -10
  29. ansible/galaxy/dependency_resolution/providers.py +1 -2
  30. ansible/galaxy/role.py +1 -33
  31. ansible/inventory/manager.py +2 -3
  32. ansible/keyword_desc.yml +0 -3
  33. ansible/module_utils/_internal/_datatag/__init__.py +2 -10
  34. ansible/module_utils/_internal/_no_six.py +86 -0
  35. ansible/module_utils/_text.py +28 -8
  36. ansible/module_utils/ansible_release.py +2 -2
  37. ansible/module_utils/basic.py +27 -24
  38. ansible/module_utils/common/_collections_compat.py +11 -2
  39. ansible/module_utils/common/collections.py +8 -3
  40. ansible/module_utils/common/dict_transformations.py +1 -2
  41. ansible/module_utils/common/network.py +4 -2
  42. ansible/module_utils/common/parameters.py +32 -41
  43. ansible/module_utils/common/text/converters.py +109 -23
  44. ansible/module_utils/common/text/formatters.py +6 -2
  45. ansible/module_utils/common/validation.py +11 -9
  46. ansible/module_utils/connection.py +8 -3
  47. ansible/module_utils/facts/hardware/linux.py +23 -7
  48. ansible/module_utils/facts/hardware/netbsd.py +1 -1
  49. ansible/module_utils/facts/hardware/sunos.py +2 -1
  50. ansible/module_utils/facts/packages.py +6 -2
  51. ansible/module_utils/facts/system/distribution.py +2 -1
  52. ansible/module_utils/facts/system/env.py +6 -3
  53. ansible/module_utils/facts/system/local.py +3 -1
  54. ansible/module_utils/parsing/convert_bool.py +6 -2
  55. ansible/module_utils/service.py +2 -3
  56. ansible/module_utils/six/__init__.py +11 -6
  57. ansible/module_utils/urls.py +6 -2
  58. ansible/module_utils/yumdnf.py +0 -5
  59. ansible/modules/apt.py +18 -13
  60. ansible/modules/apt_repository.py +1 -1
  61. ansible/modules/assemble.py +5 -9
  62. ansible/modules/blockinfile.py +39 -23
  63. ansible/modules/cron.py +26 -35
  64. ansible/modules/deb822_repository.py +83 -12
  65. ansible/modules/dnf.py +3 -7
  66. ansible/modules/dnf5.py +4 -6
  67. ansible/modules/expect.py +0 -3
  68. ansible/modules/find.py +1 -2
  69. ansible/modules/get_url.py +1 -1
  70. ansible/modules/git.py +4 -5
  71. ansible/modules/include_vars.py +1 -1
  72. ansible/modules/lineinfile.py +71 -63
  73. ansible/modules/package_facts.py +1 -1
  74. ansible/modules/pip.py +8 -2
  75. ansible/modules/replace.py +6 -6
  76. ansible/modules/service.py +3 -4
  77. ansible/modules/stat.py +20 -0
  78. ansible/modules/uri.py +9 -10
  79. ansible/modules/user.py +1 -2
  80. ansible/modules/wait_for.py +2 -2
  81. ansible/modules/wait_for_connection.py +2 -1
  82. ansible/modules/yum_repository.py +1 -16
  83. ansible/parsing/dataloader.py +24 -31
  84. ansible/parsing/mod_args.py +3 -0
  85. ansible/parsing/vault/__init__.py +1 -2
  86. ansible/playbook/base.py +8 -56
  87. ansible/playbook/block.py +0 -60
  88. ansible/playbook/collectionsearch.py +1 -2
  89. ansible/playbook/handler.py +1 -7
  90. ansible/playbook/helpers.py +0 -7
  91. ansible/playbook/included_file.py +1 -1
  92. ansible/playbook/play.py +103 -37
  93. ansible/playbook/play_context.py +4 -0
  94. ansible/playbook/role/__init__.py +10 -65
  95. ansible/playbook/role/definition.py +3 -4
  96. ansible/playbook/role/include.py +2 -3
  97. ansible/playbook/role/metadata.py +1 -12
  98. ansible/playbook/role/requirement.py +1 -2
  99. ansible/playbook/role_include.py +1 -2
  100. ansible/playbook/taggable.py +16 -5
  101. ansible/playbook/task.py +51 -55
  102. ansible/plugins/action/__init__.py +20 -19
  103. ansible/plugins/action/add_host.py +1 -2
  104. ansible/plugins/action/fetch.py +2 -4
  105. ansible/plugins/action/group_by.py +1 -2
  106. ansible/plugins/action/include_vars.py +20 -22
  107. ansible/plugins/action/script.py +1 -3
  108. ansible/plugins/action/template.py +1 -2
  109. ansible/plugins/action/uri.py +4 -2
  110. ansible/plugins/cache/__init__.py +1 -0
  111. ansible/plugins/callback/__init__.py +13 -6
  112. ansible/plugins/connection/__init__.py +3 -7
  113. ansible/plugins/connection/local.py +2 -3
  114. ansible/plugins/connection/psrp.py +0 -2
  115. ansible/plugins/connection/ssh.py +2 -7
  116. ansible/plugins/connection/winrm.py +0 -2
  117. ansible/plugins/doc_fragments/result_format_callback.py +15 -0
  118. ansible/plugins/filter/core.py +4 -5
  119. ansible/plugins/filter/encryption.py +3 -27
  120. ansible/plugins/filter/mathstuff.py +1 -2
  121. ansible/plugins/filter/to_nice_yaml.yml +31 -3
  122. ansible/plugins/filter/to_yaml.yml +29 -12
  123. ansible/plugins/inventory/__init__.py +1 -2
  124. ansible/plugins/inventory/script.py +2 -1
  125. ansible/plugins/inventory/toml.py +3 -6
  126. ansible/plugins/inventory/yaml.py +1 -2
  127. ansible/plugins/list.py +10 -3
  128. ansible/plugins/loader.py +6 -6
  129. ansible/plugins/lookup/password.py +1 -2
  130. ansible/plugins/lookup/subelements.py +2 -3
  131. ansible/plugins/lookup/url.py +1 -1
  132. ansible/plugins/lookup/varnames.py +1 -2
  133. ansible/plugins/shell/__init__.py +9 -4
  134. ansible/plugins/shell/powershell.py +8 -24
  135. ansible/plugins/strategy/__init__.py +6 -3
  136. ansible/plugins/test/core.py +4 -1
  137. ansible/plugins/test/regex.yml +18 -6
  138. ansible/release.py +2 -2
  139. ansible/template/__init__.py +3 -7
  140. ansible/utils/collection_loader/_collection_config.py +5 -0
  141. ansible/utils/collection_loader/_collection_finder.py +11 -14
  142. ansible/utils/context_objects.py +7 -4
  143. ansible/utils/display.py +28 -167
  144. ansible/utils/encrypt.py +0 -5
  145. ansible/utils/helpers.py +6 -2
  146. ansible/utils/jsonrpc.py +7 -3
  147. ansible/utils/plugin_docs.py +49 -38
  148. ansible/utils/ssh_functions.py +0 -19
  149. ansible/utils/unsafe_proxy.py +7 -7
  150. ansible/vars/clean.py +2 -3
  151. ansible/vars/manager.py +27 -20
  152. ansible/vars/plugins.py +1 -31
  153. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/METADATA +3 -3
  154. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/RECORD +200 -200
  155. ansible_test/_data/completion/docker.txt +7 -7
  156. ansible_test/_data/completion/network.txt +0 -1
  157. ansible_test/_data/completion/remote.txt +4 -4
  158. ansible_test/_data/requirements/ansible-test.txt +1 -1
  159. ansible_test/_data/requirements/sanity.changelog.txt +1 -1
  160. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  161. ansible_test/_data/requirements/sanity.pylint.txt +4 -4
  162. ansible_test/_internal/cache.py +2 -5
  163. ansible_test/_internal/cli/compat.py +1 -1
  164. ansible_test/_internal/commands/coverage/combine.py +1 -3
  165. ansible_test/_internal/commands/integration/__init__.py +3 -7
  166. ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
  167. ansible_test/_internal/commands/integration/coverage.py +1 -3
  168. ansible_test/_internal/commands/integration/filters.py +5 -10
  169. ansible_test/_internal/commands/sanity/validate_modules.py +1 -5
  170. ansible_test/_internal/commands/units/__init__.py +1 -13
  171. ansible_test/_internal/completion.py +2 -5
  172. ansible_test/_internal/config.py +2 -7
  173. ansible_test/_internal/coverage_util.py +1 -1
  174. ansible_test/_internal/delegation.py +2 -0
  175. ansible_test/_internal/docker_util.py +1 -1
  176. ansible_test/_internal/host_profiles.py +6 -11
  177. ansible_test/_internal/provider/__init__.py +2 -5
  178. ansible_test/_internal/provisioning.py +2 -5
  179. ansible_test/_internal/pypi_proxy.py +1 -1
  180. ansible_test/_internal/target.py +2 -6
  181. ansible_test/_internal/thread.py +1 -4
  182. ansible_test/_internal/util.py +9 -14
  183. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +14 -19
  184. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +30 -27
  185. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +31 -18
  186. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +1 -2
  187. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +59 -71
  188. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -2
  189. ansible_test/_util/target/cli/ansible_test_cli_stub.py +4 -2
  190. ansible_test/_util/target/common/constants.py +2 -2
  191. ansible_test/_util/target/setup/bootstrap.sh +0 -6
  192. ansible/utils/py3compat.py +0 -27
  193. ansible_test/_data/pytest/config/legacy.ini +0 -4
  194. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/WHEEL +0 -0
  195. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/entry_points.txt +0 -0
  196. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/COPYING +0 -0
  197. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  198. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
  199. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  200. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  201. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  202. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/top_level.txt +0 -0
ansible/release.py CHANGED
@@ -17,6 +17,6 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- __version__ = '2.19.2'
20
+ __version__ = '2.20.0b1'
21
21
  __author__ = 'Ansible, Inc.'
22
- __codename__ = "What Is and What Should Never Be"
22
+ __codename__ = "Good Times Bad Times"
@@ -25,7 +25,6 @@ if _t.TYPE_CHECKING: # pragma: nocover
25
25
 
26
26
  _display: _t.Final[_Display] = _Display()
27
27
  _UNSET = _t.cast(_t.Any, object())
28
- _TTrustable = _t.TypeVar('_TTrustable', bound=str | _io.IOBase | _t.TextIO | _t.BinaryIO)
29
28
  _TRUSTABLE_TYPES = (str, _io.IOBase)
30
29
 
31
30
  AnsibleUndefined = _jinja_common.UndefinedMarker
@@ -361,7 +360,7 @@ def generate_ansible_template_vars(
361
360
  return _template_vars.generate_ansible_template_vars(path=path, fullpath=fullpath, dest_path=dest_path, include_ansible_managed=True)
362
361
 
363
362
 
364
- def trust_as_template(value: _TTrustable) -> _TTrustable:
363
+ def trust_as_template[T: str | _io.IOBase | _t.TextIO | _t.BinaryIO](value: T) -> T:
365
364
  """
366
365
  Returns `value` tagged as trusted for templating.
367
366
  Raises a `TypeError` if `value` is not a supported type.
@@ -385,10 +384,7 @@ def is_trusted_as_template(value: object) -> bool:
385
384
  return isinstance(value, _TRUSTABLE_TYPES) and _tags.TrustedAsTemplate.is_tagged_on(value)
386
385
 
387
386
 
388
- _TCallable = _t.TypeVar('_TCallable', bound=_t.Callable)
389
-
390
-
391
- def accept_args_markers(plugin: _TCallable) -> _TCallable:
387
+ def accept_args_markers[T: _t.Callable](plugin: T) -> T:
392
388
  """
393
389
  A decorator to mark a Jinja plugin as capable of handling `Marker` values for its top-level arguments.
394
390
  Non-decorated plugin invocation is skipped when a top-level argument is a `Marker`, with the first such value substituted as the plugin result.
@@ -399,7 +395,7 @@ def accept_args_markers(plugin: _TCallable) -> _TCallable:
399
395
  return plugin
400
396
 
401
397
 
402
- def accept_lazy_markers(plugin: _TCallable) -> _TCallable:
398
+ def accept_lazy_markers[T: _t.Callable](plugin: T) -> T:
403
399
  """
404
400
  A decorator to mark a Jinja plugin as capable of handling `Marker` values retrieved from lazy containers.
405
401
  Non-decorated plugins will trigger a `MarkerError` exception when attempting to retrieve a `Marker` from a lazy container.
@@ -62,6 +62,11 @@ class _AnsibleCollectionConfig(type):
62
62
  cls._require_finder()
63
63
  return [_to_text(p) for p in cls._collection_finder._n_collection_paths]
64
64
 
65
+ @property
66
+ def _internal_collections(cls):
67
+ cls._require_finder()
68
+ return cls._collection_finder._internal_collections
69
+
65
70
  @property
66
71
  def default_collection(cls):
67
72
  return cls._default_collection
@@ -26,20 +26,16 @@ from . import _to_bytes, _to_text
26
26
  from ._collection_config import AnsibleCollectionConfig
27
27
 
28
28
  try:
29
- try:
30
- # Available on Python >= 3.11
31
- # We ignore the import error that will trigger when running mypy with
32
- # older Python versions.
33
- from importlib.resources.abc import TraversableResources # type: ignore[import]
34
- except ImportError:
35
- # Used with Python 3.9 and 3.10 only
36
- # This member is still available as an alias up until Python 3.14 but
37
- # is deprecated as of Python 3.12.
38
- from importlib.abc import TraversableResources # deprecated: description='TraversableResources move' python_version='3.10'
29
+ # Available on Python >= 3.11
30
+ # We ignore the import error that will trigger when running mypy with
31
+ # older Python versions.
32
+ from importlib.resources.abc import TraversableResources # type: ignore[import]
39
33
  except ImportError:
40
- # Python < 3.9
41
- # deprecated: description='TraversableResources fallback' python_version='3.8'
42
- TraversableResources = object # type: ignore[assignment,misc]
34
+ # Used with Python 3.9 and 3.10 only
35
+ # This member is still available as an alias up until Python 3.14 but
36
+ # is deprecated as of Python 3.12.
37
+ # deprecated: description='TraversableResources move' python_version='3.10'
38
+ from importlib.abc import TraversableResources # type: ignore[assignment,no-redef]
43
39
 
44
40
  # NB: this supports import sanity test providing a different impl
45
41
  try:
@@ -186,7 +182,7 @@ class _AnsibleTraversableResources(TraversableResources):
186
182
 
187
183
 
188
184
  class _AnsibleCollectionFinder:
189
- def __init__(self, paths=None, scan_sys_paths=True):
185
+ def __init__(self, paths=None, scan_sys_paths=True, internal_collections=None):
190
186
  # TODO: accept metadata loader override
191
187
  self._ansible_pkg_path = _to_text(os.path.dirname(_to_bytes(sys.modules['ansible'].__file__)))
192
188
 
@@ -213,6 +209,7 @@ class _AnsibleCollectionFinder:
213
209
  if p not in good_paths and os.path.isdir(_to_bytes(os.path.join(p, 'ansible_collections'))):
214
210
  good_paths.append(p)
215
211
 
212
+ self._internal_collections = internal_collections
216
213
  self._n_configured_paths = good_paths
217
214
  self._n_cached_collection_paths = None
218
215
  self._n_cached_collection_qualified_paths = None
@@ -9,14 +9,14 @@ from __future__ import annotations
9
9
  from abc import ABCMeta
10
10
  from collections.abc import Container, Mapping, Sequence, Set
11
11
 
12
+ from ansible.module_utils._internal import _no_six
12
13
  from ansible.module_utils.common.collections import ImmutableDict
13
- from ansible.module_utils.six import add_metaclass, binary_type, text_type
14
14
  from ansible.utils.singleton import Singleton
15
15
 
16
16
 
17
17
  def _make_immutable(obj):
18
18
  """Recursively convert a container and objects inside of it into immutable data types"""
19
- if isinstance(obj, (text_type, binary_type)):
19
+ if isinstance(obj, (str, bytes)):
20
20
  # Strings first because they are also sequences
21
21
  return obj
22
22
  elif isinstance(obj, Mapping):
@@ -79,11 +79,14 @@ class CLIArgs(ImmutableDict):
79
79
  return cls(vars(options))
80
80
 
81
81
 
82
- @add_metaclass(_ABCSingleton)
83
- class GlobalCLIArgs(CLIArgs):
82
+ class GlobalCLIArgs(CLIArgs, metaclass=_ABCSingleton):
84
83
  """
85
84
  Globally hold a parsed copy of cli arguments.
86
85
 
87
86
  Only one of these exist per program as it is for global context
88
87
  """
89
88
  pass
89
+
90
+
91
+ def __getattr__(importable_name):
92
+ return _no_six.deprecate(importable_name, __name__, "binary_type", "text_type", "add_metaclass")
ansible/utils/display.py CHANGED
@@ -18,7 +18,6 @@
18
18
  from __future__ import annotations
19
19
 
20
20
  import contextlib
21
- import dataclasses
22
21
 
23
22
  try:
24
23
  import curses
@@ -52,12 +51,11 @@ from ansible import constants as C
52
51
  from ansible.constants import config
53
52
  from ansible.errors import AnsibleAssertionError, AnsiblePromptInterrupt, AnsiblePromptNoninteractive, AnsibleError
54
53
  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
54
+ from ansible._internal import _display_utils
55
+ from ansible.module_utils._internal import _deprecator, _messages, _no_six
57
56
  from ansible.module_utils.common.text.converters import to_bytes, to_text
58
57
  from ansible.module_utils.datatag import deprecator_from_collection_name
59
58
  from ansible._internal._datatag._tags import TrustedAsTemplate
60
- from ansible.module_utils.six import text_type
61
59
  from ansible.module_utils._internal import _traceback, _errors
62
60
  from ansible.utils.color import stringc
63
61
  from ansible.utils.multiprocessing import context as multiprocessing_context
@@ -67,8 +65,6 @@ if t.TYPE_CHECKING:
67
65
  # avoid circular import at runtime
68
66
  from ansible.executor.task_queue_manager import FinalQueue
69
67
 
70
- P = t.ParamSpec('P')
71
-
72
68
  _LIBC = ctypes.cdll.LoadLibrary(ctypes.util.find_library('c'))
73
69
  # Set argtypes, to avoid segfault if the wrong type is provided,
74
70
  # restype is assumed to be c_int
@@ -100,6 +96,17 @@ def _is_controller_traceback_enabled(event: _traceback.TracebackEvent) -> bool:
100
96
  _traceback._is_traceback_enabled = _is_controller_traceback_enabled
101
97
 
102
98
 
99
+ def _deprecation_warnings_enabled() -> bool:
100
+ """Return True if deprecation warnings are enabled for the current calling context, otherwise False."""
101
+ # DTFIX-FUTURE: move this capability into config using an AmbientContext-derived TaskContext (once it exists)
102
+ if warning_ctx := _display_utils.DeferredWarningContext.current(optional=True):
103
+ variables = warning_ctx._variables
104
+ else:
105
+ variables = None
106
+
107
+ return C.config.get_config_value('DEPRECATION_WARNINGS', variables=variables)
108
+
109
+
103
110
  def get_text_width(text: str) -> int:
104
111
  """Function that utilizes ``wcswidth`` or ``wcwidth`` to determine the
105
112
  number of columns used to display a text string.
@@ -108,7 +115,7 @@ def get_text_width(text: str) -> int:
108
115
  character and using wcwidth individually, falling back to a value of 0
109
116
  for non-printable wide characters.
110
117
  """
111
- if not isinstance(text, text_type):
118
+ if not isinstance(text, str):
112
119
  raise TypeError('get_text_width requires text, not %s' % type(text))
113
120
 
114
121
  try:
@@ -388,7 +395,7 @@ class Display(metaclass=Singleton):
388
395
  self.b_cowsay = b_cow_path
389
396
 
390
397
  @staticmethod
391
- def _proxy(
398
+ def _proxy[**P](
392
399
  func: c.Callable[t.Concatenate[Display, P], None]
393
400
  ) -> c.Callable[..., None]:
394
401
  @wraps(func)
@@ -582,7 +589,7 @@ class Display(metaclass=Singleton):
582
589
  version="2.23",
583
590
  )
584
591
 
585
- msg = self._get_deprecation_message_with_plugin_info(
592
+ msg = _display_utils.get_deprecation_message_with_plugin_info(
586
593
  msg=msg,
587
594
  version=version,
588
595
  removed=removed,
@@ -597,70 +604,6 @@ class Display(metaclass=Singleton):
597
604
 
598
605
  return msg
599
606
 
600
- def _get_deprecation_message_with_plugin_info(
601
- self,
602
- *,
603
- msg: str,
604
- version: str | None,
605
- removed: bool = False,
606
- date: str | None,
607
- deprecator: _messages.PluginInfo | None,
608
- ) -> str:
609
- """Internal use only. Return a deprecation message and help text for display."""
610
- # 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
611
-
612
- if removed:
613
- removal_fragment = 'This feature was removed'
614
- else:
615
- removal_fragment = 'This feature will be removed'
616
-
617
- if not deprecator or not deprecator.type:
618
- # indeterminate has no resolved_name or type
619
- # collections have a resolved_name but no type
620
- collection = deprecator.resolved_name if deprecator else None
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'
628
- else:
629
- parts = deprecator.resolved_name.split('.')
630
- plugin_name = parts[-1]
631
- plugin_type_name = str(deprecator.type) if deprecator.type is _messages.PluginType.MODULE else f'{deprecator.type} plugin'
632
-
633
- collection = '.'.join(parts[:2]) if len(parts) > 2 else None
634
- plugin_fragment = f'{plugin_type_name} {plugin_name!r}'
635
-
636
- if collection and plugin_fragment:
637
- plugin_fragment += ' in'
638
-
639
- if collection == 'ansible.builtin':
640
- collection_fragment = 'ansible-core'
641
- elif collection:
642
- collection_fragment = f'collection {collection!r}'
643
- else:
644
- collection_fragment = ''
645
-
646
- if not collection:
647
- when_fragment = 'in the future' if not removed else ''
648
- elif date:
649
- when_fragment = f'in a release after {date}'
650
- elif version:
651
- when_fragment = f'version {version}'
652
- else:
653
- when_fragment = 'in a future release' if not removed else ''
654
-
655
- if plugin_fragment or collection_fragment:
656
- from_fragment = 'from'
657
- else:
658
- from_fragment = ''
659
-
660
- deprecation_msg = ' '.join(f for f in [removal_fragment, from_fragment, plugin_fragment, collection_fragment, when_fragment] if f) + '.'
661
-
662
- return _join_sentences(msg, deprecation_msg)
663
-
664
607
  @staticmethod
665
608
  def _deduplicate(msg: str, messages: set[str]) -> bool:
666
609
  """
@@ -729,7 +672,7 @@ class Display(metaclass=Singleton):
729
672
  _skip_stackwalk = True
730
673
 
731
674
  if removed:
732
- formatted_msg = self._get_deprecation_message_with_plugin_info(
675
+ formatted_msg = _display_utils.get_deprecation_message_with_plugin_info(
733
676
  msg=msg,
734
677
  version=version,
735
678
  removed=removed,
@@ -756,7 +699,7 @@ class Display(metaclass=Singleton):
756
699
  deprecator=deprecator,
757
700
  )
758
701
 
759
- if warning_ctx := _DeferredWarningContext.current(optional=True):
702
+ if warning_ctx := _display_utils.DeferredWarningContext.current(optional=True):
760
703
  warning_ctx.capture(deprecation)
761
704
  return
762
705
 
@@ -769,12 +712,12 @@ class Display(metaclass=Singleton):
769
712
  # This is the post-proxy half of the `deprecated` implementation.
770
713
  # Any logic that must occur in the primary controller process needs to be implemented here.
771
714
 
772
- if not _DeferredWarningContext.deprecation_warnings_enabled():
715
+ if not _deprecation_warnings_enabled():
773
716
  return
774
717
 
775
718
  self.warning('Deprecation warnings can be disabled by setting `deprecation_warnings=False` in ansible.cfg.')
776
719
 
777
- msg = _format_message(warning, _traceback.is_traceback_enabled(_traceback.TracebackEvent.DEPRECATED))
720
+ msg = _display_utils.format_message(warning, _traceback.is_traceback_enabled(_traceback.TracebackEvent.DEPRECATED))
778
721
  msg = f'[DEPRECATION WARNING]: {msg}'
779
722
 
780
723
  if self._deduplicate(msg, self._deprecations):
@@ -812,7 +755,7 @@ class Display(metaclass=Singleton):
812
755
  ),
813
756
  )
814
757
 
815
- if warning_ctx := _DeferredWarningContext.current(optional=True):
758
+ if warning_ctx := _display_utils.DeferredWarningContext.current(optional=True):
816
759
  warning_ctx.capture(warning)
817
760
  return
818
761
 
@@ -825,7 +768,7 @@ class Display(metaclass=Singleton):
825
768
  # This is the post-proxy half of the `warning` implementation.
826
769
  # Any logic that must occur in the primary controller process needs to be implemented here.
827
770
 
828
- msg = _format_message(warning, _traceback.is_traceback_enabled(_traceback.TracebackEvent.WARNING))
771
+ msg = _display_utils.format_message(warning, _traceback.is_traceback_enabled(_traceback.TracebackEvent.WARNING))
829
772
  msg = f"[WARNING]: {msg}"
830
773
 
831
774
  if self._deduplicate(msg, self._warns):
@@ -915,7 +858,7 @@ class Display(metaclass=Singleton):
915
858
  event=event,
916
859
  )
917
860
 
918
- if warning_ctx := _DeferredWarningContext.current(optional=True):
861
+ if warning_ctx := _display_utils.DeferredWarningContext.current(optional=True):
919
862
  warning_ctx.capture(warning)
920
863
  return
921
864
 
@@ -952,7 +895,7 @@ class Display(metaclass=Singleton):
952
895
  # This is the post-proxy half of the `error` implementation.
953
896
  # Any logic that must occur in the primary controller process needs to be implemented here.
954
897
 
955
- msg = _format_message(error, _traceback.is_traceback_enabled(_traceback.TracebackEvent.ERROR))
898
+ msg = _display_utils.format_message(error, _traceback.is_traceback_enabled(_traceback.TracebackEvent.ERROR))
956
899
  msg = f'[ERROR]: {msg}'
957
900
 
958
901
  if self._deduplicate(msg, self._errors):
@@ -1173,92 +1116,6 @@ class Display(metaclass=Singleton):
1173
1116
  _display = Display()
1174
1117
 
1175
1118
 
1176
- class _DeferredWarningContext(_ambient_context.AmbientContextBase):
1177
- """
1178
- Calls to `Display.warning()` and `Display.deprecated()` within this context will cause the resulting warnings to be captured and not displayed.
1179
- The intended use is for task-initiated warnings to be recorded with the task result, which makes them visible to registered results, callbacks, etc.
1180
- The active display callback is responsible for communicating any warnings to the user.
1181
- """
1182
-
1183
- # DTFIX-FUTURE: once we start implementing nested scoped contexts for our own bookkeeping, this should be an interface facade that forwards to the nearest
1184
- # context that actually implements the warnings collection capability
1185
-
1186
- def __init__(self, *, variables: dict[str, object]) -> None:
1187
- self._variables = variables # DTFIX-FUTURE: move this to an AmbientContext-derived TaskContext (once it exists)
1188
- self._deprecation_warnings: list[_messages.DeprecationSummary] = []
1189
- self._warnings: list[_messages.WarningSummary] = []
1190
- self._seen: set[_messages.WarningSummary] = set()
1191
-
1192
- @classmethod
1193
- def deprecation_warnings_enabled(cls) -> bool:
1194
- """Return True if deprecation warnings are enabled for the current calling context, otherwise False."""
1195
- # DTFIX-FUTURE: move this capability into config using an AmbientContext-derived TaskContext (once it exists)
1196
- if warning_ctx := cls.current(optional=True):
1197
- variables = warning_ctx._variables
1198
- else:
1199
- variables = None
1200
-
1201
- return C.config.get_config_value('DEPRECATION_WARNINGS', variables=variables)
1202
-
1203
- def capture(self, warning: _messages.WarningSummary) -> None:
1204
- """Add the warning/deprecation to the context if it has not already been seen by this context."""
1205
- if warning in self._seen:
1206
- return
1207
-
1208
- self._seen.add(warning)
1209
-
1210
- if isinstance(warning, _messages.DeprecationSummary):
1211
- self._deprecation_warnings.append(warning)
1212
- else:
1213
- self._warnings.append(warning)
1214
-
1215
- def get_warnings(self) -> list[_messages.WarningSummary]:
1216
- """Return a list of the captured non-deprecation warnings."""
1217
- # DTFIX-FUTURE: return a read-only list proxy instead
1218
- return self._warnings
1219
-
1220
- def get_deprecation_warnings(self) -> list[_messages.DeprecationSummary]:
1221
- """Return a list of the captured deprecation warnings."""
1222
- # DTFIX-FUTURE: return a read-only list proxy instead
1223
- return self._deprecation_warnings
1224
-
1225
-
1226
- def _join_sentences(first: str | None, second: str | None) -> str:
1227
- """Join two sentences together."""
1228
- first = (first or '').strip()
1229
- second = (second or '').strip()
1230
-
1231
- if first and first[-1] not in ('!', '?', '.'):
1232
- first += '.'
1233
-
1234
- if second and second[-1] not in ('!', '?', '.'):
1235
- second += '.'
1236
-
1237
- if first and not second:
1238
- return first
1239
-
1240
- if not first and second:
1241
- return second
1242
-
1243
- return ' '.join((first, second))
1244
-
1245
-
1246
- def _format_message(summary: _messages.SummaryBase, include_traceback: bool) -> str:
1247
- if isinstance(summary, _messages.DeprecationSummary):
1248
- deprecation_message = _display._get_deprecation_message_with_plugin_info(
1249
- msg=summary.event.msg,
1250
- version=summary.version,
1251
- date=summary.date,
1252
- deprecator=summary.deprecator,
1253
- )
1254
-
1255
- event = dataclasses.replace(summary.event, msg=deprecation_message)
1256
- else:
1257
- event = summary.event
1258
-
1259
- return _event_formatting.format_event(event, include_traceback)
1260
-
1261
-
1262
1119
  def _report_config_warnings(deprecator: _messages.PluginInfo) -> None:
1263
1120
  """Called by config to report warnings/deprecations collected during a config parse."""
1264
1121
  while config._errors:
@@ -1284,3 +1141,7 @@ def _report_config_warnings(deprecator: _messages.PluginInfo) -> None:
1284
1141
  # emit any warnings or deprecations
1285
1142
  # in the event config fails before display is up, we'll lose warnings -- but that's OK, since everything is broken anyway
1286
1143
  _report_config_warnings(_deprecator.ANSIBLE_CORE_DEPRECATOR)
1144
+
1145
+
1146
+ def __getattr__(importable_name):
1147
+ return _no_six.deprecate(importable_name, __name__, "text_type")
ansible/utils/encrypt.py CHANGED
@@ -176,11 +176,6 @@ class PasslibHash(BaseHash):
176
176
  return to_text(result, errors='strict')
177
177
 
178
178
 
179
- def passlib_or_crypt(secret, algorithm, salt=None, salt_size=None, rounds=None, ident=None):
180
- display.deprecated("passlib_or_crypt API is deprecated in favor of do_encrypt", version='2.20')
181
- return do_encrypt(secret, algorithm, salt=salt, salt_size=salt_size, rounds=rounds, ident=ident)
182
-
183
-
184
179
  def do_encrypt(result, encrypt, salt_size=None, salt=None, ident=None, rounds=None):
185
180
  if PASSLIB_AVAILABLE:
186
181
  return PasslibHash(encrypt).hash(result, salt=salt, salt_size=salt_size, rounds=rounds, ident=ident)
ansible/utils/helpers.py CHANGED
@@ -17,7 +17,7 @@
17
17
 
18
18
  from __future__ import annotations
19
19
 
20
- from ansible.module_utils.six import string_types
20
+ from ansible.module_utils._internal import _no_six
21
21
 
22
22
 
23
23
  def pct_to_int(value, num_items, min_value=1):
@@ -25,7 +25,7 @@ def pct_to_int(value, num_items, min_value=1):
25
25
  Converts a given value to a percentage if specified as "x%",
26
26
  otherwise converts the given value to an integer.
27
27
  """
28
- if isinstance(value, string_types) and value.endswith('%'):
28
+ if isinstance(value, str) and value.endswith('%'):
29
29
  value_pct = int(value.replace("%", ""))
30
30
  return int((value_pct / 100.0) * num_items) or min_value
31
31
  else:
@@ -47,3 +47,7 @@ def deduplicate_list(original_list):
47
47
  """
48
48
  seen = set()
49
49
  return [x for x in original_list if x not in seen and not seen.add(x)]
50
+
51
+
52
+ def __getattr__(importable_name):
53
+ return _no_six.deprecate(importable_name, __name__, "string_types")
ansible/utils/jsonrpc.py CHANGED
@@ -7,9 +7,9 @@ import json
7
7
  import pickle
8
8
  import traceback
9
9
 
10
+ from ansible.module_utils._internal import _no_six
10
11
  from ansible.module_utils.common.text.converters import to_text
11
12
  from ansible.module_utils.connection import ConnectionError
12
- from ansible.module_utils.six import binary_type, text_type
13
13
  from ansible.utils.display import Display
14
14
 
15
15
  display = Display()
@@ -79,9 +79,9 @@ class JsonRpcServer(object):
79
79
 
80
80
  def response(self, result=None):
81
81
  response = self.header()
82
- if isinstance(result, binary_type):
82
+ if isinstance(result, bytes):
83
83
  result = to_text(result)
84
- if not isinstance(result, text_type):
84
+ if not isinstance(result, str):
85
85
  response["result_type"] = "pickle"
86
86
  result = to_text(pickle.dumps(result), errors='surrogateescape')
87
87
  response['result'] = result
@@ -110,3 +110,7 @@ class JsonRpcServer(object):
110
110
 
111
111
  def internal_error(self, data=None):
112
112
  return self.error(-32603, 'Internal error', data)
113
+
114
+
115
+ def __getattr__(importable_name):
116
+ return _no_six.deprecate(importable_name, __name__, "binary_type", "text_type")