ansible-core 2.19.4rc1__py3-none-any.whl → 2.20.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ansible-core might be problematic. Click here for more details.

Files changed (215) 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/_json/__init__.py +3 -4
  5. ansible/_internal/_templating/_engine.py +1 -1
  6. ansible/_internal/_templating/_jinja_plugins.py +1 -2
  7. ansible/_internal/_wrapt.py +105 -301
  8. ansible/cli/__init__.py +11 -10
  9. ansible/cli/adhoc.py +1 -2
  10. ansible/cli/arguments/option_helpers.py +1 -1
  11. ansible/cli/config.py +5 -6
  12. ansible/cli/doc.py +67 -67
  13. ansible/cli/galaxy.py +15 -24
  14. ansible/cli/inventory.py +0 -1
  15. ansible/cli/playbook.py +0 -1
  16. ansible/cli/pull.py +0 -1
  17. ansible/cli/scripts/ansible_connection_cli_stub.py +1 -1
  18. ansible/config/base.yml +1 -25
  19. ansible/config/manager.py +0 -2
  20. ansible/executor/play_iterator.py +42 -20
  21. ansible/executor/playbook_executor.py +0 -9
  22. ansible/executor/task_executor.py +26 -18
  23. ansible/executor/task_queue_manager.py +1 -3
  24. ansible/galaxy/api.py +33 -80
  25. ansible/galaxy/collection/__init__.py +11 -21
  26. ansible/galaxy/dependency_resolution/__init__.py +10 -9
  27. ansible/galaxy/dependency_resolution/dataclasses.py +86 -70
  28. ansible/galaxy/dependency_resolution/providers.py +54 -134
  29. ansible/galaxy/dependency_resolution/versioning.py +2 -4
  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 +26 -23
  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/yumdnf.py +0 -5
  58. ansible/modules/apt.py +18 -13
  59. ansible/modules/apt_repository.py +1 -1
  60. ansible/modules/assemble.py +5 -9
  61. ansible/modules/blockinfile.py +39 -23
  62. ansible/modules/cron.py +26 -35
  63. ansible/modules/deb822_repository.py +83 -12
  64. ansible/modules/dnf.py +3 -7
  65. ansible/modules/dnf5.py +4 -6
  66. ansible/modules/expect.py +0 -3
  67. ansible/modules/find.py +1 -2
  68. ansible/modules/get_url.py +1 -1
  69. ansible/modules/git.py +4 -5
  70. ansible/modules/include_vars.py +1 -1
  71. ansible/modules/known_hosts.py +7 -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/vault/__init__.py +1 -2
  85. ansible/playbook/base.py +8 -56
  86. ansible/playbook/block.py +0 -60
  87. ansible/playbook/collectionsearch.py +1 -2
  88. ansible/playbook/handler.py +1 -7
  89. ansible/playbook/helpers.py +0 -7
  90. ansible/playbook/included_file.py +1 -1
  91. ansible/playbook/play.py +102 -36
  92. ansible/playbook/play_context.py +4 -0
  93. ansible/playbook/role/__init__.py +10 -65
  94. ansible/playbook/role/definition.py +3 -4
  95. ansible/playbook/role/include.py +2 -3
  96. ansible/playbook/role/metadata.py +1 -12
  97. ansible/playbook/role/requirement.py +1 -2
  98. ansible/playbook/role_include.py +1 -2
  99. ansible/playbook/taggable.py +16 -5
  100. ansible/playbook/task.py +11 -50
  101. ansible/plugins/action/__init__.py +20 -19
  102. ansible/plugins/action/add_host.py +1 -2
  103. ansible/plugins/action/fetch.py +3 -5
  104. ansible/plugins/action/group_by.py +1 -2
  105. ansible/plugins/action/include_vars.py +20 -22
  106. ansible/plugins/action/script.py +1 -3
  107. ansible/plugins/action/template.py +1 -2
  108. ansible/plugins/action/uri.py +4 -2
  109. ansible/plugins/cache/__init__.py +1 -0
  110. ansible/plugins/callback/__init__.py +13 -6
  111. ansible/plugins/connection/__init__.py +3 -7
  112. ansible/plugins/connection/local.py +2 -3
  113. ansible/plugins/connection/psrp.py +0 -2
  114. ansible/plugins/connection/ssh.py +2 -7
  115. ansible/plugins/connection/winrm.py +0 -2
  116. ansible/plugins/doc_fragments/result_format_callback.py +15 -0
  117. ansible/plugins/filter/core.py +4 -5
  118. ansible/plugins/filter/encryption.py +3 -27
  119. ansible/plugins/filter/mathstuff.py +1 -2
  120. ansible/plugins/filter/to_nice_yaml.yml +31 -3
  121. ansible/plugins/filter/to_yaml.yml +29 -12
  122. ansible/plugins/inventory/__init__.py +1 -2
  123. ansible/plugins/inventory/toml.py +3 -6
  124. ansible/plugins/inventory/yaml.py +1 -2
  125. ansible/plugins/loader.py +3 -4
  126. ansible/plugins/lookup/password.py +1 -2
  127. ansible/plugins/lookup/subelements.py +2 -3
  128. ansible/plugins/lookup/url.py +1 -1
  129. ansible/plugins/lookup/varnames.py +1 -2
  130. ansible/plugins/shell/__init__.py +9 -4
  131. ansible/plugins/shell/powershell.py +8 -24
  132. ansible/plugins/strategy/__init__.py +5 -2
  133. ansible/plugins/test/core.py +4 -1
  134. ansible/plugins/test/falsy.yml +1 -1
  135. ansible/plugins/test/regex.yml +18 -6
  136. ansible/plugins/test/truthy.yml +1 -1
  137. ansible/release.py +2 -2
  138. ansible/template/__init__.py +3 -7
  139. ansible/utils/collection_loader/_collection_config.py +5 -0
  140. ansible/utils/collection_loader/_collection_finder.py +11 -14
  141. ansible/utils/context_objects.py +7 -4
  142. ansible/utils/display.py +7 -6
  143. ansible/utils/encrypt.py +0 -5
  144. ansible/utils/helpers.py +6 -2
  145. ansible/utils/jsonrpc.py +7 -3
  146. ansible/utils/plugin_docs.py +49 -38
  147. ansible/utils/ssh_functions.py +0 -19
  148. ansible/utils/unsafe_proxy.py +7 -7
  149. ansible/vars/clean.py +2 -3
  150. ansible/vars/manager.py +28 -22
  151. ansible/vars/plugins.py +1 -31
  152. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/METADATA +4 -4
  153. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/RECORD +213 -214
  154. ansible_test/_data/completion/docker.txt +7 -7
  155. ansible_test/_data/completion/network.txt +0 -1
  156. ansible_test/_data/completion/remote.txt +4 -4
  157. ansible_test/_data/requirements/ansible-test.txt +1 -1
  158. ansible_test/_data/requirements/ansible.txt +1 -1
  159. ansible_test/_data/requirements/sanity.ansible-doc.txt +2 -2
  160. ansible_test/_data/requirements/sanity.changelog.txt +2 -2
  161. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  162. ansible_test/_data/requirements/sanity.import.txt +1 -1
  163. ansible_test/_data/requirements/sanity.integration-aliases.txt +1 -1
  164. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  165. ansible_test/_data/requirements/sanity.pylint.txt +6 -6
  166. ansible_test/_data/requirements/sanity.runtime-metadata.txt +1 -1
  167. ansible_test/_data/requirements/sanity.validate-modules.txt +2 -2
  168. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  169. ansible_test/_internal/cache.py +2 -5
  170. ansible_test/_internal/cli/compat.py +1 -1
  171. ansible_test/_internal/commands/coverage/combine.py +1 -3
  172. ansible_test/_internal/commands/integration/__init__.py +3 -7
  173. ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
  174. ansible_test/_internal/commands/integration/coverage.py +1 -3
  175. ansible_test/_internal/commands/integration/filters.py +5 -10
  176. ansible_test/_internal/commands/sanity/pylint.py +11 -0
  177. ansible_test/_internal/commands/sanity/validate_modules.py +1 -5
  178. ansible_test/_internal/commands/units/__init__.py +1 -13
  179. ansible_test/_internal/compat/packaging.py +2 -2
  180. ansible_test/_internal/compat/yaml.py +2 -2
  181. ansible_test/_internal/completion.py +2 -5
  182. ansible_test/_internal/config.py +2 -7
  183. ansible_test/_internal/coverage_util.py +1 -1
  184. ansible_test/_internal/delegation.py +2 -0
  185. ansible_test/_internal/docker_util.py +1 -1
  186. ansible_test/_internal/host_profiles.py +6 -11
  187. ansible_test/_internal/provider/__init__.py +2 -5
  188. ansible_test/_internal/provisioning.py +2 -5
  189. ansible_test/_internal/pypi_proxy.py +1 -1
  190. ansible_test/_internal/python_requirements.py +1 -1
  191. ansible_test/_internal/target.py +2 -6
  192. ansible_test/_internal/thread.py +1 -4
  193. ansible_test/_internal/util.py +9 -14
  194. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +14 -19
  195. ansible_test/_util/controller/sanity/pylint/plugins/deprecated_calls.py +48 -45
  196. ansible_test/_util/controller/sanity/pylint/plugins/string_format.py +9 -7
  197. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +51 -37
  198. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +31 -18
  199. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +1 -2
  200. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +59 -71
  201. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -2
  202. ansible_test/_util/target/cli/ansible_test_cli_stub.py +4 -2
  203. ansible_test/_util/target/common/constants.py +2 -2
  204. ansible_test/_util/target/setup/bootstrap.sh +0 -6
  205. ansible/utils/py3compat.py +0 -27
  206. ansible_test/_data/pytest/config/legacy.ini +0 -4
  207. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/WHEEL +0 -0
  208. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/entry_points.txt +0 -0
  209. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/COPYING +0 -0
  210. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  211. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
  212. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  213. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  214. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  215. {ansible_core-2.19.4rc1.dist-info → ansible_core-2.20.0.dist-info}/top_level.txt +0 -0
@@ -65,7 +65,7 @@ def walk_completion_targets(targets: c.Iterable[CompletionTarget], prefix: str,
65
65
  return tuple(sorted(matches))
66
66
 
67
67
 
68
- def walk_internal_targets(
68
+ def walk_internal_targets[TCompletionTarget: CompletionTarget](
69
69
  targets: c.Iterable[TCompletionTarget],
70
70
  includes: t.Optional[list[str]] = None,
71
71
  excludes: t.Optional[list[str]] = None,
@@ -87,7 +87,7 @@ def walk_internal_targets(
87
87
  return tuple(sorted(internal_targets, key=lambda sort_target: sort_target.name))
88
88
 
89
89
 
90
- def filter_targets(
90
+ def filter_targets[TCompletionTarget: CompletionTarget](
91
91
  targets: c.Iterable[TCompletionTarget],
92
92
  patterns: list[str],
93
93
  include: bool = True,
@@ -711,7 +711,3 @@ class TargetPatternsNotMatched(ApplicationError):
711
711
  message = 'Target pattern not matched: %s' % self.patterns[0]
712
712
 
713
713
  super().__init__(message)
714
-
715
-
716
- TCompletionTarget = t.TypeVar('TCompletionTarget', bound=CompletionTarget)
717
- TIntegrationTarget = t.TypeVar('TIntegrationTarget', bound=IntegrationTarget)
@@ -11,9 +11,6 @@ import queue
11
11
  import typing as t
12
12
 
13
13
 
14
- TCallable = t.TypeVar('TCallable', bound=t.Callable[..., t.Any])
15
-
16
-
17
14
  class WrappedThread(threading.Thread):
18
15
  """Wrapper around Thread which captures results and exceptions."""
19
16
 
@@ -50,7 +47,7 @@ class WrappedThread(threading.Thread):
50
47
  return result
51
48
 
52
49
 
53
- def mutex(func: TCallable) -> TCallable:
50
+ def mutex[TCallable: t.Callable[..., t.Any]](func: TCallable) -> TCallable:
54
51
  """Enforce exclusive access on a decorated function."""
55
52
  lock = threading.Lock()
56
53
 
@@ -57,11 +57,6 @@ from .constants import (
57
57
  SUPPORTED_PYTHON_VERSIONS,
58
58
  )
59
59
 
60
- C = t.TypeVar('C')
61
- TBase = t.TypeVar('TBase')
62
- TKey = t.TypeVar('TKey')
63
- TValue = t.TypeVar('TValue')
64
-
65
60
  PYTHON_PATHS: dict[str, str] = {}
66
61
 
67
62
  COVERAGE_CONFIG_NAME = 'coveragerc'
@@ -180,7 +175,7 @@ def is_valid_identifier(value: str) -> bool:
180
175
  return value.isidentifier() and not keyword.iskeyword(value)
181
176
 
182
177
 
183
- def cache(func: c.Callable[[], TValue]) -> c.Callable[[], TValue]:
178
+ def cache[TValue](func: c.Callable[[], TValue]) -> c.Callable[[], TValue]:
184
179
  """Enforce exclusive access on a decorated function and cache the result."""
185
180
  storage: dict[None, TValue] = {}
186
181
  sentinel = object()
@@ -313,7 +308,7 @@ def read_lines_without_comments(path: str, remove_blank_lines: bool = False, opt
313
308
  return lines
314
309
 
315
310
 
316
- def exclude_none_values(data: dict[TKey, t.Optional[TValue]]) -> dict[TKey, TValue]:
311
+ def exclude_none_values[TKey, TValue](data: dict[TKey, t.Optional[TValue]]) -> dict[TKey, TValue]:
317
312
  """Return the provided dictionary with any None values excluded."""
318
313
  return dict((key, value) for key, value in data.items() if value is not None)
319
314
 
@@ -1059,7 +1054,7 @@ def format_command_output(stdout: str | None, stderr: str | None) -> str:
1059
1054
  return message
1060
1055
 
1061
1056
 
1062
- def retry(func: t.Callable[..., TValue], ex_type: t.Type[BaseException] = SubprocessError, sleep: int = 10, attempts: int = 10, warn: bool = True) -> TValue:
1057
+ def retry[T](func: t.Callable[..., T], ex_type: t.Type[BaseException] = SubprocessError, sleep: int = 10, attempts: int = 10, warn: bool = True) -> T:
1063
1058
  """Retry the specified function on failure."""
1064
1059
  for dummy in range(1, attempts):
1065
1060
  try:
@@ -1092,7 +1087,7 @@ def parse_to_list_of_dict(pattern: str, value: str) -> list[dict[str, str]]:
1092
1087
  return matched
1093
1088
 
1094
1089
 
1095
- def get_subclasses(class_type: t.Type[C]) -> list[t.Type[C]]:
1090
+ def get_subclasses[C](class_type: t.Type[C]) -> list[t.Type[C]]:
1096
1091
  """Returns a list of types that are concrete subclasses of the given type."""
1097
1092
  subclasses: set[t.Type[C]] = set()
1098
1093
  queue: list[t.Type[C]] = [class_type]
@@ -1168,7 +1163,7 @@ def import_plugins(directory: str, root: t.Optional[str] = None) -> None:
1168
1163
  load_module(module_path, name)
1169
1164
 
1170
1165
 
1171
- def load_plugins(base_type: t.Type[C], database: dict[str, t.Type[C]]) -> None:
1166
+ def load_plugins[C](base_type: t.Type[C], database: dict[str, t.Type[C]]) -> None:
1172
1167
  """
1173
1168
  Load plugins of the specified type and track them in the specified database.
1174
1169
  Only plugins which have already been imported will be loaded.
@@ -1195,19 +1190,19 @@ def sanitize_host_name(name: str) -> str:
1195
1190
  return re.sub('[^A-Za-z0-9]+', '-', name)[:63].strip('-')
1196
1191
 
1197
1192
 
1198
- def get_generic_type(base_type: t.Type, generic_base_type: t.Type[TValue]) -> t.Optional[t.Type[TValue]]:
1193
+ def get_generic_type[TValue](base_type: t.Type, generic_base_type: t.Type[TValue]) -> t.Optional[t.Type[TValue]]:
1199
1194
  """Return the generic type arg derived from the generic_base_type type that is associated with the base_type type, if any, otherwise return None."""
1200
1195
  # noinspection PyUnresolvedReferences
1201
1196
  type_arg = t.get_args(base_type.__orig_bases__[0])[0]
1202
1197
  return None if isinstance(type_arg, generic_base_type) else type_arg
1203
1198
 
1204
1199
 
1205
- def get_type_associations(base_type: t.Type[TBase], generic_base_type: t.Type[TValue]) -> list[tuple[t.Type[TValue], t.Type[TBase]]]:
1200
+ def get_type_associations[TBase, TValue](base_type: t.Type[TBase], generic_base_type: t.Type[TValue]) -> list[tuple[t.Type[TValue], t.Type[TBase]]]:
1206
1201
  """Create and return a list of tuples associating generic_base_type derived types with a corresponding base_type derived type."""
1207
1202
  return [item for item in [(get_generic_type(sc_type, generic_base_type), sc_type) for sc_type in get_subclasses(base_type)] if item[1]]
1208
1203
 
1209
1204
 
1210
- def get_type_map(base_type: t.Type[TBase], generic_base_type: t.Type[TValue]) -> dict[t.Type[TValue], t.Type[TBase]]:
1205
+ def get_type_map[TBase, TValue](base_type: t.Type[TBase], generic_base_type: t.Type[TValue]) -> dict[t.Type[TValue], t.Type[TBase]]:
1211
1206
  """Create and return a mapping of generic_base_type derived types to base_type derived types."""
1212
1207
  return {item[0]: item[1] for item in get_type_associations(base_type, generic_base_type)}
1213
1208
 
@@ -1228,7 +1223,7 @@ def verify_sys_executable(path: str) -> t.Optional[str]:
1228
1223
  return expected_executable
1229
1224
 
1230
1225
 
1231
- def type_guard(sequence: c.Sequence[t.Any], guard_type: t.Type[C]) -> t.TypeGuard[c.Sequence[C]]:
1226
+ def type_guard[C](sequence: c.Sequence[t.Any], guard_type: t.Type[C]) -> t.TypeGuard[c.Sequence[C]]:
1232
1227
  """
1233
1228
  Raises an exception if any item in the given sequence does not match the specified guard type.
1234
1229
  Use with assert so that type checkers are aware of the type guard.
@@ -17,14 +17,13 @@ from voluptuous import Required, Schema, Invalid
17
17
  from voluptuous.humanize import humanize_error
18
18
 
19
19
  from ansible.module_utils.compat.version import StrictVersion, LooseVersion
20
- from ansible.module_utils.six import string_types
21
20
  from ansible.utils.collection_loader import AnsibleCollectionRef
22
21
  from ansible.utils.version import SemanticVersion
23
22
 
24
23
 
25
24
  def fqcr(value):
26
25
  """Validate a FQCR."""
27
- if not isinstance(value, string_types):
26
+ if not isinstance(value, str):
28
27
  raise Invalid('Must be a string that is a FQCR')
29
28
  if not AnsibleCollectionRef.is_valid_fqcr(value):
30
29
  raise Invalid('Must be a FQCR')
@@ -33,7 +32,7 @@ def fqcr(value):
33
32
 
34
33
  def fqcr_or_shortname(value):
35
34
  """Validate a FQCR or a shortname."""
36
- if not isinstance(value, string_types):
35
+ if not isinstance(value, str):
37
36
  raise Invalid('Must be a string that is a FQCR or a short name')
38
37
  if '.' in value and not AnsibleCollectionRef.is_valid_fqcr(value):
39
38
  raise Invalid('Must be a FQCR or a short name')
@@ -48,7 +47,7 @@ def isodate(value, check_deprecation_date=False, is_tombstone=False):
48
47
  else:
49
48
  # make sure we have a string
50
49
  msg = 'Expected ISO 8601 date string (YYYY-MM-DD), or YAML date'
51
- if not isinstance(value, string_types):
50
+ if not isinstance(value, str):
52
51
  raise Invalid(msg)
53
52
  # From Python 3.7 in, there is datetime.date.fromisoformat(). For older versions,
54
53
  # we have to do things manually.
@@ -80,7 +79,7 @@ def removal_version(value, is_ansible, current_version=None, is_tombstone=False)
80
79
  'Removal version must be a string' if is_ansible else
81
80
  'Removal version must be a semantic version (https://semver.org/)'
82
81
  )
83
- if not isinstance(value, string_types):
82
+ if not isinstance(value, str):
84
83
  raise Invalid(msg)
85
84
  try:
86
85
  if is_ansible:
@@ -191,7 +190,7 @@ def validate_metadata_file(path, is_ansible, check_deprecation_dates=False):
191
190
  'removal_version': partial(removal_version, is_ansible=is_ansible,
192
191
  current_version=current_version),
193
192
  'removal_date': partial(isodate, check_deprecation_date=check_deprecation_dates),
194
- 'warning_text': Any(*string_types),
193
+ 'warning_text': str,
195
194
  }
196
195
  ),
197
196
  avoid_additional_data
@@ -204,7 +203,7 @@ def validate_metadata_file(path, is_ansible, check_deprecation_dates=False):
204
203
  'removal_version': partial(removal_version, is_ansible=is_ansible,
205
204
  current_version=current_version, is_tombstone=True),
206
205
  'removal_date': partial(isodate, is_tombstone=True),
207
- 'warning_text': Any(*string_types),
206
+ 'warning_text': str,
208
207
  }
209
208
  ),
210
209
  avoid_additional_data
@@ -228,18 +227,15 @@ def validate_metadata_file(path, is_ansible, check_deprecation_dates=False):
228
227
  # Adjusted schema for module_utils
229
228
  plugin_routing_schema_mu = Any(
230
229
  plugins_routing_common_schema.extend({
231
- ('redirect'): Any(*string_types)}
230
+ ('redirect'): str}
232
231
  ),
233
232
  )
234
233
 
235
- list_dict_plugin_routing_schema = [{str_type: plugin_routing_schema}
236
- for str_type in string_types]
234
+ list_dict_plugin_routing_schema = [{str: plugin_routing_schema}]
237
235
 
238
- list_dict_plugin_routing_schema_mu = [{str_type: plugin_routing_schema_mu}
239
- for str_type in string_types]
236
+ list_dict_plugin_routing_schema_mu = [{str: plugin_routing_schema_mu}]
240
237
 
241
- list_dict_plugin_routing_schema_modules = [{str_type: plugin_routing_schema_modules}
242
- for str_type in string_types]
238
+ list_dict_plugin_routing_schema_modules = [{str: plugin_routing_schema_modules}]
243
239
 
244
240
  plugin_schema = Schema({
245
241
  ('action'): Any(None, *list_dict_plugin_routing_schema),
@@ -267,13 +263,12 @@ def validate_metadata_file(path, is_ansible, check_deprecation_dates=False):
267
263
 
268
264
  import_redirection_schema = Any(
269
265
  Schema({
270
- ('redirect'): Any(*string_types),
266
+ ('redirect'): str,
271
267
  # import_redirect doesn't currently support deprecation
272
268
  }, extra=PREVENT_EXTRA)
273
269
  )
274
270
 
275
- list_dict_import_redirection_schema = [{str_type: import_redirection_schema}
276
- for str_type in string_types]
271
+ list_dict_import_redirection_schema = [{str: import_redirection_schema}]
277
272
 
278
273
  # action_groups schema
279
274
 
@@ -289,7 +284,7 @@ def validate_metadata_file(path, is_ansible, check_deprecation_dates=False):
289
284
  }, extra=PREVENT_EXTRA)
290
285
  }, extra=PREVENT_EXTRA)
291
286
  action_group_schema = All([metadata_dict, fqcr_or_shortname], at_most_one_dict)
292
- list_dict_action_groups_schema = [{str_type: action_group_schema} for str_type in string_types]
287
+ list_dict_action_groups_schema = [{str: action_group_schema}]
293
288
 
294
289
  # top level schema
295
290
 
@@ -298,7 +293,7 @@ def validate_metadata_file(path, is_ansible, check_deprecation_dates=False):
298
293
  ('plugin_routing'): Any(plugin_schema),
299
294
  ('import_redirection'): Any(None, *list_dict_import_redirection_schema),
300
295
  # requires_ansible: In the future we should validate this with SpecifierSet
301
- ('requires_ansible'): Any(*string_types),
296
+ ('requires_ansible'): str,
302
297
  ('action_groups'): Any(*list_dict_action_groups_schema),
303
298
  }, extra=PREVENT_EXTRA)
304
299
 
@@ -11,9 +11,11 @@ import functools
11
11
  import pathlib
12
12
  import re
13
13
 
14
- import astroid
15
- import astroid.context
14
+ import astroid.bases
15
+ import astroid.exceptions
16
+ import astroid.nodes
16
17
  import astroid.typing
18
+ import astroid.util
17
19
 
18
20
  import pylint.lint
19
21
  import pylint.checkers
@@ -42,7 +44,7 @@ class DeprecationCallArgs:
42
44
 
43
45
  def all_args_dynamic(self) -> bool:
44
46
  """True if all args are dynamic or None, otherwise False."""
45
- return all(arg is None or isinstance(arg, astroid.NodeNG) for arg in dataclasses.asdict(self).values())
47
+ return all(arg is None or isinstance(arg, astroid.nodes.NodeNG) for arg in dataclasses.asdict(self).values())
46
48
 
47
49
 
48
50
  class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
@@ -177,7 +179,7 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
177
179
  def __init__(self, *args, **kwargs) -> None:
178
180
  super().__init__(*args, **kwargs)
179
181
 
180
- self.module_cache: dict[str, astroid.Module] = {}
182
+ self.module_cache: dict[str, astroid.nodes.Module] = {}
181
183
 
182
184
  @functools.cached_property
183
185
  def collection_name(self) -> str | None:
@@ -226,7 +228,7 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
226
228
  return None
227
229
 
228
230
  @pylint.checkers.utils.only_required_for_messages(*(msgs.keys()))
229
- def visit_call(self, node: astroid.Call) -> None:
231
+ def visit_call(self, node: astroid.nodes.Call) -> None:
230
232
  """Visit a call node."""
