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
@@ -2,10 +2,12 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import functools
5
6
  import os
6
7
  import typing as t
7
8
 
8
- import astroid
9
+ import astroid.exceptions
10
+ import astroid.nodes
9
11
 
10
12
  from pylint.checkers import BaseChecker
11
13
 
@@ -80,36 +82,35 @@ class AnsibleUnwantedChecker(BaseChecker):
80
82
  'Identifies imports which should not be used.'),
81
83
  )
82
84
 
83
- unwanted_imports = dict(
84
- # Additional imports that we may want to start checking:
85
- # boto=UnwantedEntry('boto3', modules_only=True),
86
- # requests=UnwantedEntry('ansible.module_utils.urls', modules_only=True),
87
- # urllib=UnwantedEntry('ansible.module_utils.urls', modules_only=True),
88
-
85
+ unwanted_imports = {
89
86
  # see https://docs.python.org/2/library/urllib2.html
90
- urllib2=UnwantedEntry('ansible.module_utils.urls',
91
- ignore_paths=(
92
- '/lib/ansible/module_utils/urls.py',
93
- )),
87
+ 'urllib2': UnwantedEntry(
88
+ 'ansible.module_utils.urls',
89
+ ignore_paths=(
90
+ '/lib/ansible/module_utils/urls.py',
91
+ )
92
+ ),
94
93
 
95
94
  # see https://docs.python.org/3/library/collections.abc.html
96
- collections=UnwantedEntry('ansible.module_utils.six.moves.collections_abc',
97
- names=(
98
- 'MappingView',
99
- 'ItemsView',
100
- 'KeysView',
101
- 'ValuesView',
102
- 'Mapping', 'MutableMapping',
103
- 'Sequence', 'MutableSequence',
104
- 'Set', 'MutableSet',
105
- 'Container',
106
- 'Hashable',
107
- 'Sized',
108
- 'Callable',
109
- 'Iterable',
110
- 'Iterator',
111
- )),
112
- )
95
+ 'collections': UnwantedEntry(
96
+ 'collections.abc',
97
+ names=(
98
+ 'MappingView',
99
+ 'ItemsView',
100
+ 'KeysView',
101
+ 'ValuesView',
102
+ 'Mapping', 'MutableMapping',
103
+ 'Sequence', 'MutableSequence',
104
+ 'Set', 'MutableSet',
105
+ 'Container',
106
+ 'Hashable',
107
+ 'Sized',
108
+ 'Callable',
109
+ 'Iterable',
110
+ 'Iterator',
111
+ )
112
+ ),
113
+ }
113
114
 
114
115
  unwanted_functions = {
115
116
  # see https://docs.python.org/3/library/tempfile.html#tempfile.mktemp
@@ -133,21 +134,34 @@ class AnsibleUnwantedChecker(BaseChecker):
133
134
  modules_only=True),
134
135
  }
135
136
 
136
- def visit_import(self, node): # type: (astroid.node_classes.Import) -> None
137
+ def __init__(self, *args, **kwargs) -> None:
138
+ super().__init__(*args, **kwargs)
139
+ # ansible.module_utils.six is deprecated and collections can still use it until it is removed
140
+ if self.is_ansible_core:
141
+ self.unwanted_imports['ansible.module_utils.six'] = UnwantedEntry(
142
+ 'the Python standard library equivalent'
143
+ )
144
+
145
+ @functools.cached_property
146
+ def is_ansible_core(self) -> bool:
147
+ """True if ansible-core is being tested."""
148
+ return not self.linter.config.collection_name
149
+
150
+ def visit_import(self, node: astroid.nodes.Import) -> None:
137
151
  """Visit an import node."""
138
152
  for name in node.names:
139
153
  self._check_import(node, name[0])
140
154
 
141
- def visit_importfrom(self, node): # type: (astroid.node_classes.ImportFrom) -> None
155
+ def visit_importfrom(self, node: astroid.nodes.ImportFrom) -> None:
142
156
  """Visit an import from node."""
143
157
  self._check_importfrom(node, node.modname, node.names)
144
158
 
145
- def visit_attribute(self, node): # type: (astroid.node_classes.Attribute) -> None
159
+ def visit_attribute(self, node: astroid.nodes.Attribute) -> None:
146
160
  """Visit an attribute node."""
147
161
  last_child = node.last_child()
148
162
 
149
163
  # this is faster than using type inference and will catch the most common cases
150
- if not isinstance(last_child, astroid.node_classes.Name):
164
+ if not isinstance(last_child, astroid.nodes.Name):
151
165
  return
152
166
 
153
167
  module = last_child.name
@@ -158,13 +172,13 @@ class AnsibleUnwantedChecker(BaseChecker):
158
172
  if entry.applies_to(self.linter.current_file, node.attrname):
