ansible-core 2.17.4__py3-none-any.whl → 2.18.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 (320) hide show
  1. ansible/__main__.py +2 -17
  2. ansible/cli/__init__.py +3 -15
  3. ansible/cli/config.py +187 -24
  4. ansible/cli/console.py +1 -1
  5. ansible/cli/doc.py +38 -16
  6. ansible/cli/galaxy.py +30 -53
  7. ansible/cli/inventory.py +2 -2
  8. ansible/cli/pull.py +2 -2
  9. ansible/cli/scripts/ansible_connection_cli_stub.py +1 -10
  10. ansible/config/base.yml +127 -57
  11. ansible/config/manager.py +89 -11
  12. ansible/constants.py +32 -9
  13. ansible/errors/__init__.py +5 -0
  14. ansible/executor/interpreter_discovery.py +1 -1
  15. ansible/executor/play_iterator.py +16 -0
  16. ansible/executor/playbook_executor.py +1 -4
  17. ansible/executor/powershell/become_wrapper.ps1 +4 -5
  18. ansible/executor/powershell/bootstrap_wrapper.ps1 +2 -3
  19. ansible/executor/powershell/exec_wrapper.ps1 +1 -1
  20. ansible/executor/powershell/module_manifest.py +2 -2
  21. ansible/executor/task_executor.py +50 -39
  22. ansible/executor/task_queue_manager.py +1 -1
  23. ansible/executor/task_result.py +1 -1
  24. ansible/galaxy/api.py +3 -4
  25. ansible/galaxy/collection/__init__.py +21 -10
  26. ansible/galaxy/collection/concrete_artifact_manager.py +2 -2
  27. ansible/galaxy/collection/galaxy_api_proxy.py +10 -16
  28. ansible/galaxy/collection/gpg.py +17 -23
  29. ansible/galaxy/data/COPYING +7 -0
  30. ansible/galaxy/data/apb/Dockerfile.j2 +1 -0
  31. ansible/galaxy/data/apb/Makefile.j2 +1 -0
  32. ansible/galaxy/data/apb/README.md +7 -3
  33. ansible/galaxy/data/apb/apb.yml.j2 +1 -0
  34. ansible/galaxy/data/apb/defaults/main.yml.j2 +1 -0
  35. ansible/galaxy/data/apb/handlers/main.yml.j2 +1 -0
  36. ansible/galaxy/data/apb/meta/main.yml.j2 +1 -0
  37. ansible/galaxy/data/apb/playbooks/deprovision.yml.j2 +1 -0
  38. ansible/galaxy/data/apb/playbooks/provision.yml.j2 +1 -0
  39. ansible/galaxy/data/apb/tasks/main.yml.j2 +1 -0
  40. ansible/galaxy/data/apb/tests/ansible.cfg +1 -0
  41. ansible/galaxy/data/apb/tests/inventory +1 -0
  42. ansible/galaxy/data/apb/tests/test.yml.j2 +1 -0
  43. ansible/galaxy/data/apb/vars/main.yml.j2 +1 -0
  44. ansible/galaxy/data/collections_galaxy_meta.yml +1 -0
  45. ansible/galaxy/data/container/defaults/main.yml.j2 +1 -0
  46. ansible/galaxy/data/container/handlers/main.yml.j2 +1 -0
  47. ansible/galaxy/data/container/meta/container.yml.j2 +1 -0
  48. ansible/galaxy/data/container/meta/main.yml.j2 +1 -0
  49. ansible/galaxy/data/container/tasks/main.yml.j2 +1 -0
  50. ansible/galaxy/data/container/tests/ansible.cfg +1 -0
  51. ansible/galaxy/data/container/tests/inventory +1 -0
  52. ansible/galaxy/data/container/tests/test.yml.j2 +1 -0
  53. ansible/galaxy/data/container/vars/main.yml.j2 +1 -0
  54. ansible/galaxy/data/default/collection/README.md.j2 +1 -0
  55. ansible/galaxy/data/default/collection/galaxy.yml.j2 +1 -0
  56. ansible/galaxy/data/default/collection/meta/runtime.yml +1 -0
  57. ansible/galaxy/data/default/collection/plugins/README.md.j2 +1 -0
  58. ansible/galaxy/data/default/role/defaults/main.yml.j2 +1 -0
  59. ansible/galaxy/data/default/role/handlers/main.yml.j2 +1 -0
  60. ansible/galaxy/data/default/role/meta/main.yml.j2 +1 -0
  61. ansible/galaxy/data/default/role/tasks/main.yml.j2 +1 -0
  62. ansible/galaxy/data/default/role/tests/inventory +1 -0
  63. ansible/galaxy/data/default/role/tests/test.yml.j2 +1 -0
  64. ansible/galaxy/data/default/role/vars/main.yml.j2 +1 -0
  65. ansible/galaxy/data/network/cliconf_plugins/example.py.j2 +1 -0
  66. ansible/galaxy/data/network/defaults/main.yml.j2 +1 -0
  67. ansible/galaxy/data/network/library/example_command.py.j2 +1 -0
  68. ansible/galaxy/data/network/library/example_config.py.j2 +1 -0
  69. ansible/galaxy/data/network/library/example_facts.py.j2 +1 -0
  70. ansible/galaxy/data/network/meta/main.yml.j2 +1 -0
  71. ansible/galaxy/data/network/module_utils/example.py.j2 +1 -0
  72. ansible/galaxy/data/network/netconf_plugins/example.py.j2 +1 -0
  73. ansible/galaxy/data/network/tasks/main.yml.j2 +1 -0
  74. ansible/galaxy/data/network/terminal_plugins/example.py.j2 +1 -0
  75. ansible/galaxy/data/network/tests/inventory +1 -0
  76. ansible/galaxy/data/network/tests/test.yml.j2 +1 -0
  77. ansible/galaxy/data/network/vars/main.yml.j2 +1 -0
  78. ansible/galaxy/dependency_resolution/providers.py +3 -3
  79. ansible/galaxy/role.py +1 -1
  80. ansible/galaxy/token.py +20 -8
  81. ansible/keyword_desc.yml +1 -1
  82. ansible/module_utils/_internal/__init__.py +0 -0
  83. ansible/module_utils/_internal/_concurrent/__init__.py +0 -0
  84. ansible/module_utils/_internal/_concurrent/_daemon_threading.py +28 -0
  85. ansible/module_utils/_internal/_concurrent/_futures.py +21 -0
  86. ansible/module_utils/ansible_release.py +2 -2
  87. ansible/module_utils/api.py +2 -2
  88. ansible/module_utils/basic.py +14 -11
  89. ansible/module_utils/common/collections.py +1 -1
  90. ansible/module_utils/common/file.py +0 -6
  91. ansible/module_utils/common/process.py +22 -9
  92. ansible/module_utils/common/text/converters.py +5 -8
  93. ansible/module_utils/common/text/formatters.py +20 -4
  94. ansible/module_utils/common/validation.py +33 -25
  95. ansible/module_utils/compat/paramiko.py +6 -1
  96. ansible/module_utils/compat/selinux.py +2 -2
  97. ansible/module_utils/connection.py +8 -24
  98. ansible/module_utils/csharp/Ansible.Become.cs +14 -25
  99. ansible/module_utils/csharp/Ansible.Process.cs +1 -1
  100. ansible/module_utils/distro/__init__.py +1 -1
  101. ansible/module_utils/distro/_distro.py +8 -4
  102. ansible/module_utils/facts/collector.py +2 -0
  103. ansible/module_utils/facts/default_collectors.py +3 -1
  104. ansible/module_utils/facts/hardware/aix.py +54 -52
  105. ansible/module_utils/facts/hardware/darwin.py +37 -34
  106. ansible/module_utils/facts/hardware/freebsd.py +55 -15
  107. ansible/module_utils/facts/hardware/hpux.py +3 -0
  108. ansible/module_utils/facts/hardware/linux.py +101 -57
  109. ansible/module_utils/facts/hardware/netbsd.py +3 -0
  110. ansible/module_utils/facts/hardware/openbsd.py +4 -1
  111. ansible/module_utils/facts/hardware/sunos.py +7 -1
  112. ansible/module_utils/facts/network/aix.py +16 -17
  113. ansible/module_utils/facts/network/fc_wwn.py +4 -1
  114. ansible/module_utils/facts/network/hpux.py +21 -4
  115. ansible/module_utils/facts/network/iscsi.py +7 -8
  116. ansible/module_utils/facts/network/linux.py +0 -2
  117. ansible/module_utils/facts/other/facter.py +9 -4
  118. ansible/module_utils/facts/other/ohai.py +5 -5
  119. ansible/module_utils/facts/packages.py +49 -7
  120. ansible/module_utils/facts/sysctl.py +33 -31
  121. ansible/module_utils/facts/system/distribution.py +1 -1
  122. ansible/module_utils/facts/system/local.py +12 -22
  123. ansible/module_utils/facts/system/service_mgr.py +3 -1
  124. ansible/module_utils/facts/system/systemd.py +47 -0
  125. ansible/module_utils/powershell/Ansible.ModuleUtils.AddType.psm1 +1 -1
  126. ansible/module_utils/powershell/Ansible.ModuleUtils.CamelConversion.psm1 +1 -1
  127. ansible/module_utils/splitter.py +1 -1
  128. ansible/modules/add_host.py +1 -1
  129. ansible/modules/apt.py +43 -32
  130. ansible/modules/apt_key.py +6 -6
  131. ansible/modules/apt_repository.py +23 -14
  132. ansible/modules/assemble.py +7 -2
  133. ansible/modules/assert.py +4 -4
  134. ansible/modules/blockinfile.py +3 -6
  135. ansible/modules/command.py +1 -1
  136. ansible/modules/copy.py +4 -4
  137. ansible/modules/cron.py +13 -10
  138. ansible/modules/deb822_repository.py +16 -17
  139. ansible/modules/debconf.py +9 -9
  140. ansible/modules/debug.py +1 -1
  141. ansible/modules/dnf.py +79 -164
  142. ansible/modules/dnf5.py +48 -31
  143. ansible/modules/dpkg_selections.py +2 -2
  144. ansible/modules/expect.py +2 -2
  145. ansible/modules/fetch.py +2 -2
  146. ansible/modules/file.py +5 -3
  147. ansible/modules/find.py +40 -12
  148. ansible/modules/gather_facts.py +4 -2
  149. ansible/modules/get_url.py +29 -24
  150. ansible/modules/git.py +35 -35
  151. ansible/modules/group.py +71 -1
  152. ansible/modules/hostname.py +2 -4
  153. ansible/modules/include_vars.py +5 -5
  154. ansible/modules/iptables.py +13 -16
  155. ansible/modules/known_hosts.py +16 -13
  156. ansible/modules/lineinfile.py +1 -4
  157. ansible/modules/meta.py +6 -1
  158. ansible/modules/mount_facts.py +651 -0
  159. ansible/modules/package_facts.py +63 -80
  160. ansible/modules/pause.py +4 -3
  161. ansible/modules/pip.py +14 -14
  162. ansible/modules/replace.py +1 -4
  163. ansible/modules/rpm_key.py +31 -11
  164. ansible/modules/service.py +8 -8
  165. ansible/modules/service_facts.py +20 -5
  166. ansible/modules/set_stats.py +1 -1
  167. ansible/modules/setup.py +3 -3
  168. ansible/modules/stat.py +3 -3
  169. ansible/modules/subversion.py +1 -1
  170. ansible/modules/systemd.py +16 -10
  171. ansible/modules/systemd_service.py +16 -10
  172. ansible/modules/sysvinit.py +4 -4
  173. ansible/modules/unarchive.py +35 -22
  174. ansible/modules/uri.py +24 -18
  175. ansible/modules/user.py +145 -12
  176. ansible/modules/validate_argument_spec.py +3 -3
  177. ansible/modules/wait_for_connection.py +2 -1
  178. ansible/modules/yum_repository.py +136 -179
  179. ansible/parsing/dataloader.py +2 -2
  180. ansible/parsing/mod_args.py +11 -10
  181. ansible/parsing/vault/__init__.py +8 -3
  182. ansible/parsing/yaml/constructor.py +10 -8
  183. ansible/parsing/yaml/objects.py +1 -1
  184. ansible/playbook/base.py +12 -23
  185. ansible/playbook/helpers.py +4 -0
  186. ansible/playbook/loop_control.py +8 -0
  187. ansible/playbook/play.py +4 -22
  188. ansible/playbook/play_context.py +0 -16
  189. ansible/playbook/playbook_include.py +2 -2
  190. ansible/playbook/role/__init__.py +2 -2
  191. ansible/playbook/task.py +1 -1
  192. ansible/plugins/__init__.py +2 -0
  193. ansible/plugins/action/__init__.py +7 -9
  194. ansible/plugins/action/reboot.py +2 -2
  195. ansible/plugins/become/__init__.py +1 -1
  196. ansible/plugins/callback/__init__.py +44 -3
  197. ansible/plugins/callback/default.py +1 -1
  198. ansible/plugins/cliconf/__init__.py +1 -1
  199. ansible/plugins/connection/paramiko_ssh.py +2 -80
  200. ansible/plugins/connection/psrp.py +33 -82
  201. ansible/plugins/connection/ssh.py +0 -8
  202. ansible/plugins/connection/winrm.py +46 -1
  203. ansible/plugins/doc_fragments/connection_pipelining.py +2 -2
  204. ansible/plugins/doc_fragments/constructed.py +10 -10
  205. ansible/plugins/doc_fragments/default_callback.py +8 -8
  206. ansible/plugins/doc_fragments/files.py +5 -5
  207. ansible/plugins/doc_fragments/inventory_cache.py +2 -2
  208. ansible/plugins/doc_fragments/result_format_callback.py +6 -6
  209. ansible/plugins/doc_fragments/return_common.py +1 -1
  210. ansible/plugins/doc_fragments/shell_common.py +2 -10
  211. ansible/plugins/doc_fragments/shell_windows.py +0 -9
  212. ansible/plugins/doc_fragments/url.py +2 -2
  213. ansible/plugins/doc_fragments/url_windows.py +4 -5
  214. ansible/plugins/doc_fragments/validate.py +1 -1
  215. ansible/plugins/filter/core.py +2 -0
  216. ansible/plugins/filter/human_to_bytes.yml +9 -0
  217. ansible/plugins/filter/password_hash.yml +1 -1
  218. ansible/plugins/filter/strftime.yml +1 -1
  219. ansible/plugins/filter/to_nice_json.yml +7 -3
  220. ansible/plugins/filter/to_uuid.yml +1 -1
  221. ansible/plugins/inventory/script.py +1 -1
  222. ansible/plugins/list.py +1 -1
  223. ansible/plugins/loader.py +0 -11
  224. ansible/plugins/lookup/config.py +1 -1
  225. ansible/plugins/lookup/csvfile.py +21 -9
  226. ansible/plugins/lookup/env.py +8 -9
  227. ansible/plugins/lookup/ini.py +10 -1
  228. ansible/plugins/lookup/random_choice.py +2 -2
  229. ansible/plugins/lookup/url.py +7 -2
  230. ansible/plugins/shell/__init__.py +15 -20
  231. ansible/plugins/shell/powershell.py +9 -6
  232. ansible/plugins/strategy/__init__.py +16 -7
  233. ansible/plugins/test/core.py +23 -1
  234. ansible/plugins/test/issubset.yml +1 -1
  235. ansible/plugins/test/subset.yml +1 -1
  236. ansible/plugins/test/timedout.yml +20 -0
  237. ansible/plugins/test/vault_encrypted.yml +6 -6
  238. ansible/plugins/test/vaulted_file.yml +19 -0
  239. ansible/release.py +2 -2
  240. ansible/template/__init__.py +3 -8
  241. ansible/utils/collection_loader/_collection_finder.py +23 -55
  242. ansible/utils/display.py +44 -31
  243. ansible/utils/jsonrpc.py +1 -1
  244. ansible/utils/listify.py +1 -5
  245. ansible/utils/path.py +3 -0
  246. ansible/utils/vars.py +18 -27
  247. ansible/vars/manager.py +7 -150
  248. ansible/vars/plugins.py +1 -1
  249. ansible_core-2.18.0b1.dist-info/Apache-License.txt +202 -0
  250. {ansible_core-2.17.4.dist-info → ansible_core-2.18.0b1.dist-info}/METADATA +36 -23
  251. ansible_core-2.18.0b1.dist-info/MIT-license.txt +14 -0
  252. ansible_core-2.18.0b1.dist-info/PSF-license.txt +48 -0
  253. {ansible_core-2.17.4.dist-info → ansible_core-2.18.0b1.dist-info}/RECORD +311 -306
  254. {ansible_core-2.17.4.dist-info → ansible_core-2.18.0b1.dist-info}/WHEEL +1 -1
  255. {ansible_core-2.17.4.dist-info → ansible_core-2.18.0b1.dist-info}/entry_points.txt +1 -1
  256. ansible_core-2.18.0b1.dist-info/simplified_bsd.txt +8 -0
  257. ansible_test/_data/completion/docker.txt +7 -7
  258. ansible_test/_data/completion/remote.txt +5 -4
  259. ansible_test/_data/completion/windows.txt +4 -4
  260. ansible_test/_data/requirements/ansible-test.txt +1 -2
  261. ansible_test/_data/requirements/constraints.txt +1 -2
  262. ansible_test/_data/requirements/sanity.ansible-doc.txt +3 -3
  263. ansible_test/_data/requirements/sanity.changelog.in +1 -1
  264. ansible_test/_data/requirements/sanity.changelog.txt +4 -4
  265. ansible_test/_data/requirements/sanity.import.plugin.txt +2 -2
  266. ansible_test/_data/requirements/sanity.import.txt +1 -1
  267. ansible_test/_data/requirements/sanity.integration-aliases.txt +1 -1
  268. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  269. ansible_test/_data/requirements/sanity.pylint.txt +5 -7
  270. ansible_test/_data/requirements/sanity.runtime-metadata.txt +2 -2
  271. ansible_test/_data/requirements/sanity.validate-modules.txt +3 -3
  272. ansible_test/_data/requirements/sanity.yamllint.in +1 -0
  273. ansible_test/_data/requirements/sanity.yamllint.txt +1 -1
  274. ansible_test/_internal/ansible_util.py +8 -35
  275. ansible_test/_internal/ci/azp.py +1 -1
  276. ansible_test/_internal/classification/__init__.py +0 -2
  277. ansible_test/_internal/cli/parsers/key_value_parsers.py +3 -0
  278. ansible_test/_internal/commands/integration/cloud/hcloud.py +1 -1
  279. ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
  280. ansible_test/_internal/commands/integration/cloud/nios.py +1 -1
  281. ansible_test/_internal/commands/sanity/__init__.py +96 -19
  282. ansible_test/_internal/commands/sanity/pylint.py +20 -24
  283. ansible_test/_internal/completion.py +2 -0
  284. ansible_test/_internal/constants.py +0 -1
  285. ansible_test/_internal/coverage_util.py +1 -2
  286. ansible_test/_internal/docker_util.py +1 -1
  287. ansible_test/_internal/host_configs.py +10 -0
  288. ansible_test/_internal/host_profiles.py +9 -13
  289. ansible_test/_internal/pypi_proxy.py +1 -1
  290. ansible_test/_internal/python_requirements.py +5 -14
  291. ansible_test/_internal/timeout.py +1 -1
  292. ansible_test/_internal/util.py +40 -0
  293. ansible_test/_internal/util_common.py +5 -1
  294. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.json +3 -1
  295. ansible_test/_util/controller/sanity/code-smell/action-plugin-docs.py +6 -3
  296. ansible_test/_util/controller/sanity/code-smell/empty-init.json +0 -2
  297. ansible_test/_util/controller/sanity/pylint/config/collection.cfg +1 -0
  298. ansible_test/_util/controller/sanity/pylint/config/default.cfg +1 -0
  299. ansible_test/_util/controller/sanity/pylint/plugins/deprecated.py +1 -19
  300. ansible_test/_util/controller/sanity/shellcheck/exclude.txt +1 -0
  301. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +67 -2
  302. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +27 -5
  303. ansible_test/_util/target/cli/ansible_test_cli_stub.py +0 -0
  304. ansible_test/_util/target/common/constants.py +2 -2
  305. ansible_test/_util/target/injector/python.py +5 -0
  306. ansible_test/_util/target/pytest/plugins/ansible_pytest_coverage.py +6 -0
  307. ansible_test/_util/target/sanity/import/importer.py +1 -1
  308. ansible_test/_util/target/setup/bootstrap.sh +6 -17
  309. ansible_test/_util/target/setup/requirements.py +14 -20
  310. ansible_test/config/config.yml +1 -1
  311. ansible_core-2.17.4.data/scripts/ansible-test +0 -44
  312. ansible_test/_data/requirements/sanity.mypy.in +0 -10
  313. ansible_test/_data/requirements/sanity.mypy.txt +0 -18
  314. ansible_test/_internal/commands/sanity/mypy.py +0 -274
  315. ansible_test/_util/controller/sanity/mypy/ansible-core.ini +0 -116
  316. ansible_test/_util/controller/sanity/mypy/ansible-test.ini +0 -27
  317. ansible_test/_util/controller/sanity/mypy/modules.ini +0 -92
  318. ansible_test/_util/controller/sanity/mypy/packaging.ini +0 -20
  319. {ansible_core-2.17.4.dist-info → ansible_core-2.18.0b1.dist-info}/COPYING +0 -0
  320. {ansible_core-2.17.4.dist-info → ansible_core-2.18.0b1.dist-info}/top_level.txt +0 -0
