ansible-core 2.19.2rc1__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.
- ansible/_internal/__init__.py +1 -4
- ansible/_internal/_ansiballz/_builder.py +1 -3
- ansible/_internal/_collection_proxy.py +7 -9
- ansible/_internal/_display_utils.py +145 -0
- ansible/_internal/_json/__init__.py +3 -4
- ansible/_internal/_templating/_engine.py +1 -1
- ansible/_internal/_templating/_jinja_plugins.py +1 -2
- ansible/_internal/_wrapt.py +105 -301
- ansible/cli/__init__.py +11 -10
- ansible/cli/adhoc.py +1 -2
- ansible/cli/arguments/option_helpers.py +1 -1
- ansible/cli/config.py +5 -6
- ansible/cli/doc.py +67 -67
- ansible/cli/galaxy.py +15 -24
- ansible/cli/inventory.py +0 -1
- ansible/cli/playbook.py +0 -1
- ansible/cli/pull.py +0 -1
- ansible/cli/scripts/ansible_connection_cli_stub.py +1 -1
- ansible/config/base.yml +1 -25
- ansible/config/manager.py +0 -2
- ansible/executor/play_iterator.py +42 -20
- ansible/executor/playbook_executor.py +0 -9
- ansible/executor/powershell/async_watchdog.ps1 +24 -4
- ansible/executor/task_executor.py +32 -22
- ansible/executor/task_queue_manager.py +1 -3
- ansible/galaxy/api.py +33 -80
- ansible/galaxy/collection/__init__.py +4 -17
- ansible/galaxy/dependency_resolution/dataclasses.py +0 -10
- ansible/galaxy/dependency_resolution/providers.py +1 -2
- ansible/galaxy/role.py +1 -33
- ansible/inventory/manager.py +2 -3
- ansible/keyword_desc.yml +0 -3
- ansible/module_utils/_internal/_datatag/__init__.py +2 -10
- ansible/module_utils/_internal/_no_six.py +86 -0
- ansible/module_utils/_text.py +28 -8
- ansible/module_utils/ansible_release.py +2 -2
- ansible/module_utils/basic.py +27 -24
- ansible/module_utils/common/_collections_compat.py +11 -2
- ansible/module_utils/common/collections.py +8 -3
- ansible/module_utils/common/dict_transformations.py +1 -2
- ansible/module_utils/common/network.py +4 -2
- ansible/module_utils/common/parameters.py +32 -41
- ansible/module_utils/common/text/converters.py +109 -23
- ansible/module_utils/common/text/formatters.py +6 -2
- ansible/module_utils/common/validation.py +11 -9
- ansible/module_utils/connection.py +8 -3
- ansible/module_utils/facts/hardware/linux.py +23 -7
- ansible/module_utils/facts/hardware/netbsd.py +1 -1
- ansible/module_utils/facts/hardware/sunos.py +2 -1
- ansible/module_utils/facts/packages.py +6 -2
- ansible/module_utils/facts/system/distribution.py +2 -1
- ansible/module_utils/facts/system/env.py +6 -3
- ansible/module_utils/facts/system/local.py +3 -1
- ansible/module_utils/parsing/convert_bool.py +6 -2
- ansible/module_utils/service.py +2 -3
- ansible/module_utils/six/__init__.py +11 -6
- ansible/module_utils/urls.py +6 -2
- ansible/module_utils/yumdnf.py +0 -5
- ansible/modules/apt.py +18 -13
- ansible/modules/apt_repository.py +1 -1
- ansible/modules/assemble.py +5 -9
- ansible/modules/blockinfile.py +39 -23
- ansible/modules/cron.py +26 -35
- ansible/modules/deb822_repository.py +83 -12
- ansible/modules/dnf.py +3 -7
- ansible/modules/dnf5.py +4 -6
- ansible/modules/expect.py +0 -3
- ansible/modules/find.py +1 -2
- ansible/modules/get_url.py +1 -1
- ansible/modules/git.py +4 -5
- ansible/modules/include_vars.py +1 -1
- ansible/modules/lineinfile.py +71 -63
- ansible/modules/package_facts.py +1 -1
- ansible/modules/pip.py +8 -2
- ansible/modules/replace.py +6 -6
- ansible/modules/service.py +3 -4
- ansible/modules/stat.py +20 -0
- ansible/modules/uri.py +9 -10
- ansible/modules/user.py +1 -2
- ansible/modules/wait_for.py +2 -2
- ansible/modules/wait_for_connection.py +2 -1
- ansible/modules/yum_repository.py +1 -16
- ansible/parsing/dataloader.py +24 -31
- ansible/parsing/mod_args.py +3 -0
- ansible/parsing/vault/__init__.py +1 -2
- ansible/playbook/base.py +8 -56
- ansible/playbook/block.py +0 -60
- ansible/playbook/collectionsearch.py +1 -2
- ansible/playbook/handler.py +1 -7
- ansible/playbook/helpers.py +0 -7
- ansible/playbook/included_file.py +1 -1
- ansible/playbook/play.py +103 -37
- ansible/playbook/play_context.py +4 -0
- ansible/playbook/role/__init__.py +10 -65
- ansible/playbook/role/definition.py +3 -4
- ansible/playbook/role/include.py +2 -3
- ansible/playbook/role/metadata.py +1 -12
- ansible/playbook/role/requirement.py +1 -2
- ansible/playbook/role_include.py +1 -2
- ansible/playbook/taggable.py +16 -5
- ansible/playbook/task.py +51 -55
- ansible/plugins/action/__init__.py +20 -19
- ansible/plugins/action/add_host.py +1 -2
- ansible/plugins/action/fetch.py +2 -4
- ansible/plugins/action/group_by.py +1 -2
- ansible/plugins/action/include_vars.py +20 -22
- ansible/plugins/action/script.py +1 -3
- ansible/plugins/action/template.py +1 -2
- ansible/plugins/action/uri.py +4 -2
- ansible/plugins/cache/__init__.py +1 -0
- ansible/plugins/callback/__init__.py +13 -6
- ansible/plugins/connection/__init__.py +3 -7
- ansible/plugins/connection/local.py +2 -3
- ansible/plugins/connection/psrp.py +0 -2
- ansible/plugins/connection/ssh.py +2 -7
- ansible/plugins/connection/winrm.py +0 -2
- ansible/plugins/doc_fragments/result_format_callback.py +15 -0
- ansible/plugins/filter/core.py +4 -5
- ansible/plugins/filter/encryption.py +3 -27
- ansible/plugins/filter/mathstuff.py +1 -2
- ansible/plugins/filter/to_nice_yaml.yml +31 -3
- ansible/plugins/filter/to_yaml.yml +29 -12
- ansible/plugins/inventory/__init__.py +1 -2
- ansible/plugins/inventory/script.py +2 -1
- ansible/plugins/inventory/toml.py +3 -6
- ansible/plugins/inventory/yaml.py +1 -2
- ansible/plugins/list.py +10 -3
- ansible/plugins/loader.py +6 -6
- ansible/plugins/lookup/password.py +1 -2
- ansible/plugins/lookup/subelements.py +2 -3
- ansible/plugins/lookup/url.py +1 -1
- ansible/plugins/lookup/varnames.py +1 -2
- ansible/plugins/shell/__init__.py +9 -4
- ansible/plugins/shell/powershell.py +8 -24
- ansible/plugins/strategy/__init__.py +6 -3
- ansible/plugins/test/core.py +4 -1
- ansible/plugins/test/regex.yml +18 -6
- ansible/release.py +2 -2
- ansible/template/__init__.py +3 -7
- ansible/utils/collection_loader/_collection_config.py +5 -0
- ansible/utils/collection_loader/_collection_finder.py +11 -14
- ansible/utils/context_objects.py +7 -4
- ansible/utils/display.py +28 -167
- ansible/utils/encrypt.py +0 -5
- ansible/utils/helpers.py +6 -2
- ansible/utils/jsonrpc.py +7 -3
- ansible/utils/plugin_docs.py +49 -38
- ansible/utils/ssh_functions.py +0 -19
- ansible/utils/unsafe_proxy.py +7 -7
- ansible/vars/clean.py +2 -3
- ansible/vars/manager.py +27 -20
- ansible/vars/plugins.py +1 -31
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/METADATA +3 -3
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/RECORD +200 -200
- ansible_test/_data/completion/docker.txt +7 -7
- ansible_test/_data/completion/network.txt +0 -1
- ansible_test/_data/completion/remote.txt +4 -4
- ansible_test/_data/requirements/ansible-test.txt +1 -1
- ansible_test/_data/requirements/sanity.changelog.txt +1 -1
- ansible_test/_data/requirements/sanity.pep8.txt +1 -1
- ansible_test/_data/requirements/sanity.pylint.txt +4 -4
- ansible_test/_internal/cache.py +2 -5
- ansible_test/_internal/cli/compat.py +1 -1
- ansible_test/_internal/commands/coverage/combine.py +1 -3
- ansible_test/_internal/commands/integration/__init__.py +3 -7
- ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
- ansible_test/_internal/commands/integration/coverage.py +1 -3
- ansible_test/_internal/commands/integration/filters.py +5 -10
- ansible_test/_internal/commands/sanity/validate_modules.py +1 -5
- ansible_test/_internal/commands/units/__init__.py +1 -13
- ansible_test/_internal/completion.py +2 -5
- ansible_test/_internal/config.py +2 -7
- ansible_test/_internal/coverage_util.py +1 -1
- ansible_test/_internal/delegation.py +2 -0
- ansible_test/_internal/docker_util.py +1 -1
- ansible_test/_internal/host_profiles.py +6 -11
- ansible_test/_internal/provider/__init__.py +2 -5
- ansible_test/_internal/provisioning.py +2 -5
- ansible_test/_internal/pypi_proxy.py +1 -1
- ansible_test/_internal/target.py +2 -6
- ansible_test/_internal/thread.py +1 -4
- ansible_test/_internal/util.py +9 -14
- ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +14 -19
- ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +30 -27
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +31 -18
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +1 -2
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +59 -71
- ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -2
- ansible_test/_util/target/cli/ansible_test_cli_stub.py +4 -2
- ansible_test/_util/target/common/constants.py +2 -2
- ansible_test/_util/target/setup/bootstrap.sh +0 -6
- ansible/utils/py3compat.py +0 -27
- ansible_test/_data/pytest/config/legacy.ini +0 -4
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/WHEEL +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/entry_points.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/COPYING +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/Apache-License.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/MIT-license.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/PSF-license.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
- {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/top_level.txt +0 -0
ansible/release.py
CHANGED
ansible/template/__init__.py
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
|
41
|
-
#
|
|
42
|
-
|
|
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
|
ansible/utils/context_objects.py
CHANGED
|
@@ -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, (
|
|
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
|
-
|
|
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
|
|
56
|
-
from ansible.module_utils._internal import
|
|
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,
|
|
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 =
|
|
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 =
|
|
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 :=
|
|
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
|
|
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 =
|
|
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 :=
|
|
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 =
|
|
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 :=
|
|
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 =
|
|
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.
|
|
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,
|
|
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,
|
|
82
|
+
if isinstance(result, bytes):
|
|
83
83
|
result = to_text(result)
|
|
84
|
-
if not isinstance(result,
|
|
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")
|