159
173
  self.add_message(self.BAD_IMPORT_FROM, args=(node.attrname, entry.alternative, module), node=node)
160
174
 
161
- def visit_call(self, node): # type: (astroid.node_classes.Call) -> None
175
+ def visit_call(self, node: astroid.nodes.Call) -> None:
162
176
  """Visit a call node."""
163
177
  try:
164
178
  for i in node.func.inferred():
165
179
  func = None
166
180
 
167
- if isinstance(i, astroid.scoped_nodes.FunctionDef) and isinstance(i.parent, astroid.scoped_nodes.Module):
181
+ if isinstance(i, astroid.nodes.FunctionDef) and isinstance(i.parent, astroid.nodes.Module):
168
182
  func = '%s.%s' % (i.parent.name, i.name)
169
183
 
170
184
  if not func:
@@ -177,7 +191,7 @@ class AnsibleUnwantedChecker(BaseChecker):
177
191
  except astroid.exceptions.InferenceError:
178
192
  pass
179
193
 
180
- def _check_import(self, node, modname): # type: (astroid.node_classes.Import, str) -> None
194
+ def _check_import(self, node: astroid.nodes.Import, modname: str) -> None:
181
195
  """Check the imports on the specified import node."""
182
196
  self._check_module_import(node, modname)
183
197
 
@@ -189,7 +203,7 @@ class AnsibleUnwantedChecker(BaseChecker):
189
203
  if entry.applies_to(self.linter.current_file):
190
204
  self.add_message(self.BAD_IMPORT, args=(entry.alternative, modname), node=node)
191
205
 
192
- def _check_importfrom(self, node, modname, names): # type: (astroid.node_classes.ImportFrom, str, t.List[str]) -> None
206
+ def _check_importfrom(self, node: astroid.nodes.ImportFrom, modname: str, names: list[tuple[str, str | None]]) -> None:
193
207
  """Check the imports on the specified import from node."""
194
208
  self._check_module_import(node, modname)
195
209
 
@@ -202,7 +216,7 @@ class AnsibleUnwantedChecker(BaseChecker):
202
216
  if entry.applies_to(self.linter.current_file, name[0]):
203
217
  self.add_message(self.BAD_IMPORT_FROM, args=(name[0], entry.alternative, modname), node=node)
204
218
 
205
- def _check_module_import(self, node, modname): # type: (t.Union[astroid.node_classes.Import, astroid.node_classes.ImportFrom], str) -> None
219
+ def _check_module_import(self, node: astroid.nodes.Import | astroid.nodes.ImportFrom, modname: str) -> None:
206
220
  """Check the module import on the given import or import from node."""
207
221
  if not is_module_path(self.linter.current_file):
208
222
  return
@@ -72,7 +72,7 @@ from ansible.module_utils.compat.version import StrictVersion, LooseVersion
72
72
  from ansible.module_utils.basic import to_bytes
73
73
  from ansible.plugins.loader import fragment_loader
74
74
  from ansible.plugins.list import IGNORE as REJECTLIST
75
- from ansible.utils.plugin_docs import add_collection_to_versions_and_dates, add_fragments, get_docstring
75
+ from ansible.utils.plugin_docs import AnsibleFragmentError, add_collection_to_versions_and_dates, add_fragments, get_docstring
76
76
  from ansible.utils.version import SemanticVersion
77
77
 
78
78
  from .module_args import AnsibleModuleImportError, AnsibleModuleNotInitialized, get_py_argument_spec, get_ps_argument_spec
@@ -1003,21 +1003,15 @@ class ModuleValidator(Validator):
1003
1003
  add_collection_to_versions_and_dates(doc, self.collection_name,
1004
1004
  is_module=self.plugin_type == 'module')
1005
1005
 
1006
- missing_fragment = False
1007
1006
  with CaptureStd():
1008
1007
  try:
1009
1008
  get_docstring(os.path.abspath(self.path), fragment_loader=fragment_loader,
1010
1009
  verbose=True,
1011
1010
  collection_name=self.collection_name,
1012
1011
  plugin_type=self.plugin_type)
1013
- except AssertionError:
1014
- fragment = doc['extends_documentation_fragment']
1015
- self.reporter.error(
1016
- path=self.object_path,
1017
- code='missing-doc-fragment',
1018
- msg='DOCUMENTATION fragment missing: %s' % fragment
1019
- )
1020
- missing_fragment = True
1012
+ except AnsibleFragmentError:
1013
+ # Will be re-triggered below when explicitly calling add_fragments()
1014
+ pass
1021
1015
  except Exception as e:
