ansible-core 2.19.0b5__py3-none-any.whl → 2.19.0b6__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.
Files changed (117) hide show
  1. ansible/_internal/_ansiballz/__init__.py +0 -0
  2. ansible/_internal/_ansiballz/_builder.py +101 -0
  3. ansible/_internal/{_ansiballz.py → _ansiballz/_wrapper.py} +11 -11
  4. ansible/_internal/_templating/_jinja_bits.py +7 -4
  5. ansible/_internal/_templating/_jinja_plugins.py +5 -2
  6. ansible/_internal/_templating/_template_vars.py +72 -0
  7. ansible/_internal/_templating/_transform.py +6 -0
  8. ansible/_internal/_yaml/_constructor.py +4 -4
  9. ansible/_internal/_yaml/_dumper.py +26 -18
  10. ansible/cli/__init__.py +7 -12
  11. ansible/cli/arguments/option_helpers.py +1 -1
  12. ansible/cli/console.py +1 -1
  13. ansible/cli/doc.py +2 -2
  14. ansible/cli/inventory.py +5 -7
  15. ansible/config/base.yml +24 -0
  16. ansible/errors/__init__.py +2 -1
  17. ansible/executor/module_common.py +67 -39
  18. ansible/executor/process/worker.py +2 -2
  19. ansible/galaxy/api.py +1 -4
  20. ansible/galaxy/collection/__init__.py +1 -6
  21. ansible/galaxy/collection/concrete_artifact_manager.py +2 -8
  22. ansible/galaxy/role.py +2 -2
  23. ansible/module_utils/_internal/__init__.py +7 -4
  24. ansible/module_utils/_internal/_ansiballz/__init__.py +0 -0
  25. ansible/module_utils/_internal/_ansiballz/_extensions/__init__.py +0 -0
  26. ansible/module_utils/_internal/_ansiballz/_extensions/_coverage.py +45 -0
  27. ansible/module_utils/_internal/_ansiballz/_extensions/_pydevd.py +62 -0
  28. ansible/module_utils/_internal/{_ansiballz.py → _ansiballz/_loader.py} +10 -38
  29. ansible/module_utils/_internal/_ansiballz/_respawn.py +32 -0
  30. ansible/module_utils/_internal/_ansiballz/_respawn_wrapper.py +23 -0
  31. ansible/module_utils/_internal/_datatag/__init__.py +23 -1
  32. ansible/module_utils/_internal/_deprecator.py +27 -33
  33. ansible/module_utils/_internal/_json/_profiles/__init__.py +1 -0
  34. ansible/module_utils/_internal/_messages.py +26 -2
  35. ansible/module_utils/_internal/_plugin_info.py +14 -1
  36. ansible/module_utils/ansible_release.py +1 -1
  37. ansible/module_utils/basic.py +46 -56
  38. ansible/module_utils/common/respawn.py +4 -41
  39. ansible/module_utils/connection.py +8 -11
  40. ansible/module_utils/facts/hardware/linux.py +1 -1
  41. ansible/module_utils/facts/sysctl.py +4 -6
  42. ansible/module_utils/facts/system/caps.py +2 -2
  43. ansible/module_utils/facts/system/local.py +1 -1
  44. ansible/module_utils/facts/virtual/linux.py +1 -1
  45. ansible/module_utils/service.py +1 -1
  46. ansible/module_utils/urls.py +4 -4
  47. ansible/modules/apt_repository.py +10 -10
  48. ansible/modules/assemble.py +2 -2
  49. ansible/modules/async_wrapper.py +7 -17
  50. ansible/modules/command.py +3 -3
  51. ansible/modules/copy.py +4 -4
  52. ansible/modules/cron.py +1 -1
  53. ansible/modules/file.py +16 -17
  54. ansible/modules/find.py +3 -3
  55. ansible/modules/get_url.py +17 -0
  56. ansible/modules/git.py +9 -7
  57. ansible/modules/known_hosts.py +12 -14
  58. ansible/modules/package.py +6 -0
  59. ansible/modules/replace.py +2 -2
  60. ansible/modules/slurp.py +10 -13
  61. ansible/modules/stat.py +5 -7
  62. ansible/modules/unarchive.py +6 -6
  63. ansible/modules/user.py +1 -1
  64. ansible/modules/wait_for.py +28 -30
  65. ansible/modules/yum_repository.py +4 -3
  66. ansible/parsing/dataloader.py +2 -2
  67. ansible/parsing/vault/__init__.py +6 -10
  68. ansible/playbook/base.py +7 -2
  69. ansible/playbook/included_file.py +3 -1
  70. ansible/playbook/play_context.py +2 -0
  71. ansible/playbook/taggable.py +19 -5
  72. ansible/playbook/task.py +2 -0
  73. ansible/plugins/action/fetch.py +3 -3
  74. ansible/plugins/action/template.py +8 -2
  75. ansible/plugins/cache/__init__.py +17 -19
  76. ansible/plugins/callback/tree.py +5 -5
  77. ansible/plugins/connection/local.py +4 -4
  78. ansible/plugins/connection/paramiko_ssh.py +5 -5
  79. ansible/plugins/connection/ssh.py +8 -6
  80. ansible/plugins/connection/winrm.py +1 -1
  81. ansible/plugins/filter/core.py +19 -21
  82. ansible/plugins/filter/encryption.py +10 -2
  83. ansible/plugins/list.py +5 -4
  84. ansible/plugins/lookup/template.py +9 -4
  85. ansible/plugins/shell/powershell.py +3 -2
  86. ansible/plugins/shell/sh.py +3 -2
  87. ansible/plugins/strategy/__init__.py +3 -3
  88. ansible/plugins/test/core.py +2 -2
  89. ansible/release.py +1 -1
  90. ansible/template/__init__.py +9 -53
  91. ansible/utils/collection_loader/_collection_finder.py +3 -3
  92. ansible/utils/display.py +23 -12
  93. ansible/utils/galaxy.py +2 -2
  94. ansible/utils/hashing.py +6 -7
  95. ansible/utils/path.py +5 -7
  96. ansible/utils/py3compat.py +2 -1
  97. ansible/utils/ssh_functions.py +3 -2
  98. ansible/vars/plugins.py +3 -3
  99. {ansible_core-2.19.0b5.dist-info → ansible_core-2.19.0b6.dist-info}/METADATA +1 -1
  100. {ansible_core-2.19.0b5.dist-info → ansible_core-2.19.0b6.dist-info}/RECORD +117 -108
  101. ansible_test/_internal/commands/integration/coverage.py +7 -2
  102. ansible_test/_internal/host_profiles.py +62 -10
  103. ansible_test/_internal/provisioning.py +10 -4
  104. ansible_test/_internal/ssh.py +1 -5
  105. ansible_test/_internal/thread.py +2 -1
  106. ansible_test/_internal/timeout.py +1 -1
  107. ansible_test/_internal/util.py +20 -12
  108. ansible_test/_util/target/setup/requirements.py +3 -9
  109. {ansible_core-2.19.0b5.dist-info → ansible_core-2.19.0b6.dist-info}/WHEEL +0 -0
  110. {ansible_core-2.19.0b5.dist-info → ansible_core-2.19.0b6.dist-info}/entry_points.txt +0 -0
  111. {ansible_core-2.19.0b5.dist-info → ansible_core-2.19.0b6.dist-info}/licenses/COPYING +0 -0
  112. {ansible_core-2.19.0b5.dist-info → ansible_core-2.19.0b6.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  113. {ansible_core-2.19.0b5.dist-info → ansible_core-2.19.0b6.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
  114. {ansible_core-2.19.0b5.dist-info → ansible_core-2.19.0b6.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  115. {ansible_core-2.19.0b5.dist-info → ansible_core-2.19.0b6.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  116. {ansible_core-2.19.0b5.dist-info → ansible_core-2.19.0b6.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  117. {ansible_core-2.19.0b5.dist-info → ansible_core-2.19.0b6.dist-info}/top_level.txt +0 -0
@@ -333,8 +333,8 @@ class SourcesList(object):
333
333
 
334
334
  try:
335
335
  fd, tmp_path = tempfile.mkstemp(prefix=".%s-" % fn, dir=d)
336
- except (OSError, IOError) as e:
337
- self.module.fail_json(msg='Unable to create temp file at "%s" for apt source: %s' % (d, to_native(e)))
336
+ except OSError as ex:
337
+ raise Exception(f'Unable to create temp file at {d!r} for apt source.') from ex
338
338
 
339
339
  f = os.fdopen(fd, 'w')
340
340
  for n, valid, enabled, source, comment in sources:
@@ -350,8 +350,8 @@ class SourcesList(object):
350
350
 
351
351
  try:
352
352
  f.write(line)
353
- except IOError as ex:
354
- self.module.fail_json(msg="Failed to write to file %s: %s" % (tmp_path, to_native(ex)))
353
+ except OSError as ex:
354
+ raise Exception(f"Failed to write to file {tmp_path!r}.") from ex
355
355
  if filename in self.files_mapping:
356
356
  # Write to symlink target instead of replacing symlink as a normal file
357
357
  self.module.atomic_move(tmp_path, self.files_mapping[filename])
@@ -507,8 +507,8 @@ class UbuntuSourcesList(SourcesList):
507
507
  if os.path.exists(key_file):
508
508
  try:
509
509
  rc, out, err = self.module.run_command([self.gpg_bin, '--list-packets', key_file])
510
- except (IOError, OSError) as e:
511
- self.debug("Could check key against file %s: %s" % (key_file, to_native(e)))
510
+ except OSError as ex:
511
+ self.debug(f"Could check key against file {key_file!r}: {ex}")
512
512
  continue
513
513
 
514
514
  if key_fingerprint in out:
@@ -557,8 +557,8 @@ class UbuntuSourcesList(SourcesList):
557
557
  with open(keyfile, 'wb') as f:
558
558
  f.write(stdout)
559
559
  self.module.log('Added repo key "%s" for apt to file "%s"' % (info['signing_key_fingerprint'], keyfile))
560
- except (OSError, IOError) as e:
561
- self.module.fail_json(msg='Unable to add required signing key for%s ', rc=rc, stderr=stderr, error=to_native(e))
560
+ except OSError as ex:
561
+ self.module.fail_json(msg='Unable to add required signing key.', rc=rc, stderr=stderr, error=str(ex), exception=ex)
562
562
 
563
563
  # apt source file
564
564
  file = file or self._suggest_filename('%s_%s' % (line, self.codename))
@@ -752,9 +752,9 @@ def main():
752
752
  )
753
753
  module.fail_json(msg=msg)
754
754
 
755
- except (OSError, IOError) as ex:
755
+ except OSError as ex:
756
756
  revert_sources_list(sources_before, sources_after, sourceslist_before)
757
- module.fail_json(msg=to_native(ex))
757
+ raise
758
758
 
759
759
  module.exit_json(changed=changed, repo=repo, sources_added=sources_added, sources_removed=sources_removed, state=state, diff=diff)
760
760
 
@@ -186,10 +186,10 @@ def cleanup(module, path, result=None):
186
186
  if os.path.exists(path):
187
187
  try:
188
188
  os.remove(path)
189
- except (IOError, OSError) as e:
189
+ except OSError as ex:
190
190
  # don't error on possible race conditions, but keep warning
191
191
  if result is not None:
192
- module.warn('Unable to remove temp file (%s): %s' % (path, to_native(e)))
192
+ module.error_as_warning(f'Unable to remove temp file {path!r}.', exception=ex)
193
193
 
194
194
 
195
195
  def main():
@@ -6,7 +6,6 @@
6
6
  from __future__ import annotations
7
7
 
8
8
 
9
- import errno
10
9
  import json
11
10
  import shlex
12
11
  import shutil
@@ -122,24 +121,14 @@ def _get_interpreter(module_path):
122
121
  return head[2:head.index(b'\n')].strip().split(b' ')
123
122
 
124
123
 
125
- def _make_temp_dir(path):
126
- # TODO: Add checks for permissions on path.
127
- try:
128
- os.makedirs(path)
129
- except OSError as e:
130
- if e.errno != errno.EEXIST:
131
- raise
132
-
133
-
134
124
  def jwrite(info):
135
-
136
125
  jobfile = job_path + ".tmp"
137
126
  tjob = open(jobfile, "w")
138
127
  try:
139
128
  tjob.write(json.dumps(info))
140
- except (IOError, OSError) as e:
141
- notice('failed to write to %s: %s' % (jobfile, str(e)))
142
- raise e
129
+ except OSError as ex:
130
+ notice(f'failed to write to {jobfile!r}: {ex}')
131
+ raise
143
132
  finally:
144
133
  tjob.close()
145
134
  os.rename(jobfile, job_path)
@@ -200,7 +189,7 @@ def _run_module(wrapped_cmd, jid):
200
189
  result['stderr'] = stderr
201
190
  jwrite(result)
202
191
 
203
- except (OSError, IOError):
192
+ except OSError:
204
193
  e = sys.exc_info()[1]
205
194
  result = {
206
195
  "failed": True,
@@ -212,7 +201,7 @@ def _run_module(wrapped_cmd, jid):
212
201
  result['ansible_job_id'] = jid
213
202
  jwrite(result)
214
203
 
215
- except (ValueError, Exception):
204
+ except Exception:
216
205
  result = {
217
206
  "failed": True,
218
207
  "cmd": wrapped_cmd,
@@ -257,7 +246,8 @@ def main():
257
246
  job_path = os.path.join(jobdir, jid)
258
247
 
259
248
  try:
260
- _make_temp_dir(jobdir)
249
+ # TODO: Add checks for permissions on path.
250
+ os.makedirs(jobdir, exist_ok=True)
261
251
  except Exception as e:
262
252
  end({
263
253
  "failed": True,
@@ -299,9 +299,9 @@ def main():
299
299
 
300
300
  try:
301
301
  os.chdir(chdir)
302
- except (IOError, OSError) as e:
303
- r['msg'] = 'Unable to change directory before execution: %s' % to_text(e)
304
- module.fail_json(**r)
302
+ except OSError as ex:
303
+ r['msg'] = 'Unable to change directory before execution.'
304
+ module.fail_json(**r, exception=ex)
305
305
 
306
306
  # check_mode partial support, since it only really works in checking creates/removes
307
307
  if module.check_mode:
ansible/modules/copy.py CHANGED
@@ -522,8 +522,8 @@ def main():
522
522
  if os.path.isfile(src):
523
523
  try:
524
524
  checksum_src = module.sha1(src)
525
- except (OSError, IOError) as e:
526
- module.warn("Unable to calculate src checksum, assuming change: %s" % to_native(e))
525
+ except OSError as ex:
526
+ module.error_as_warning("Unable to calculate src checksum, assuming change.", exception=ex)
527
527
  try:
528
528
  # Backwards compat only. This will be None in FIPS mode
529
529
  md5sum_src = module.md5(src)
@@ -636,8 +636,8 @@ def main():
636
636
  # at this point we should always have tmp file
637
637
  module.atomic_move(b_mysrc, dest, unsafe_writes=module.params['unsafe_writes'], keep_dest_attrs=not remote_src)
638
638
 
639
- except (IOError, OSError):
640
- module.fail_json(msg=f"Failed to copy {src!r} to {dest!r}.")
639
+ except OSError as ex:
640
+ raise Exception(f"Failed to copy {src!r} to {dest!r}.") from ex
641
641
  changed = True
642
642
 
643
643
  # If neither have checksums, both src and dest are directories.
ansible/modules/cron.py CHANGED
@@ -271,7 +271,7 @@ class CronTab(object):
271
271
  with open(self.b_cron_file, 'rb') as f:
272
272
  self.n_existing = to_native(f.read(), errors='surrogate_or_strict')
273
273
  self.lines = self.n_existing.splitlines()
274
- except IOError:
274
+ except OSError:
275
275
  # cron file does not exist
276
276
  return
277
277
  except Exception:
ansible/modules/file.py CHANGED
@@ -323,11 +323,8 @@ def get_state(path):
323
323
  return 'file'
324
324
 
325
325
  return 'absent'
326
- except OSError as e:
327
- if e.errno == errno.ENOENT: # It may already have been removed
328
- return 'absent'
329
- else:
330
- raise
326
+ except FileNotFoundError:
327
+ return 'absent'
331
328
 
332
329
 
333
330
  # This should be moved into the common file utilities
@@ -527,12 +524,14 @@ def ensure_absent(path):
527
524
  else:
528
525
  try:
529
526
  os.unlink(b_path)
530
- except OSError as e:
531
- if e.errno != errno.ENOENT: # It may already have been removed
532
- module.fail_json(
533
- msg=f"unlinking failed: {to_native(e)}",
534
- path=path
535
- )
527
+ except FileNotFoundError:
528
+ pass
529
+ except OSError as ex:
530
+ module.fail_json(
531
+ msg="Unlinking failed.",
532
+ path=path,
533
+ exception=ex,
534
+ )
536
535
 
537
536
  result.update({'path': path, 'changed': True, 'diff': diff, 'state': 'absent'})
538
537
  else:
@@ -560,10 +559,11 @@ def execute_touch(path, follow, timestamps):
560
559
  try:
561
560
  open(b_path, 'wb').close()
562
561
  changed = True
563
- except (OSError, IOError) as e:
562
+ except OSError as ex:
564
563
  module.fail_json(
565
- msg=f"Error, could not touch target: {to_native(e, nonstring='simplerepr')}",
566
- path=path
564
+ msg="Error, could not touch target.",
565
+ path=path,
566
+ exception=ex,
567
567
  )
568
568
  # Update the attributes on the file
569
569
  diff = initial_diff(path, 'touch', prev_state)
@@ -894,9 +894,8 @@ def ensure_hardlink(path, src, follow, force, timestamps):
894
894
  if os.path.exists(b_path):
895
895
  try:
896
896
  os.unlink(b_path)
897
- except OSError as e:
898
- if e.errno != errno.ENOENT: # It may already have been removed
899
- raise
897
+ except FileNotFoundError:
898
+ pass
900
899
  os.link(b_src, b_tmppath)
901
900
  os.rename(b_tmppath, b_path)
902
901
  except OSError as e:
ansible/modules/find.py CHANGED
@@ -571,9 +571,9 @@ def main():
571
571
 
572
572
  try:
573
573
  st = os.lstat(fsname)
574
- except (IOError, OSError) as e:
575
- module.warn("Skipped entry '%s' due to this access issue: %s\n" % (fsname, to_text(e)))
576
- skipped[fsname] = to_text(e)
574
+ except OSError as ex:
575
+ module.error_as_warning(f"Skipped entry {fsname!r} due to access issue.", exception=ex)
576
+ skipped[fsname] = str(ex)
577
577
  has_warnings = True
578
578
  continue
579
579
 
@@ -436,6 +436,23 @@ def url_get(module, url, dest, use_proxy, last_mod_time, force, timeout=10, head
436
436
  module.fail_json(msg="failed to create temporary content file: %s" % to_native(e), elapsed=elapsed)
437
437
  f.close()
438
438
  rsp.close()
439
+
440
+ # Since shutil.copyfileobj() will read from HTTPResponse in chunks, HTTPResponse.read() will not recognize
441
+ # if the entire content-length of data was not read. We need to do that validation here, unless a 'chunked'
442
+ # transfer-encoding was used, in which case we will not know content-length because it will not be returned.
443
+ # But in that case, HTTPResponse will behave correctly and recognize an IncompleteRead.
444
+
445
+ is_gzip = info.get('content-encoding') == 'gzip'
446
+
447
+ if not module.check_mode and 'content-length' in info:
448
+ # If data is decompressed, then content-length won't match the amount of data we've read, so skip.
449
+ if not is_gzip or (is_gzip and not decompress):
450
+ st = os.stat(tempname)
451
+ cl = int(info['content-length'])
452
+ if st.st_size != cl:
453
+ diff = cl - st.st_size
454
+ module.fail_json(msg=f'Incomplete read, ({rsp.length=}, {cl=}, {st.st_size=}) failed to read remaining {diff} bytes')
455
+
439
456
  return tempname, info
440
457
 
441
458
 
ansible/modules/git.py CHANGED
@@ -357,11 +357,11 @@ def relocate_repo(module, result, repo_dir, old_repo_dir, worktree_dir):
357
357
  dot_git_file.write('gitdir: %s' % repo_dir)
358
358
  result['git_dir_before'] = old_repo_dir
359
359
  result['git_dir_now'] = repo_dir
360
- except (IOError, OSError) as err:
360
+ except OSError as ex:
361
361
  # if we already moved the .git dir, roll it back
362
362
  if os.path.exists(repo_dir):
363
363
  shutil.move(repo_dir, old_repo_dir)
364
- module.fail_json(msg=u'Unable to move git dir. %s' % to_text(err))
364
+ raise Exception('Unable to move git dir.') from ex
365
365
 
366
366
 
367
367
  def head_splitter(headfile, remote, module=None, fail_on_error=False):
@@ -439,7 +439,7 @@ def write_ssh_wrapper(module):
439
439
  fd, wrapper_path = tempfile.mkstemp(prefix=module.tmpdir + '/')
440
440
  else:
441
441
  raise OSError
442
- except (IOError, OSError):
442
+ except OSError:
443
443
  fd, wrapper_path = tempfile.mkstemp()
444
444
 
445
445
  # use existing git_ssh/ssh_command, fallback to 'ssh'
@@ -824,13 +824,14 @@ def get_head_branch(git_path, module, dest, remote, bare=False):
824
824
  """
825
825
  try:
826
826
  repo_path = get_repo_path(dest, bare)
827
- except (IOError, ValueError) as err:
827
+ except (OSError, ValueError) as ex:
828
828
  # No repo path found
829
829
  # ``.git`` file does not have a valid format for detached Git dir.
830
830
  module.fail_json(
831
831
  msg='Current repo does not have a valid reference to a '
832
832
  'separate Git dir or it refers to the invalid path',
833
- details=to_text(err),
833
+ details=str(ex),
834
+ exception=ex,
834
835
  )
835
836
  # Read .git/HEAD for the name of the branch.
836
837
  # If we're in a detached HEAD state, look up the branch associated with
@@ -1290,13 +1291,14 @@ def main():
1290
1291
  if not module.check_mode:
1291
1292
  relocate_repo(module, result, separate_git_dir, repo_path, dest)
1292
1293
  repo_path = separate_git_dir
1293
- except (IOError, ValueError) as err:
1294
+ except (OSError, ValueError) as ex:
1294
1295
  # No repo path found
1295
1296
  # ``.git`` file does not have a valid format for detached Git dir.
1296
1297
  module.fail_json(
1297
1298
  msg='Current repo does not have a valid reference to a '
1298
1299
  'separate Git dir or it refers to the invalid path',
1299
- details=to_text(err),
1300
+ details=str(ex),
1301
+ exception=ex,
1300
1302
  )
1301
1303
  gitconfig = os.path.join(repo_path, 'config')
1302
1304
 
@@ -102,7 +102,6 @@ EXAMPLES = r"""
102
102
 
103
103
  import base64
104
104
  import copy
105
- import errno
106
105
  import hashlib
107
106
  import hmac
108
107
  import os
@@ -169,11 +168,10 @@ def enforce_state(module, params):
169
168
  if replace_or_add or found != (state == "present"):
170
169
  try:
171
170
  inf = open(path, "r")
172
- except IOError as e:
173
- if e.errno == errno.ENOENT:
174
- inf = None
175
- else:
176
- module.fail_json(msg="Failed to read %s: %s" % (path, str(e)))
171
+ except FileNotFoundError:
172
+ inf = None
173
+ except OSError as ex:
174
+ raise Exception(f"Failed to read {path!r}.") from ex
177
175
  try:
178
176
  with tempfile.NamedTemporaryFile(mode='w+', dir=os.path.dirname(path), delete=False) as outf:
179
177
  if inf is not None:
@@ -184,8 +182,8 @@ def enforce_state(module, params):
184
182
  inf.close()
185
183
  if state == 'present':
186
184
  outf.write(key)
187
- except (IOError, OSError) as e:
188
- module.fail_json(msg="Failed to write to file %s: %s" % (path, to_native(e)))
185
+ except OSError as ex:
186
+ raise Exception(f"Failed to write to file {path!r}.") from ex
189
187
  else:
190
188
  module.atomic_move(outf.name, path)
191
189
 
@@ -220,9 +218,8 @@ def sanity_check(module, host, key, sshkeygen):
220
218
  try:
221
219
  outf.write(key)
222
220
  outf.flush()
223
- except IOError as e:
224
- module.fail_json(msg="Failed to write to temporary file %s: %s" %
225
- (outf.name, to_native(e)))
221
+ except OSError as ex:
222
+ raise Exception(f"Failed to write to temporary file {outf.name!r}.") from ex
226
223
 
227
224
  sshkeygen_command = [sshkeygen, '-F', host, '-f', outf.name]
228
225
  rc, stdout, stderr = module.run_command(sshkeygen_command)
@@ -337,9 +334,10 @@ def compute_diff(path, found_line, replace_or_add, state, key):
337
334
  }
338
335
  try:
339
336
  inf = open(path, "r")
340
- except IOError as e:
341
- if e.errno == errno.ENOENT:
342
- diff['before_header'] = '/dev/null'
337
+ except FileNotFoundError:
338
+ diff['before_header'] = '/dev/null'
339
+ except OSError:
340
+ pass
343
341
  else:
344
342
  diff['before'] = inf.read()
345
343
  inf.close()
@@ -85,4 +85,10 @@ EXAMPLES = """
85
85
  - httpd
86
86
  - mariadb-server
87
87
  state: latest
88
+
89
+ - name: Use the dnf package manager to install httpd
90
+ ansible.builtin.package:
91
+ name: httpd
92
+ state: present
93
+ use: dnf
88
94
  """
@@ -256,8 +256,8 @@ def main():
256
256
  try:
257
257
  with open(path, 'rb') as f:
258
258
  contents = to_text(f.read(), errors='surrogate_or_strict', encoding=encoding)
259
- except (OSError, IOError) as e:
260
- module.fail_json(msg='Unable to read the contents of %s: %s' % (path, to_text(e)))
259
+ except OSError as ex:
260
+ raise Exception(f"Unable to read the contents of {path!r}.") from ex
261
261
 
262
262
  pattern = u''
263
263
  if params['after'] and params['before']:
ansible/modules/slurp.py CHANGED
@@ -85,7 +85,6 @@ import base64
85
85
  import errno
86
86
 
87
87
  from ansible.module_utils.basic import AnsibleModule
88
- from ansible.module_utils.common.text.converters import to_native
89
88
 
90
89
 
91
90
  def main():
@@ -99,20 +98,18 @@ def main():
99
98
 
100
99
  try:
101
100
  with open(source, 'rb') as source_fh:
102
- source_content = source_fh.read()
103
- except (IOError, OSError) as e:
104
- if e.errno == errno.ENOENT:
105
- msg = "file not found: %s" % source
106
- elif e.errno == errno.EACCES:
107
- msg = "file is not readable: %s" % source
108
- elif e.errno == errno.EISDIR:
109
- msg = "source is a directory and must be a file: %s" % source
101
+ data = base64.b64encode(source_fh.read())
102
+ except OSError as ex:
103
+ if ex.errno == errno.ENOENT:
104
+ msg = f"File not found: {source}"
105
+ elif ex.errno == errno.EACCES:
106
+ msg = f"File is not readable: {source}"
107
+ elif ex.errno == errno.EISDIR:
108
+ msg = f"Source is a directory and must be a file: {source}"
110
109
  else:
111
- msg = "unable to slurp file: %s" % to_native(e, errors='surrogate_then_replace')
110
+ msg = "Unable to slurp file: {source}"
112
111
 
113
- module.fail_json(msg)
114
-
115
- data = base64.b64encode(source_content)
112
+ module.fail_json(msg, exception=ex)
116
113
 
117
114
  module.exit_json(content=data, source=source, encoding='base64')
118
115
 
ansible/modules/stat.py CHANGED
@@ -354,7 +354,6 @@ stat:
354
354
  version_added: 2.3
355
355
  """
356
356
 
357
- import errno
358
357
  import grp
359
358
  import os
360
359
  import pwd
@@ -456,12 +455,11 @@ def main():
456
455
  st = os.stat(b_path)
457
456
  else:
458
457
  st = os.lstat(b_path)
459
- except OSError as e:
460
- if e.errno == errno.ENOENT:
461
- output = {'exists': False}
462
- module.exit_json(changed=False, stat=output)
463
-
464
- module.fail_json(msg=e.strerror)
458
+ except FileNotFoundError:
459
+ output = {'exists': False}
460
+ module.exit_json(changed=False, stat=output)
461
+ except OSError as ex:
462
+ module.fail_json(msg=ex.strerror, exception=ex)
465
463
 
466
464
  # process base results
467
465
  output = format_output(module, path, st)
@@ -1132,8 +1132,8 @@ def main():
1132
1132
  res_args['extract_results'] = handler.unarchive()
1133
1133
  if res_args['extract_results']['rc'] != 0:
1134
1134
  module.fail_json(msg="failed to unpack %s to %s" % (src, dest), **res_args)
1135
- except IOError:
1136
- module.fail_json(msg="failed to unpack %s to %s" % (src, dest), **res_args)
1135
+ except OSError as ex:
1136
+ module.fail_json(f"Failed to unpack {src!r} to {dest!r}.", exception=ex, **res_args)
1137
1137
  else:
1138
1138
  res_args['changed'] = True
1139
1139
 
@@ -1150,8 +1150,8 @@ def main():
1150
1150
 
1151
1151
  try:
1152
1152
  res_args['changed'] = module.set_fs_attributes_if_different(file_args, res_args['changed'], expand=False)
1153
- except (IOError, OSError) as e:
1154
- module.fail_json(msg="Unexpected error when accessing exploded file: %s" % to_native(e), **res_args)
1153
+ except OSError as ex:
1154
+ module.fail_json("Unexpected error when accessing exploded file.", exception=ex, **res_args)
1155
1155
 
1156
1156
  if '/' in filename:
1157
1157
  top_folder_path = filename.split('/')[0]
@@ -1165,8 +1165,8 @@ def main():
1165
1165
  file_args['path'] = "%s/%s" % (dest, f)
1166
1166
  try:
1167
1167
  res_args['changed'] = module.set_fs_attributes_if_different(file_args, res_args['changed'], expand=False)
1168
- except (IOError, OSError) as e:
1169
- module.fail_json(msg="Unexpected error when accessing exploded file: %s" % to_native(e), **res_args)
1168
+ except OSError as ex:
1169
+ module.fail_json("Unexpected error when accessing exploded file.", exception=ex, **res_args)
1170
1170
 
1171
1171
  if module.params['list_files']:
1172
1172
  res_args['files'] = handler.files_in_archive
ansible/modules/user.py CHANGED
@@ -1341,7 +1341,7 @@ class User(object):
1341
1341
  try:
1342
1342
  with open(ssh_public_key_file, 'r') as f:
1343
1343
  ssh_public_key = f.read().strip()
1344
- except IOError:
1344
+ except OSError:
1345
1345
  return None
1346
1346
  return ssh_public_key
1347
1347
 
@@ -380,31 +380,29 @@ class LinuxTCPConnectionInfo(TCPConnectionInfo):
380
380
  if not os.path.isfile(self.source_file[family]):
381
381
  continue
382
382
  try:
383
- f = open(self.source_file[family])
384
- for tcp_connection in f.readlines():
385
- tcp_connection = tcp_connection.strip().split()
386
- if tcp_connection[self.local_address_field] == 'local_address':
387
- continue
388
- if (tcp_connection[self.connection_state_field] not in
389
- [get_connection_state_id(_connection_state) for _connection_state in self.module.params['active_connection_states']]):
390
- continue
391
- (local_ip, local_port) = tcp_connection[self.local_address_field].split(':')
392
- if self.port != local_port:
393
- continue
394
- (remote_ip, remote_port) = tcp_connection[self.remote_address_field].split(':')
395
- if (family, remote_ip) in self.exclude_ips:
396
- continue
397
- if any((
398
- (family, local_ip) in self.ips,
399
- (family, self.match_all_ips[family]) in self.ips,
400
- local_ip.startswith(self.ipv4_mapped_ipv6_address['prefix']) and
401
- (family, self.ipv4_mapped_ipv6_address['match_all']) in self.ips,
402
- )):
403
- active_connections += 1
404
- except IOError as e:
383
+ with open(self.source_file[family]) as f:
384
+ for tcp_connection in f.readlines():
385
+ tcp_connection = tcp_connection.strip().split()
386
+ if tcp_connection[self.local_address_field] == 'local_address':
387
+ continue
388
+ if (tcp_connection[self.connection_state_field] not in
389
+ [get_connection_state_id(_connection_state) for _connection_state in self.module.params['active_connection_states']]):
390
+ continue
391
+ (local_ip, local_port) = tcp_connection[self.local_address_field].split(':')
392
+ if self.port != local_port:
393
+ continue
394
+ (remote_ip, remote_port) = tcp_connection[self.remote_address_field].split(':')
395
+ if (family, remote_ip) in self.exclude_ips:
396
+ continue
397
+ if any((
398
+ (family, local_ip) in self.ips,
399
+ (family, self.match_all_ips[family]) in self.ips,
400
+ local_ip.startswith(self.ipv4_mapped_ipv6_address['prefix']) and
401
+ (family, self.ipv4_mapped_ipv6_address['match_all']) in self.ips,
402
+ )):
403
+ active_connections += 1
404
+ except OSError:
405
405
  pass
406
- finally:
407
- f.close()
408
406
 
409
407
  return active_connections
410
408
 
@@ -549,7 +547,7 @@ def main():
549
547
  try:
550
548
  if not os.access(b_path, os.F_OK):
551
549
  break
552
- except IOError:
550
+ except OSError:
553
551
  break
554
552
  elif port:
555
553
  try:
@@ -609,7 +607,7 @@ def main():
609
607
  break
610
608
  except Exception as e:
611
609
  module.warn('wait_for failed on "%s", unexpected exception(%s): %s.).' % (path, to_native(e.__class__), to_native(e)))
612
- except IOError:
610
+ except OSError:
613
611
  pass
614
612
  elif port:
615
613
  alt_connect_timeout = math.ceil(
@@ -648,8 +646,8 @@ def main():
648
646
  # Shutdown the client socket
649
647
  try:
650
648
  s.shutdown(socket.SHUT_RDWR)
651
- except socket.error as e:
652
- if e.errno != errno.ENOTCONN:
649
+ except OSError as ex:
650
+ if ex.errno != errno.ENOTCONN:
653
651
  raise
654
652
  # else, the server broke the connection on its end, assume it's not ready
655
653
  else:
@@ -661,8 +659,8 @@ def main():
661
659
  # Connection established, success!
662
660
  try:
663
661
  s.shutdown(socket.SHUT_RDWR)
664
- except socket.error as e:
665
- if e.errno != errno.ENOTCONN:
662
+ except OSError as ex:
663
+ if ex.errno != errno.ENOTCONN:
666
664
  raise
667
665
  # else, the server broke the connection on its end, assume it's not ready
668
666
  else:
@@ -502,10 +502,11 @@ class YumRepo:
502
502
  try:
503
503
  with open(self.dest, 'w') as fd:
504
504
  self.repofile.write(fd)
505
- except IOError as e:
505
+ except OSError as ex:
506
506
  self.module.fail_json(
507
- msg=f"Problems handling file {self.dest}.",
508
- details=to_native(e),
507
+ msg=f"Problems handling file {self.dest!r}.",
508
+ details=str(ex),
509
+ exception=ex,
509
510
  )
510
511
  else:
511
512
  try: