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.

Files changed (202) hide show
  1. ansible/_internal/__init__.py +1 -4
  2. ansible/_internal/_ansiballz/_builder.py +1 -3
  3. ansible/_internal/_collection_proxy.py +7 -9
  4. ansible/_internal/_display_utils.py +145 -0
  5. ansible/_internal/_json/__init__.py +3 -4
  6. ansible/_internal/_templating/_engine.py +1 -1
  7. ansible/_internal/_templating/_jinja_plugins.py +1 -2
  8. ansible/_internal/_wrapt.py +105 -301
  9. ansible/cli/__init__.py +11 -10
  10. ansible/cli/adhoc.py +1 -2
  11. ansible/cli/arguments/option_helpers.py +1 -1
  12. ansible/cli/config.py +5 -6
  13. ansible/cli/doc.py +67 -67
  14. ansible/cli/galaxy.py +15 -24
  15. ansible/cli/inventory.py +0 -1
  16. ansible/cli/playbook.py +0 -1
  17. ansible/cli/pull.py +0 -1
  18. ansible/cli/scripts/ansible_connection_cli_stub.py +1 -1
  19. ansible/config/base.yml +1 -25
  20. ansible/config/manager.py +0 -2
  21. ansible/executor/play_iterator.py +42 -20
  22. ansible/executor/playbook_executor.py +0 -9
  23. ansible/executor/powershell/async_watchdog.ps1 +24 -4
  24. ansible/executor/task_executor.py +32 -22
  25. ansible/executor/task_queue_manager.py +1 -3
  26. ansible/galaxy/api.py +33 -80
  27. ansible/galaxy/collection/__init__.py +4 -17
  28. ansible/galaxy/dependency_resolution/dataclasses.py +0 -10
  29. ansible/galaxy/dependency_resolution/providers.py +1 -2
  30. ansible/galaxy/role.py +1 -33
  31. ansible/inventory/manager.py +2 -3
  32. ansible/keyword_desc.yml +0 -3
  33. ansible/module_utils/_internal/_datatag/__init__.py +2 -10
  34. ansible/module_utils/_internal/_no_six.py +86 -0
  35. ansible/module_utils/_text.py +28 -8
  36. ansible/module_utils/ansible_release.py +2 -2
  37. ansible/module_utils/basic.py +27 -24
  38. ansible/module_utils/common/_collections_compat.py +11 -2
  39. ansible/module_utils/common/collections.py +8 -3
  40. ansible/module_utils/common/dict_transformations.py +1 -2
  41. ansible/module_utils/common/network.py +4 -2
  42. ansible/module_utils/common/parameters.py +32 -41
  43. ansible/module_utils/common/text/converters.py +109 -23
  44. ansible/module_utils/common/text/formatters.py +6 -2
  45. ansible/module_utils/common/validation.py +11 -9
  46. ansible/module_utils/connection.py +8 -3
  47. ansible/module_utils/facts/hardware/linux.py +23 -7
  48. ansible/module_utils/facts/hardware/netbsd.py +1 -1
  49. ansible/module_utils/facts/hardware/sunos.py +2 -1
  50. ansible/module_utils/facts/packages.py +6 -2
  51. ansible/module_utils/facts/system/distribution.py +2 -1
  52. ansible/module_utils/facts/system/env.py +6 -3
  53. ansible/module_utils/facts/system/local.py +3 -1
  54. ansible/module_utils/parsing/convert_bool.py +6 -2
  55. ansible/module_utils/service.py +2 -3
  56. ansible/module_utils/six/__init__.py +11 -6
  57. ansible/module_utils/urls.py +6 -2
  58. ansible/module_utils/yumdnf.py +0 -5
  59. ansible/modules/apt.py +18 -13
  60. ansible/modules/apt_repository.py +1 -1
  61. ansible/modules/assemble.py +5 -9
  62. ansible/modules/blockinfile.py +39 -23
  63. ansible/modules/cron.py +26 -35
  64. ansible/modules/deb822_repository.py +83 -12
  65. ansible/modules/dnf.py +3 -7
  66. ansible/modules/dnf5.py +4 -6
  67. ansible/modules/expect.py +0 -3
  68. ansible/modules/find.py +1 -2
  69. ansible/modules/get_url.py +1 -1
  70. ansible/modules/git.py +4 -5
  71. ansible/modules/include_vars.py +1 -1
  72. ansible/modules/lineinfile.py +71 -63
  73. ansible/modules/package_facts.py +1 -1
  74. ansible/modules/pip.py +8 -2
  75. ansible/modules/replace.py +6 -6
  76. ansible/modules/service.py +3 -4
  77. ansible/modules/stat.py +20 -0
  78. ansible/modules/uri.py +9 -10
  79. ansible/modules/user.py +1 -2
  80. ansible/modules/wait_for.py +2 -2
  81. ansible/modules/wait_for_connection.py +2 -1
  82. ansible/modules/yum_repository.py +1 -16
  83. ansible/parsing/dataloader.py +24 -31
  84. ansible/parsing/mod_args.py +3 -0
  85. ansible/parsing/vault/__init__.py +1 -2
  86. ansible/playbook/base.py +8 -56
  87. ansible/playbook/block.py +0 -60
  88. ansible/playbook/collectionsearch.py +1 -2
  89. ansible/playbook/handler.py +1 -7
  90. ansible/playbook/helpers.py +0 -7
  91. ansible/playbook/included_file.py +1 -1
  92. ansible/playbook/play.py +103 -37
  93. ansible/playbook/play_context.py +4 -0
  94. ansible/playbook/role/__init__.py +10 -65
  95. ansible/playbook/role/definition.py +3 -4
  96. ansible/playbook/role/include.py +2 -3
  97. ansible/playbook/role/metadata.py +1 -12
  98. ansible/playbook/role/requirement.py +1 -2
  99. ansible/playbook/role_include.py +1 -2
  100. ansible/playbook/taggable.py +16 -5
  101. ansible/playbook/task.py +51 -55
  102. ansible/plugins/action/__init__.py +20 -19
  103. ansible/plugins/action/add_host.py +1 -2
  104. ansible/plugins/action/fetch.py +2 -4
  105. ansible/plugins/action/group_by.py +1 -2
  106. ansible/plugins/action/include_vars.py +20 -22
  107. ansible/plugins/action/script.py +1 -3
  108. ansible/plugins/action/template.py +1 -2
  109. ansible/plugins/action/uri.py +4 -2
  110. ansible/plugins/cache/__init__.py +1 -0
  111. ansible/plugins/callback/__init__.py +13 -6
  112. ansible/plugins/connection/__init__.py +3 -7
  113. ansible/plugins/connection/local.py +2 -3
  114. ansible/plugins/connection/psrp.py +0 -2
  115. ansible/plugins/connection/ssh.py +2 -7
  116. ansible/plugins/connection/winrm.py +0 -2
  117. ansible/plugins/doc_fragments/result_format_callback.py +15 -0
  118. ansible/plugins/filter/core.py +4 -5
  119. ansible/plugins/filter/encryption.py +3 -27
  120. ansible/plugins/filter/mathstuff.py +1 -2
  121. ansible/plugins/filter/to_nice_yaml.yml +31 -3
  122. ansible/plugins/filter/to_yaml.yml +29 -12
  123. ansible/plugins/inventory/__init__.py +1 -2
  124. ansible/plugins/inventory/script.py +2 -1
  125. ansible/plugins/inventory/toml.py +3 -6
  126. ansible/plugins/inventory/yaml.py +1 -2
  127. ansible/plugins/list.py +10 -3
  128. ansible/plugins/loader.py +6 -6
  129. ansible/plugins/lookup/password.py +1 -2
  130. ansible/plugins/lookup/subelements.py +2 -3
  131. ansible/plugins/lookup/url.py +1 -1
  132. ansible/plugins/lookup/varnames.py +1 -2
  133. ansible/plugins/shell/__init__.py +9 -4
  134. ansible/plugins/shell/powershell.py +8 -24
  135. ansible/plugins/strategy/__init__.py +6 -3
  136. ansible/plugins/test/core.py +4 -1
  137. ansible/plugins/test/regex.yml +18 -6
  138. ansible/release.py +2 -2
  139. ansible/template/__init__.py +3 -7
  140. ansible/utils/collection_loader/_collection_config.py +5 -0
  141. ansible/utils/collection_loader/_collection_finder.py +11 -14
  142. ansible/utils/context_objects.py +7 -4
  143. ansible/utils/display.py +28 -167
  144. ansible/utils/encrypt.py +0 -5
  145. ansible/utils/helpers.py +6 -2
  146. ansible/utils/jsonrpc.py +7 -3
  147. ansible/utils/plugin_docs.py +49 -38
  148. ansible/utils/ssh_functions.py +0 -19
  149. ansible/utils/unsafe_proxy.py +7 -7
  150. ansible/vars/clean.py +2 -3
  151. ansible/vars/manager.py +27 -20
  152. ansible/vars/plugins.py +1 -31
  153. {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/METADATA +3 -3
  154. {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/RECORD +200 -200
  155. ansible_test/_data/completion/docker.txt +7 -7
  156. ansible_test/_data/completion/network.txt +0 -1
  157. ansible_test/_data/completion/remote.txt +4 -4
  158. ansible_test/_data/requirements/ansible-test.txt +1 -1
  159. ansible_test/_data/requirements/sanity.changelog.txt +1 -1
  160. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  161. ansible_test/_data/requirements/sanity.pylint.txt +4 -4
  162. ansible_test/_internal/cache.py +2 -5
  163. ansible_test/_internal/cli/compat.py +1 -1
  164. ansible_test/_internal/commands/coverage/combine.py +1 -3
  165. ansible_test/_internal/commands/integration/__init__.py +3 -7
  166. ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
  167. ansible_test/_internal/commands/integration/coverage.py +1 -3
  168. ansible_test/_internal/commands/integration/filters.py +5 -10
  169. ansible_test/_internal/commands/sanity/validate_modules.py +1 -5
  170. ansible_test/_internal/commands/units/__init__.py +1 -13
  171. ansible_test/_internal/completion.py +2 -5
  172. ansible_test/_internal/config.py +2 -7
  173. ansible_test/_internal/coverage_util.py +1 -1
  174. ansible_test/_internal/delegation.py +2 -0
  175. ansible_test/_internal/docker_util.py +1 -1
  176. ansible_test/_internal/host_profiles.py +6 -11
  177. ansible_test/_internal/provider/__init__.py +2 -5
  178. ansible_test/_internal/provisioning.py +2 -5
  179. ansible_test/_internal/pypi_proxy.py +1 -1
  180. ansible_test/_internal/target.py +2 -6
  181. ansible_test/_internal/thread.py +1 -4
  182. ansible_test/_internal/util.py +9 -14
  183. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +14 -19
  184. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +30 -27
  185. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +31 -18
  186. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +1 -2
  187. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +59 -71
  188. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -2
  189. ansible_test/_util/target/cli/ansible_test_cli_stub.py +4 -2
  190. ansible_test/_util/target/common/constants.py +2 -2
  191. ansible_test/_util/target/setup/bootstrap.sh +0 -6
  192. ansible/utils/py3compat.py +0 -27
  193. ansible_test/_data/pytest/config/legacy.ini +0 -4
  194. {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/WHEEL +0 -0
  195. {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/entry_points.txt +0 -0
  196. {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/COPYING +0 -0
  197. {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  198. {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
  199. {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  200. {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  201. {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  202. {ansible_core-2.19.2rc1.dist-info → ansible_core-2.20.0b1.dist-info}/top_level.txt +0 -0
@@ -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
 
@@ -80,36 +80,39 @@ class AnsibleUnwantedChecker(BaseChecker):
80
80
  'Identifies imports which should not be used.'),
81
81
  )
82
82
 
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
-
83
+ unwanted_imports = {
89
84
  # 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
- )),
85
+ 'urllib2': UnwantedEntry(
86
+ 'ansible.module_utils.urls',
87
+ ignore_paths=(
88
+ '/lib/ansible/module_utils/urls.py',
89
+ )
90
+ ),
94
91
 
95
92
  # 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
- )
93
+ 'collections': UnwantedEntry(
94
+ 'collections.abc',
95
+ names=(
96
+ 'MappingView',
97
+ 'ItemsView',
98
+ 'KeysView',
99
+ 'ValuesView',
100
+ 'Mapping', 'MutableMapping',
101
+ 'Sequence', 'MutableSequence',
102
+ 'Set', 'MutableSet',
103
+ 'Container',
104
+ 'Hashable',
105
+ 'Sized',
106
+ 'Callable',
107
+ 'Iterable',
108
+ 'Iterator',
109
+ )
110
+ ),
111
+
112
+ 'ansible.module_utils.six': UnwantedEntry(
113
+ 'the Python standard library equivalent'
114
+ ),
115
+ }
113
116
 
114
117
  unwanted_functions = {
115
118
  # see https://docs.python.org/3/library/tempfile.html#tempfile.mktemp
@@ -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()