1022
1016
  self.reporter.trace(
1023
1017
  path=self.object_path,
@@ -1029,9 +1023,16 @@ class ModuleValidator(Validator):
1029
1023
  msg='Unknown DOCUMENTATION error, see TRACE: %s' % e
1030
1024
  )
1031
1025
 
1032
- if not missing_fragment:
1026
+ try:
1033
1027
  add_fragments(doc, os.path.abspath(self.object_path), fragment_loader=fragment_loader,
1034
- is_module=self.plugin_type == 'module')
1028
+ is_module=self.plugin_type == 'module', section='DOCUMENTATION')
1029
+ except AnsibleFragmentError as exc:
1030
+ error = str(exc).replace(os.path.abspath(self.object_path), self.object_path)
1031
+ self.reporter.error(
1032
+ path=self.object_path,
1033
+ code='doc-fragment-error',
1034
+ msg=f'Error while adding fragments: {error}'
1035
+ )
1035
1036
 
1036
1037
  if 'options' in doc and doc['options'] is None:
1037
1038
  self.reporter.error(
@@ -1130,6 +1131,16 @@ class ModuleValidator(Validator):
1130
1131
  self.collection_name,
1131
1132
  is_module=self.plugin_type == 'module',
1132
1133
  return_docs=True)
1134
+ try:
1135
+ add_fragments(returns, os.path.abspath(self.object_path), fragment_loader=fragment_loader,
1136
+ is_module=self.plugin_type == 'module', section='RETURN')
1137
+ except AnsibleFragmentError as exc:
1138
+ error = str(exc).replace(os.path.abspath(self.object_path), self.object_path)
1139
+ self.reporter.error(
1140
+ path=self.object_path,
1141
+ code='return-fragment-error',
1142
+ msg=f'Error while adding fragments: {error}'
1143
+ )
1133
1144
  self._validate_docs_schema(
1134
1145
  returns,
1135
1146
  return_schema(for_collection=bool(self.collection), plugin_type=self.plugin_type),
@@ -1268,16 +1279,18 @@ class ModuleValidator(Validator):
1268
1279
  if not isinstance(options, dict):
1269
1280
  return
1270
1281
  for key, value in options.items():
1271
- self._validate_semantic_markup(value.get('description'))
1272
- self._validate_semantic_markup_options(value.get('suboptions'))
1282
+ if isinstance(value, dict):
1283
+ self._validate_semantic_markup(value.get('description'))
1284
+ self._validate_semantic_markup_options(value.get('suboptions'))
1273
1285
 
1274
1286
  def _validate_semantic_markup_return_values(self, return_vars):
1275
1287
  if not isinstance(return_vars, dict):
1276
1288
  return
1277
1289
  for key, value in return_vars.items():
1278
- self._validate_semantic_markup(value.get('description'))
1279
- self._validate_semantic_markup(value.get('returned'))
1280
- self._validate_semantic_markup_return_values(value.get('contains'))
1290
+ if isinstance(value, dict):
1291
+ self._validate_semantic_markup(value.get('description'))
1292
+ self._validate_semantic_markup(value.get('returned'))
1293
+ self._validate_semantic_markup_return_values(value.get('contains'))
1281
1294
 
1282
1295
  def _validate_all_semantic_markup(self, docs, return_docs):
1283
1296
  if not isinstance(docs, dict):
@@ -1617,7 +1630,7 @@ class ModuleValidator(Validator):
1617
1630
  try:
1618
1631
  if not context:
1619
1632
  add_fragments(docs, os.path.abspath(self.object_path), fragment_loader=fragment_loader,
1620
- is_module=self.plugin_type == 'module')
1633
+ is_module=self.plugin_type == 'module', section='DOCUMENTATION')
1621
1634
  except Exception:
1622
1635
  # Cannot merge fragments
1623
1636
  return
@@ -28,7 +28,6 @@ from contextlib import contextmanager
28
28
 
29
29
  from ansible.executor.powershell.module_manifest import PSModuleDepFinder
30
30
  from ansible.module_utils.basic import FILE_COMMON_ARGUMENTS, AnsibleModule
31
- from ansible.module_utils.six import reraise
32
31
  from ansible.module_utils.common.text.converters import to_bytes, to_text
33
32
 
34
33
  from .utils import CaptureStd, find_executable, get_module_name_from_filename
@@ -153,7 +152,7 @@ def get_py_argument_spec(filename, collection):
153
152
  pass
154
153
  except BaseException as e:
155
154
  # we want to catch all exceptions here, including sys.exit
156
- reraise(AnsibleModuleImportError, AnsibleModuleImportError('%s' % e), sys.exc_info()[2])
155
+ raise AnsibleModuleImportError from e
157
156
 
158
157
  if not fake.called:
159
158
  raise AnsibleModuleNotInitialized()