231
233
  if inferred := self.infer(node.func):
232
234
  name = self.get_fully_qualified_name(inferred)
@@ -234,50 +236,50 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
234
236
  if args := self.DEPRECATION_FUNCTIONS.get(name):
235
237
  self.check_call(node, name, args)
236
238
 
237
- def infer(self, node: astroid.NodeNG) -> astroid.NodeNG | None:
239
+ def infer(self, node: astroid.nodes.NodeNG) -> astroid.nodes.NodeNG | None:
238
240
  """Return the inferred node from the given node, or `None` if it cannot be unambiguously inferred."""
239
241
  names: list[str] = []
240
- target: astroid.NodeNG | None = node
242
+ target: astroid.nodes.NodeNG | None = node
241
243
  inferred: astroid.typing.InferenceResult | None = None
242
244
 
243
245
  while target:
244
246
  if inferred := astroid.util.safe_infer(target):
245
247
  break
246
248
 
247
- if isinstance(target, astroid.Call):
249
+ if isinstance(target, astroid.nodes.Call):
248
250
  inferred = self.infer(target.func)
249
251
  break
250
252
 
251
- if isinstance(target, astroid.FunctionDef):
253
+ if isinstance(target, astroid.nodes.FunctionDef):
252
254
  inferred = target
253
255
  break