@@ -6,12 +6,15 @@ import importlib.util
6
6
  import os
7
7
  import sys
8
8
 
9
+ NETWORKING_CLI_STUB_SCRIPT = 'ansible_connection_cli_stub.py'
10
+
9
11
 
10
12
  def main():
11
13
  """Main entry point."""
12
14
  name = os.path.basename(__file__)
13
15
  args = [sys.executable]
14
16
 
17
+ ansible_lib_root = os.environ.get('ANSIBLE_TEST_ANSIBLE_LIB_ROOT')
15
18
  coverage_config = os.environ.get('COVERAGE_CONF')
16
19
  coverage_output = os.environ.get('COVERAGE_FILE')
17
20
 
@@ -33,6 +36,8 @@ def main():
33
36
  args += ['-m', 'pytest']
34
37
  elif name == 'importer.py':
35
38
  args += [find_program(name, False)]
39
+ elif name == NETWORKING_CLI_STUB_SCRIPT:
40
+ args += [os.path.join(ansible_lib_root, 'cli/scripts', NETWORKING_CLI_STUB_SCRIPT)]
36
41
  else:
37
42
  args += [find_program(name, True)]
38
43
 
@@ -53,6 +53,12 @@ def pytest_configure():
53
53
 
54
54
  def coverage_exit(*args, **kwargs):