254
256
 
255
- if isinstance(target, astroid.Name):
257
+ if isinstance(target, astroid.nodes.Name):
256
258
  target = self.infer_name(target)
257
- elif isinstance(target, astroid.AssignName) and isinstance(target.parent, astroid.Assign):
259
+ elif isinstance(target, astroid.nodes.AssignName) and isinstance(target.parent, astroid.nodes.Assign):
258
260
  target = target.parent.value
259
- elif isinstance(target, astroid.Attribute):
261
+ elif isinstance(target, astroid.nodes.Attribute):
260
262
  names.append(target.attrname)
261
263
  target = target.expr
262
264
  else:
263
265
  break
264
266
 
265
267
  for name in reversed(names):
266
- if isinstance(inferred, astroid.Instance):
268
+ if isinstance(inferred, astroid.bases.Instance):
267
269
  try:
268
270
  attr = next(iter(inferred.getattr(name)), None)
269
- except astroid.AttributeInferenceError:
271
+ except astroid.exceptions.AttributeInferenceError:
270
272
  break
271
273
 
272
- if isinstance(attr, astroid.AssignAttr):
274
+ if isinstance(attr, astroid.nodes.AssignAttr):
273
275
  inferred = self.get_ansible_module(attr)
274
276
  continue
275
277
 
276
- if isinstance(attr, astroid.FunctionDef):
278
+ if isinstance(attr, astroid.nodes.FunctionDef):
277
279
  inferred = attr
278
280
  continue
279
281
 
280
- if not isinstance(inferred, (astroid.Module, astroid.ClassDef)):
282
+ if not isinstance(inferred, (astroid.nodes.Module, astroid.nodes.ClassDef)):
281
283
  inferred = None
282
284
  break
283
285
 
@@ -288,15 +290,15 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
288
290
  else:
289
291
  inferred = self.infer(inferred)
290
292
 
291
- if isinstance(inferred, astroid.FunctionDef) and isinstance(inferred.parent, astroid.ClassDef):
292
- inferred = astroid.BoundMethod(inferred, inferred.parent)
293
+ if isinstance(inferred, astroid.nodes.FunctionDef) and isinstance(inferred.parent, astroid.nodes.ClassDef):
294
+ inferred = astroid.bases.BoundMethod(inferred, inferred.parent)
293
295
 
294
296
  return inferred
295
297
 
296
- def infer_name(self, node: astroid.Name) -> astroid.NodeNG | None:
298
+ def infer_name(self, node: astroid.nodes.Name) -> astroid.nodes.NodeNG | None:
297
299
  """Infer the node referenced by the given name, or `None` if it cannot be unambiguously inferred."""
298
300
  scope = node.scope()
299
- inferred: astroid.NodeNG | None = None
301
+ inferred: astroid.nodes.NodeNG | None = None
300
302
  name = node.name
301
303
 
302
304
  while scope:
@@ -306,12 +308,12 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
306
308
  scope = scope.parent.scope() if scope.parent else None
307
309
  continue
308
310
 
309
- if isinstance(assignment, astroid.AssignName) and isinstance(assignment.parent, astroid.Assign):
311
+ if isinstance(assignment, astroid.nodes.AssignName) and isinstance(assignment.parent, astroid.nodes.Assign):
310
312
  inferred = assignment.parent.value