55
55
  for instance in coverage_instances:
56
+ # skip coverage instances which have no collector, or the collector is not the active collector
57
+ # this avoids issues with coverage 7.4.0+ when tests create subprocesses which inherit our overridden os._exit method
58
+ # pylint: disable=protected-access
59
+ if not instance._collector or not instance._collector._collectors or instance._collector != instance._collector._collectors[-1]:
60
+ continue
61
+
56
62
  instance.stop()
57
63
  instance.save()
58
64
 
@@ -159,7 +159,7 @@ def main():
159
159
  loader = self._get_loader(fullname, path=path)
160
160
  if loader is not None:
161
161
  if has_py3_loader:
162
- # loader is expected to be Optional[importlib.abc.Loader], but RestrictedModuleLoader does not inherit from importlib.abc.Loder
162
+ # loader is expected to be Optional[importlib.abc.Loader], but RestrictedModuleLoader does not inherit from importlib.abc.Loader
163
163
  return spec_from_loader(fullname, loader) # type: ignore[arg-type]
164
164
  raise ImportError("Failed to import '%s' due to a bug in ansible-test. Check importlib imports for typos." % fullname)
165
165
  return None
@@ -53,14 +53,14 @@ customize_bashrc()
53
53
  fi
54
54
 
55
55
  # Improve shell prompts for interactive use.
56
- echo "export PS1='\[\e]0;\u@\h: \w\a\]\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '" >> ~/.bashrc
56
+ echo "export PS1='"'\[\e]0;\u@\h: \w\a\]\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '"'" >> ~/.bashrc
57
57
  }
58
58
 
59
59
  install_pip() {
60
60
  if ! "${python_interpreter}" -m pip.__main__ --version --disable-pip-version-check 2>/dev/null; then
61
61
  case "${python_version}" in
62
62
  *)
63
- pip_bootstrap_url="https://ci-files.testing.ansible.com/ansible-test/get-pip-23.1.2.py"
63
+ pip_bootstrap_url="https://ci-files.testing.ansible.com/ansible-test/get-pip-24.0.py"
64
64
  ;;
65
65
  esac
66
66
 
@@ -176,10 +176,10 @@ bootstrap_remote_freebsd()
176
176
  cryptography_pkg="" # not available
177
177
  pyyaml_pkg="" # not available
178
178
  ;;
179
- 14.0/3.9)
179
+ 14.1/3.9)
180
180
  # defaults above 'just work'TM
181
181
  ;;
182
- 14.0/3.11)
182
+ 14.1/3.11)
183
183
  cryptography_pkg="" # not available
184
184
  jinja2_pkg="" # not available
185
185
  pyyaml_pkg="" # not available
@@ -268,19 +268,12 @@ bootstrap_remote_rhel_9()
268
268
  packages="
269
269
  gcc
270
270
  ${py_pkg_prefix}-devel
271
+ ${py_pkg_prefix}-pip
271
272
  "
272
273
 
273
- # pip is not included in the Python devel package under Python 3.11
274
- if [ "${python_version}" != "3.9" ]; then
275
- packages="
276
- ${packages}
277
- ${py_pkg_prefix}-pip
278
- "
279
- fi
280
-
281
274
  # Jinja2 is not installed with an OS package since the provided version is too old.
282
275
  # Instead, ansible-test will install it using pip.
283
- # packaging and resolvelib are missing for Python 3.11 (and possible later) so we just
276
+ # packaging and resolvelib are missing for controller supported Python versions, so we just
284
277
  # skip them and let ansible-test install them from PyPI.
285
278
  if [ "${controller}" ]; then
286
279
  packages="
@@ -329,10 +322,6 @@ bootstrap_remote_ubuntu()
329
322
  # For these ansible-test will use pip to install the requirements instead.
330
323
  # Only the platform is checked since Ubuntu shares Python packages across Python versions.
331
324
  case "${platform_version}" in
332
- "20.04")
333
- jinja2_pkg="" # too old
334
- resolvelib_pkg="" # not available
335
- ;;
336
325
  esac
337
326
 
338
327
  packages="
@@ -22,27 +22,13 @@ import errno
22
22
  import io
23
23
  import json
24
24
  import os
25
+ import shlex
25
26
  import shutil
26
27
  import subprocess
27
28
  import sys
28
29
  import tempfile
29
-
30
- try:
31
- import typing as t
32
- except ImportError:
33
- t = None
34
-
35
- try:
36
- from shlex import quote as cmd_quote
37
- except ImportError:
38
- # noinspection PyProtectedMember
39
- from pipes import quote as cmd_quote
40
-
41
- try:
42
- from urllib.request import urlopen
43
- except ImportError:
44
- # noinspection PyCompatibility,PyUnresolvedReferences
45
- from urllib2 import urlopen # pylint: disable=ansible-bad-import-from
30
+ import typing as t
31
+ import urllib.request
46
32
 
47
33
  ENCODING = 'utf-8'
48
34
 
@@ -80,6 +66,8 @@ def bootstrap(pip, options): # type: (str, t.Dict[str, t.Any]) -> None
80
66
  """Bootstrap pip and related packages in an empty virtual environment."""
81
67
  pip_version = options['pip_version']
82
68
  packages = options['packages']
69
+ setuptools = options['setuptools']
70
+ wheel = options['wheel']
83
71
 
84
72
  url = 'https://ci-files.testing.ansible.com/ansible-test/get-pip-%s.py' % pip_version
85
73
  cache_path = os.path.expanduser('~/.ansible/test/cache/get_pip_%s.py' % pip_version.replace(".", "_"))
@@ -115,6 +103,12 @@ https://github.com/ansible/ansible/issues/77304
115
103
  options = common_pip_options()
116
104
  options.extend(packages)
117
105
 
106
+ if not setuptools:
107
+ options.append('--no-setuptools')
108
+
109
+ if not wheel:
110
+ options.append('--no-wheel')
111
+
118
112
  command = [sys.executable, pip] + options
119
113
 
120
114
  execute_command(command, env=env)
@@ -280,7 +274,7 @@ def devnull(): # type: () -> t.IO[bytes]
280
274
  def download_file(url, path): # type: (str, str) -> None
281
275
  """Download the given URL to the specified file path."""
282
276
  with open(to_bytes(path), 'wb') as saved_file:
283
- with contextlib.closing(urlopen(url)) as download:
277
+ with contextlib.closing(urllib.request.urlopen(url)) as download:
284
278
  shutil.copyfileobj(download, saved_file)
285
279
 
286
280
 
@@ -291,7 +285,7 @@ class ApplicationError(Exception):
291
285
  class SubprocessError(ApplicationError):
292
286
  """A command returned a non-zero status."""
293
287
  def __init__(self, cmd, status, stdout, stderr): # type: (t.List[str], int, str, str) -> None
294
- message = 'A command failed with status %d: %s' % (status, ' '.join(cmd_quote(c) for c in cmd))
288
+ message = 'A command failed with status %d: %s' % (status, shlex.join(cmd))
295
289
 
296
290
  if stderr:
297
291
  message += '\n>>> Standard Error\n%s' % stderr.strip()
@@ -313,7 +307,7 @@ def log(message, verbosity=0): # type: (str, int) -> None
313
307
 
314
308
  def execute_command(cmd, cwd=None, capture=False, env=None): # type: (t.List[str], t.Optional[str], bool, t.Optional[t.Dict[str, str]]) -> None
315
309
  """Execute the specified command."""
316
- log('Execute command: %s' % ' '.join(cmd_quote(c) for c in cmd), verbosity=1)
310
+ log('Execute command: %s' % shlex.join(cmd), verbosity=1)
317
311
 
318
312
  cmd_bytes = [to_bytes(c) for c in cmd]
319
313
 
@@ -17,7 +17,7 @@ modules:
17
17
  # This is the default value if no configuration is provided.
18
18
  # - 'controller' - All Python versions supported by the Ansible controller.
19
19
  # This indicates the modules/module_utils can only run on the controller.
20
- # Intended for use only with modules/module_utils that depend on ansible-connection, which only runs on the controller.
20
+ # Intended for use only with modules/module_utils that depend on the Ansible persistent connection helper, which only runs on the controller.
21
21
  # Unit tests for modules/module_utils will be permitted to import any Ansible code, instead of only module_utils.
22
22
  # - SpecifierSet - A PEP 440 specifier set indicating the supported Python versions.
23
23
  # This is only needed when modules/module_utils do not support all Python versions supported by Ansible.
@@ -1,44 +0,0 @@
1
- #!python
2
- # PYTHON_ARGCOMPLETE_OK
3
- """Command line entry point for ansible-test."""
4
-
5
- # NOTE: This file resides in the _util/target directory to ensure compatibility with all supported Python versions.
6
-
7
- from __future__ import annotations
8
-
9
- import os
10
- import sys
11
-
12
-
13
- def main(args=None):
14
- """Main program entry point."""
15
- ansible_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16
- source_root = os.path.join(ansible_root, 'test', 'lib')
17
-
18
- if os.path.exists(os.path.join(source_root, 'ansible_test', '_internal', '__init__.py')):
19
- # running from source, use that version of ansible-test instead of any version that may already be installed
20
- sys.path.insert(0, source_root)
21
-
22
- # noinspection PyProtectedMember
23
- from ansible_test._util.target.common.constants import CONTROLLER_PYTHON_VERSIONS
24
-
25
- if version_to_str(sys.version_info[:2]) not in CONTROLLER_PYTHON_VERSIONS:
26
- raise SystemExit('This version of ansible-test cannot be executed with Python version %s. Supported Python versions are: %s' % (
27
- version_to_str(sys.version_info[:3]), ', '.join(CONTROLLER_PYTHON_VERSIONS)))
28
-
29
- if any(not os.get_blocking(handle.fileno()) for handle in (sys.stdin, sys.stdout, sys.stderr)):
30
- raise SystemExit('Standard input, output and error file handles must be blocking to run ansible-test.')
31
-
32
- # noinspection PyProtectedMember
33
- from ansible_test._internal import main as cli_main
34
-
35
- cli_main(args)
36
-
37
-
38
- def version_to_str(version):
39
- """Return a version string from a version tuple."""
40
- return '.'.join(str(n) for n in version)
41
-
42
-
43
- if __name__ == '__main__':
44
- main()
@@ -1,10 +0,0 @@
1
- mypy
2
- cryptography # type stubs not published separately
3
- jinja2 # type stubs not published separately
4
- packaging # type stubs not published separately
5
- types-backports
6
- types-paramiko
7
- types-pyyaml
8
- types-requests
9
- types-setuptools
10
- types-toml
@@ -1,18 +0,0 @@
1
- # edit "sanity.mypy.in" and generate with: hacking/update-sanity-requirements.py --test mypy
2
- cffi==1.16.0
3
- cryptography==42.0.5
4
- Jinja2==3.1.3
5
- MarkupSafe==2.1.5
6
- mypy==1.9.0
7
- mypy-extensions==1.0.0
8
- packaging==24.0
9
- pycparser==2.21
10
- tomli==2.0.1
11
- types-backports==0.1.3
12
- types-paramiko==3.4.0.20240311
13
- types-PyYAML==6.0.12.20240311
14
- types-requests==2.31.0.20240311
15
- types-setuptools==69.2.0.20240317
16
- types-toml==0.10.8.20240310
17
- typing_extensions==4.10.0
18
- urllib3==2.2.1
@@ -1,274 +0,0 @@
1
- """Sanity test which executes mypy."""
2
- from __future__ import annotations
3
-
4
- import dataclasses
5
- import os
6
- import re
7
- import typing as t
8
-
9
- from . import (
10
- SanityMultipleVersion,
11
- SanityMessage,
12
- SanityFailure,
13
- SanitySuccess,
14
- SanitySkipped,
15
- SanityTargets,
16
- create_sanity_virtualenv,
17
- )
18
-
19
- from ...constants import (
20
- CONTROLLER_PYTHON_VERSIONS,
21
- REMOTE_ONLY_PYTHON_VERSIONS,
22
- SUPPORTED_PYTHON_VERSIONS,
23
- )
24
-
25
- from ...test import (
26
- TestResult,
27
- )
28
-
29
- from ...target import (
30
- TestTarget,
31
- )
32
-
33
- from ...util import (
34
- SubprocessError,
35
- display,
36
- parse_to_list_of_dict,
37
- ANSIBLE_TEST_CONTROLLER_ROOT,
38
- ApplicationError,
39
- is_subdir,
40
- str_to_version,
41
- )
42
-
43
- from ...util_common import (
44
- intercept_python,
45
- )
46
-
47
- from ...ansible_util import (
48
- ansible_environment,
49
- )
50
-
51
- from ...config import (
52
- SanityConfig,
53
- )
54
-
55
- from ...host_configs import (
56
- PythonConfig,
57
- VirtualPythonConfig,
58
- )
59
-
60
-
61
- class MypyTest(SanityMultipleVersion):
62
- """Sanity test which executes mypy."""
63
-
64
- ansible_only = True
65
-
66
- vendored_paths = (
67
- 'lib/ansible/module_utils/six/__init__.py',
68
- 'lib/ansible/module_utils/distro/_distro.py',
69
- )
70
-
71
- def filter_targets(self, targets: list[TestTarget]) -> list[TestTarget]:
72
- """Return the given list of test targets, filtered to include only those relevant for the test."""
73
- return [target for target in targets if os.path.splitext(target.path)[1] == '.py' and target.path not in self.vendored_paths and (
74
- target.path.startswith('lib/ansible/') or target.path.startswith('test/lib/ansible_test/_internal/')
75
- or target.path.startswith('packaging/')
76
- or target.path.startswith('test/lib/ansible_test/_util/target/sanity/import/'))]
77
-
78
- @property
79
- def error_code(self) -> t.Optional[str]:
80
- """Error code for ansible-test matching the format used by the underlying test program, or None if the program does not use error codes."""
81
- return 'ansible-test'
82
-
83
- @property
84
- def needs_pypi(self) -> bool:
85
- """True if the test requires PyPI, otherwise False."""
86
- return True
87
-
88
- @property
89
- def supported_python_versions(self) -> t.Optional[tuple[str, ...]]:
90
- """A tuple of supported Python versions or None if the test does not depend on specific Python versions."""
91
- # Because the version of typeshed mypy use in 1.9 doesn't support 3.7, neither does mypy 1.9.
92
- # see: https://mypy-lang.blogspot.com/2024/03/mypy-19-released.html
93
- return tuple(version for version in SUPPORTED_PYTHON_VERSIONS if str_to_version(version) >= (3, 8))
94
-
95
- def test(self, args: SanityConfig, targets: SanityTargets, python: PythonConfig) -> TestResult:
96
- settings = self.load_processor(args, python.version)
97
-
98
- paths = [target.path for target in targets.include]
99
-
100
- virtualenv_python = create_sanity_virtualenv(args, args.controller_python, self.name)
101
-
102
- if args.prime_venvs:
103
- return SanitySkipped(self.name, python_version=python.version)
104
-
105
- if not virtualenv_python:
106
- display.warning(f'Skipping sanity test "{self.name}" due to missing virtual environment support on Python {args.controller_python.version}.')
107
- return SanitySkipped(self.name, python.version)
108
-
109
- controller_python_versions = CONTROLLER_PYTHON_VERSIONS
110
- remote_only_python_versions = REMOTE_ONLY_PYTHON_VERSIONS
111
-
112
- contexts = (
113
- MyPyContext('ansible-test', ['test/lib/ansible_test/_util/target/sanity/import/'], controller_python_versions),
114
- MyPyContext('ansible-test', ['test/lib/ansible_test/_internal/'], controller_python_versions),
115
- MyPyContext('ansible-core', ['lib/ansible/'], controller_python_versions),
116
- MyPyContext('modules', ['lib/ansible/modules/', 'lib/ansible/module_utils/'], remote_only_python_versions),
117
- MyPyContext('packaging', ['packaging/'], controller_python_versions),
118
- )
119
-
120
- unfiltered_messages: list[SanityMessage] = []
121
-
122
- for context in contexts:
123
- if python.version not in context.python_versions:
124
- continue
125
-
126
- unfiltered_messages.extend(self.test_context(args, virtualenv_python, python, context, paths))
127
-
128
- notices = []
129
- messages = []
130
-
131
- for message in unfiltered_messages:
132
- if message.level != 'error':
133
- notices.append(message)
134
- continue
135
-
136
- match = re.search(r'^(?P<message>.*) {2}\[(?P<code>.*)]$', message.message)
137
-
138
- messages.append(SanityMessage(
139
- message=match.group('message'),
140
- path=message.path,
141
- line=message.line,
142
- column=message.column,
143
- level=message.level,
144
- code=match.group('code'),
145
- ))
146
-
147
- for notice in notices:
148
- display.info(notice.format(), verbosity=3)
149
-
150
- # The following error codes from mypy indicate that results are incomplete.
151
- # That prevents the test from completing successfully, just as if mypy were to traceback or generate unexpected output.
152
- fatal_error_codes = {
153
- 'import',
154
- 'syntax',
155
- }
156
-
157
- fatal_errors = [message for message in messages if message.code in fatal_error_codes]
158
-
159
- if fatal_errors:
160
- error_message = '\n'.join(error.format() for error in fatal_errors)
161
- raise ApplicationError(f'Encountered {len(fatal_errors)} fatal errors reported by mypy:\n{error_message}')
162
-
163
- paths_set = set(paths)
164
-
165
- # Only report messages for paths that were specified as targets.
166
- # Imports in our code are followed by mypy in order to perform its analysis, which is important for accurate results.
167
- # However, it will also report issues on those files, which is not the desired behavior.
168
- messages = [message for message in messages if message.path in paths_set]
169
-
170
- if args.explain:
171
- return SanitySuccess(self.name, python_version=python.version)
172
-
173
- results = settings.process_errors(messages, paths)
174
-
175
- if results:
176
- return SanityFailure(self.name, messages=results, python_version=python.version)
177
-
178
- return SanitySuccess(self.name, python_version=python.version)
179
-
180
- @staticmethod
181
- def test_context(
182
- args: SanityConfig,
183
- virtualenv_python: VirtualPythonConfig,
184
- python: PythonConfig,
185
- context: MyPyContext,
186
- paths: list[str],
187
- ) -> list[SanityMessage]:
188
- """Run mypy tests for the specified context."""
189
- context_paths = [path for path in paths if any(is_subdir(path, match_path) for match_path in context.paths)]
190
-
191
- if not context_paths:
192
- return []
193
-
194
- config_path = os.path.join(ANSIBLE_TEST_CONTROLLER_ROOT, 'sanity', 'mypy', f'{context.name}.ini')
195
-
196
- display.info(f'Checking context "{context.name}"', verbosity=1)
197
-
198
- env = ansible_environment(args, color=False)
199
- env['MYPYPATH'] = env['PYTHONPATH']
200
-
201
- # The --no-site-packages option should not be used, as it will prevent loading of type stubs from the sanity test virtual environment.
202
-
203
- # Enabling the --warn-unused-configs option would help keep the config files clean.
204
- # However, the option can only be used when all files in tested contexts are evaluated.
205
- # Unfortunately sanity tests have no way of making that determination currently.
206
- # The option is also incompatible with incremental mode and caching.
207
-
208
- cmd = [
209
- # Below are arguments common to all contexts.
210
- # They are kept here to avoid repetition in each config file.
211
- virtualenv_python.path,
212
- '-m', 'mypy',
213
- '--show-column-numbers',
214
- '--show-error-codes',
215
- '--no-error-summary',
216
- # This is a fairly common pattern in our code, so we'll allow it.
217
- '--allow-redefinition',
218
- # Since we specify the path(s) to test, it's important that mypy is configured to use the default behavior of following imports.
219
- '--follow-imports', 'normal',
220
- # Incremental results and caching do not provide significant performance benefits.
221
- # It also prevents the use of the --warn-unused-configs option.
222
- '--no-incremental',
223
- '--cache-dir', '/dev/null',
224
- # The platform is specified here so that results are consistent regardless of what platform the tests are run from.
225
- # In the future, if testing of other platforms is desired, the platform should become part of the test specification, just like the Python version.
226
- '--platform', 'linux',
227
- # Despite what the documentation [1] states, the --python-version option does not cause mypy to search for a corresponding Python executable.
228
- # It will instead use the Python executable that is used to run mypy itself.
229
- # The --python-executable option can be used to specify the Python executable, with the default being the executable used to run mypy.
230
- # As a precaution, that option is used in case the behavior of mypy is updated in the future to match the documentation.
231
- # That should help guarantee that the Python executable providing type hints is the one used to run mypy.
232
- # [1] https://mypy.readthedocs.io/en/stable/command_line.html#cmdoption-mypy-python-version
233
- '--python-executable', virtualenv_python.path,
234
- '--python-version', python.version,
235
- # Below are context specific arguments.
236
- # They are primarily useful for listing individual 'ignore_missing_imports' entries instead of using a global ignore.
237
- '--config-file', config_path,
238
- ] # fmt: skip
239
-
240
- cmd.extend(context_paths)
241
-
242
- try:
243
- stdout, stderr = intercept_python(args, virtualenv_python, cmd, env, capture=True)
244
-
245
- if stdout or stderr:
246
- raise SubprocessError(cmd, stdout=stdout, stderr=stderr)
247
- except SubprocessError as ex:
248
- if ex.status != 1 or ex.stderr or not ex.stdout:
249
- raise
250
-
251
- stdout = ex.stdout
252
-
253
- pattern = r'^(?P<path>[^:]*):(?P<line>[0-9]+):((?P<column>[0-9]+):)? (?P<level>[^:]+): (?P<message>.*)$'
254
-
255
- parsed = parse_to_list_of_dict(pattern, stdout or '')
256
-
257
- messages = [SanityMessage(
258
- level=r['level'],
259
- message=r['message'],
260
- path=r['path'],
261
- line=int(r['line']),
262
- column=int(r.get('column') or '0'),
263
- ) for r in parsed]
264
-
265
- return messages
266
-
267
-
268
- @dataclasses.dataclass(frozen=True)
269
- class MyPyContext:
270
- """Context details for a single run of mypy."""
271
-
272
- name: str
273
- paths: list[str]
274
- python_versions: tuple[str, ...]
@@ -1,116 +0,0 @@
1
- # IMPORTANT
2
- # Set "ignore_missing_imports" per package below, rather than globally.
3
- # That will help identify missing type stubs that should be added to the sanity test environment.
4
-
5
- [mypy]
6
- # There are ~20 errors reported in ansible-core when strict optional checking is enabled.
7
- # Until the number of occurrences are reduced, it's better to disable strict checking.
8
- strict_optional = False
9
- # There are ~70 errors reported in ansible-core when checking attributes.
10
- # Until the number of occurrences are reduced, it's better to disable the check.
11
- disable_error_code = attr-defined
12
-
13
- [mypy-ansible.module_utils.six.moves.*]
14
- ignore_missing_imports = True
15
-
16
- [mypy-passlib.*]
17
- ignore_missing_imports = True
18
-
19
- [mypy-pexpect.*]
20
- ignore_missing_imports = True
21
-
22
- [mypy-pypsrp.*]
23
- ignore_missing_imports = True
24
-
25
- [mypy-winrm.*]
26
- ignore_missing_imports = True
27
-
28
- [mypy-kerberos.*]
29
- ignore_missing_imports = True
30
-
31
- [mypy-xmltodict.*]
32
- ignore_missing_imports = True
33
-
34
- [mypy-md5.*]
35
- ignore_missing_imports = True
36
-
37
- [mypy-imp.*]
38
- ignore_missing_imports = True
39
-
40
- [mypy-scp.*]
41
- ignore_missing_imports = True
42
-
43
- [mypy-ncclient.*]
44
- ignore_missing_imports = True
45
-
46
- [mypy-lxml.*]
47
- ignore_missing_imports = True
48
-
49
- [mypy-rpmUtils.*]
50
- ignore_missing_imports = True
51
-
52
- [mypy-rpm.*]
53
- ignore_missing_imports = True
54
-
55
- [mypy-psutil.*]
56
- ignore_missing_imports = True
57
-
58
- [mypy-dnf.*]
59
- ignore_missing_imports = True
60
-
61
- [mypy-apt.*]
62
- ignore_missing_imports = True
63
-
64
- [mypy-apt_pkg.*]
65
- ignore_missing_imports = True
66
-
67
- [mypy-gssapi.*]
68
- ignore_missing_imports = True
69
-
70
- [mypy-_ssl.*]
71
- ignore_missing_imports = True
72
-
73
- [mypy-urllib_gssapi.*]
74
- ignore_missing_imports = True
75
-
76
- [mypy-systemd.*]
77
- ignore_missing_imports = True
78
-
79
- [mypy-sha.*]
80
- ignore_missing_imports = True
81
-
82
- [mypy-distro.*]
83
- ignore_missing_imports = True
84
-
85
- [mypy-resolvelib.*]
86
- ignore_missing_imports = True
87
-
88
- [mypy-urlparse.*]
89
- ignore_missing_imports = True
90
-
91
- [mypy-argcomplete.*]
92
- ignore_missing_imports = True
93
-
94
- [mypy-selinux.*]
95
- ignore_missing_imports = True
96
-
97
- [mypy-urllib2.*]
98
- ignore_missing_imports = True
99
-
100
- [mypy-httplib.*]
101
- ignore_missing_imports = True
102
-
103
- [mypy-compiler.*]
104
- ignore_missing_imports = True
105
-
106
- [mypy-aptsources.*]
107
- ignore_missing_imports = True
108
-
109
- [mypy-urllib3.*]
110
- ignore_missing_imports = True
111
-
112
- [mypy-requests.*]
113
- ignore_missing_imports = True
114
-
115
- [mypy-jinja2.nativetypes]
116
- ignore_missing_imports = True