311
313
  elif (
312
- isinstance(scope, astroid.FunctionDef)
313
- and isinstance(assignment, astroid.AssignName)
314
- and isinstance(assignment.parent, astroid.Arguments)
314
+ isinstance(scope, astroid.nodes.FunctionDef)
315
+ and isinstance(assignment, astroid.nodes.AssignName)
316
+ and isinstance(assignment.parent, astroid.nodes.Arguments)
315
317
  and assignment.parent.annotations
316
318
  ):
317
319
  idx, _node = assignment.parent.find_argname(name)
@@ -322,12 +324,12 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
322
324
  except IndexError:
323
325
  pass
324
326
  else:
325
- if isinstance(annotation, astroid.Name):
327
+ if isinstance(annotation, astroid.nodes.Name):
326
328
  name = annotation.name
327
329
  continue
328
- elif isinstance(assignment, astroid.ClassDef):
330
+ elif isinstance(assignment, astroid.nodes.ClassDef):
329
331
  inferred = assignment
330
- elif isinstance(assignment, astroid.ImportFrom):
332
+ elif isinstance(assignment, astroid.nodes.ImportFrom):
331
333
  if module := self.get_module(assignment):
332
334
  name = assignment.real_name(name)
333
335
  scope = module.scope()
@@ -337,7 +339,7 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
337
339
 
338
340
  return inferred
339
341
 
340
- def get_module(self, node: astroid.ImportFrom) -> astroid.Module | None:
342
+ def get_module(self, node: astroid.nodes.ImportFrom) -> astroid.nodes.Module | None:
341
343
  """Import the requested module if possible and cache the result."""
342
344
  module_name = pylint.checkers.utils.get_import_name(node, node.modname)
343
345
 
@@ -357,21 +359,21 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
357
359
  return module
358
360
 
359
361
  @staticmethod
360
- def get_fully_qualified_name(node: astroid.NodeNG) -> str | None:
362
+ def get_fully_qualified_name(node: astroid.nodes.NodeNG) -> str | None:
361
363
  """Return the fully qualified name of the given inferred node."""
362
364
  parent = node.parent
363
365
  parts: tuple[str, ...] | None
364
366
 
365
- if isinstance(node, astroid.FunctionDef) and isinstance(parent, astroid.Module):
367
+ if isinstance(node, astroid.nodes.FunctionDef) and isinstance(parent, astroid.nodes.Module):
366
368
  parts = (parent.name, node.name)
367
- elif isinstance(node, astroid.BoundMethod) and isinstance(parent, astroid.ClassDef) and isinstance(parent.parent, astroid.Module):
369
+ elif isinstance(node, astroid.bases.BoundMethod) and isinstance(parent, astroid.nodes.ClassDef) and isinstance(parent.parent, astroid.nodes.Module):
368
370
  parts = (parent.parent.name, parent.name, node.name)
369
371
  else:
370
372
  parts = None
371
373
 
372
374
  return '.'.join(parts) if parts else None
373
375
 
374
- def check_call(self, node: astroid.Call, name: str, args: tuple[str, ...]) -> None:
376
+ def check_call(self, node: astroid.nodes.Call, name: str, args: tuple[str, ...]) -> None:
375
377
  """Check the given deprecation call node for valid arguments."""
376
378
  call_args = self.get_deprecation_call_args(node, args)
377
379
 
@@ -400,7 +402,7 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
400
402
  self.check_version(node, name, call_args)
401
403
 
402
404
  @staticmethod
403
- def get_deprecation_call_args(node: astroid.Call, args: tuple[str, ...]) -> DeprecationCallArgs:
405
+ def get_deprecation_call_args(node: astroid.nodes.Call, args: tuple[str, ...]) -> DeprecationCallArgs:
404
406
  """Get the deprecation call arguments from the given node."""
405
407
  fields: dict[str, object] = {}
406
408
 
@@ -413,12 +415,12 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
413
415
  fields[keyword.arg] = keyword.value
414
416
 
415
417
  for key, value in fields.items():
416
- if isinstance(value, astroid.Const):
418
+ if isinstance(value, astroid.nodes.Const):
417
419
  fields[key] = value.value
418
420
 
419
421
  return DeprecationCallArgs(**fields)
420
422
 
421
- def check_collection_name(self, node: astroid.Call, name: str, args: DeprecationCallArgs) -> None:
423
+ def check_collection_name(self, node: astroid.nodes.Call, name: str, args: DeprecationCallArgs) -> None:
422
424
  """Check the collection name provided to the given call node."""
423
425
  deprecator_requirement = self.is_deprecator_required()
424
426
 
@@ -459,14 +461,14 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
459
461
  if args.collection_name and args.collection_name != expected_collection_name:
460
462
  self.add_message('wrong-collection-deprecated', node=node, args=(args.collection_name, name))
461
463
 
462
- def check_version(self, node: astroid.Call, name: str, args: DeprecationCallArgs) -> None:
464
+ def check_version(self, node: astroid.nodes.Call, name: str, args: DeprecationCallArgs) -> None:
463
465
  """Check the version provided to the given call node."""
464
466
  if self.collection_name:
465
467
  self.check_collection_version(node, name, args)
466
468
  else:
467
469
  self.check_core_version(node, name, args)
468
470
 
469
- def check_core_version(self, node: astroid.Call, name: str, args: DeprecationCallArgs) -> None:
471
+ def check_core_version(self, node: astroid.nodes.Call, name: str, args: DeprecationCallArgs) -> None:
470
472
  """Check the core version provided to the given call node."""
471
473
  try:
472
474
  if not isinstance(args.version, str) or not args.version:
@@ -480,7 +482,7 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
480
482
  if self.ANSIBLE_VERSION >= strict_version:
481
483
  self.add_message('ansible-deprecated-version', node=node, args=(args.version, name))
482
484
 
483
- def check_collection_version(self, node: astroid.Call, name: str, args: DeprecationCallArgs) -> None:
485
+ def check_collection_version(self, node: astroid.nodes.Call, name: str, args: DeprecationCallArgs) -> None:
484
486
  """Check the collection version provided to the given call node."""
485
487
  try:
486
488
  if not isinstance(args.version, str) or not args.version:
@@ -497,7 +499,7 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
497
499
  if semantic_version.major != 0 and (semantic_version.minor != 0 or semantic_version.patch != 0):
498
500
  self.add_message('removal-version-must-be-major', node=node, args=(args.version,))
499
501
 
500
- def check_date(self, node: astroid.Call, name: str, args: DeprecationCallArgs) -> None:
502
+ def check_date(self, node: astroid.nodes.Call, name: str, args: DeprecationCallArgs) -> None:
501
503
  """Check the date provided to the given call node."""
502
504
  try:
503
505
  date_parsed = self.parse_isodate(args.date)
@@ -515,18 +517,19 @@ class AnsibleDeprecatedChecker(pylint.checkers.BaseChecker):
515
517
 
516
518
  raise TypeError(type(value))
517
519
 
518
- def get_ansible_module(self, node: astroid.AssignAttr) -> astroid.Instance | None:
520
+ def get_ansible_module(self, node: astroid.nodes.AssignAttr) -> astroid.bases.Instance | None:
519
521
  """Infer an AnsibleModule instance node from the given assignment."""
520
- if isinstance(node.parent, astroid.Assign) and isinstance(node.parent.type_annotation, astroid.Name):
522
+ if isinstance(node.parent, astroid.nodes.Assign) and isinstance(node.parent.type_annotation, astroid.nodes.Name):
521
523
  inferred = self.infer_name(node.parent.type_annotation)
522
- elif isinstance(node.parent, astroid.Assign) and isinstance(node.parent.parent, astroid.FunctionDef) and isinstance(node.parent.value, astroid.Name):
524
+ elif (isinstance(node.parent, astroid.nodes.Assign) and isinstance(node.parent.parent, astroid.nodes.FunctionDef) and
525
+ isinstance(node.parent.value, astroid.nodes.Name)):
523
526
  inferred = self.infer_name(node.parent.value)
524
- elif isinstance(node.parent, astroid.AnnAssign) and isinstance(node.parent.annotation, astroid.Name):
527
+ elif isinstance(node.parent, astroid.nodes.AnnAssign) and isinstance(node.parent.annotation, astroid.nodes.Name):
525
528
  inferred = self.infer_name(node.parent.annotation)
526
529
  else:
527
530
  inferred = None
528
531
 
529
- if isinstance(inferred, astroid.ClassDef) and inferred.name == 'AnsibleModule':
532
+ if isinstance(inferred, astroid.nodes.ClassDef) and inferred.name == 'AnsibleModule':
530
533
  return inferred.instantiate_class()
531
534
 
532
535
  return None
@@ -5,7 +5,9 @@
5
5
  # -*- coding: utf-8 -*-
6
6
  from __future__ import annotations
7
7
 
8
- import astroid
8
+ import astroid.bases
9
+ import astroid.exceptions
10
+ import astroid.nodes
9
11
 
10
12
  try:
11
13
  from pylint.checkers.utils import check_messages
@@ -39,22 +41,22 @@ class AnsibleStringFormatChecker(BaseChecker):
39
41
  def visit_call(self, node):
40
42
  """Visit a call node."""
41
43
  func = utils.safe_infer(node.func)
42
- if (isinstance(func, astroid.BoundMethod)
43
- and isinstance(func.bound, astroid.Instance)
44
+ if (isinstance(func, astroid.bases.BoundMethod)
45
+ and isinstance(func.bound, astroid.bases.Instance)
44
46
  and func.bound.name in ('str', 'unicode', 'bytes')):
45
47
  if func.name == 'format':
46
48
  self._check_new_format(node, func)
47
49
 
48
50
  def _check_new_format(self, node, func):
49
51
  """ Check the new string formatting """
50
- if (isinstance(node.func, astroid.Attribute)
51
- and not isinstance(node.func.expr, astroid.Const)):
52
+ if (isinstance(node.func, astroid.nodes.Attribute)
53
+ and not isinstance(node.func.expr, astroid.nodes.Const)):
52
54
  return
53
55
  try:
54
56
  strnode = next(func.bound.infer())
55
- except astroid.InferenceError:
57
+ except astroid.exceptions.InferenceError:
56
58
  return
57
- if not isinstance(strnode, astroid.Const):
59
+ if not isinstance(strnode, astroid.nodes.Const):
58
60
  return
59
61
 
60
62
  if isinstance(strnode.value, bytes):