Update to 2.16.0~b1.
This commit is contained in:
		
							parent
							
								
									37644b67ea
								
							
						
					
					
						commit
						27968f0c93
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -37,3 +37,5 @@ | |||||||
| /ansible-documentation-2.15.3.tar.gz | /ansible-documentation-2.15.3.tar.gz | ||||||
| /ansible-core-2.15.4.tar.gz | /ansible-core-2.15.4.tar.gz | ||||||
| /ansible-documentation-2.15.4.tar.gz | /ansible-documentation-2.15.4.tar.gz | ||||||
|  | /ansible-core-2.16.0b1.tar.gz | ||||||
|  | /ansible-documentation-2.16.0b1.tar.gz | ||||||
|  | |||||||
| @ -1,26 +0,0 @@ | |||||||
| From 0186f21027682a4c7013ddf75aa35f530fc2a090 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maxwell G <maxwell@gtmx.me> |  | ||||||
| Date: Tue, 13 Jun 2023 13:29:40 +0000 |  | ||||||
| Subject: [PATCH] Disable test that calls compat code removed in 3.12 |  | ||||||
| 
 |  | ||||||
| ---
 |  | ||||||
|  test/units/utils/collection_loader/test_collection_loader.py | 3 ++- |  | ||||||
|  1 file changed, 2 insertions(+), 1 deletion(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/test/units/utils/collection_loader/test_collection_loader.py b/test/units/utils/collection_loader/test_collection_loader.py
 |  | ||||||
| index 9be59307a9..9a27692ea5 100644
 |  | ||||||
| --- a/test/units/utils/collection_loader/test_collection_loader.py
 |  | ||||||
| +++ b/test/units/utils/collection_loader/test_collection_loader.py
 |  | ||||||
| @@ -29,7 +29,8 @@ def teardown(*args, **kwargs):
 |  | ||||||
|  # BEGIN STANDALONE TESTS - these exercise behaviors of the individual components without the import machinery |  | ||||||
|   |  | ||||||
|   |  | ||||||
| -@pytest.mark.skipif(not PY3, reason='Testing Python 2 codepath (find_module) on Python 3')
 |  | ||||||
| +@pytest.mark.skipif(not PY3 or sys.version_info[:2] >= (3, 12),
 |  | ||||||
| +                    reason='Testing Python 2 codepath (find_module) on Python 3')
 |  | ||||||
|  def test_find_module_py3(): |  | ||||||
|      dir_to_a_file = os.path.dirname(ping_module.__file__) |  | ||||||
|      path_hook_finder = _AnsiblePathHookFinder(_AnsibleCollectionFinder(), dir_to_a_file) |  | ||||||
| -- 
 |  | ||||||
| 2.40.1 |  | ||||||
| 
 |  | ||||||
| @ -1,67 +0,0 @@ | |||||||
| From 3e76a568f0b63a0faa336125448ee284549da9da Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maxwell G <maxwell@gtmx.me> |  | ||||||
| Date: Fri, 21 Apr 2023 07:29:10 -0500 |  | ||||||
| Subject: [PATCH] Add GALAXY_COLLECTIONS_PATH_WARNINGS option. (#78487) |  | ||||||
| 
 |  | ||||||
| * Add GALAXY_COLLECTIONS_PATH_WARNING option. |  | ||||||
| 
 |  | ||||||
| This allows users to disable warnings from `ansible-galaxy collection |  | ||||||
| install` about `--collections-path` missing from Ansible's configured |  | ||||||
| collections_paths. |  | ||||||
| 
 |  | ||||||
| (cherry picked from commit 734f38b2594692707d1fd3cbcfc8dc8a677f4ee3) |  | ||||||
| ---
 |  | ||||||
|  .../fragments/78487-galaxy-collections-path-warnings.yml | 6 ++++++ |  | ||||||
|  lib/ansible/cli/galaxy.py                                | 2 +- |  | ||||||
|  lib/ansible/config/base.yml                              | 9 +++++++++ |  | ||||||
|  3 files changed, 16 insertions(+), 1 deletion(-) |  | ||||||
|  create mode 100644 changelogs/fragments/78487-galaxy-collections-path-warnings.yml |  | ||||||
| 
 |  | ||||||
| diff --git a/changelogs/fragments/78487-galaxy-collections-path-warnings.yml b/changelogs/fragments/78487-galaxy-collections-path-warnings.yml
 |  | ||||||
| new file mode 100644 |  | ||||||
| index 0000000000..4702e94f96
 |  | ||||||
| --- /dev/null
 |  | ||||||
| +++ b/changelogs/fragments/78487-galaxy-collections-path-warnings.yml
 |  | ||||||
| @@ -0,0 +1,6 @@
 |  | ||||||
| +---
 |  | ||||||
| +minor_changes:
 |  | ||||||
| +- >-
 |  | ||||||
| +  Add ``GALAXY_COLLECTIONS_PATH_WARNING`` option to disable the warning
 |  | ||||||
| +  given by ``ansible-galaxy collection install`` when installing a collection
 |  | ||||||
| +  to a path that isn't in the configured collection paths.
 |  | ||||||
| diff --git a/lib/ansible/cli/galaxy.py b/lib/ansible/cli/galaxy.py
 |  | ||||||
| index d8a7c03756..3649be56f2 100755
 |  | ||||||
| --- a/lib/ansible/cli/galaxy.py
 |  | ||||||
| +++ b/lib/ansible/cli/galaxy.py
 |  | ||||||
| @@ -1401,7 +1401,7 @@ class GalaxyCLI(CLI):
 |  | ||||||
|          managed_paths = set(validate_collection_path(p) for p in C.COLLECTIONS_PATHS) |  | ||||||
|          read_req_paths = set(validate_collection_path(p) for p in AnsibleCollectionConfig.collection_paths) |  | ||||||
|   |  | ||||||
| -        unexpected_path = not any(p.startswith(path) for p in managed_paths)
 |  | ||||||
| +        unexpected_path = C.GALAXY_COLLECTIONS_PATH_WARNING and not any(p.startswith(path) for p in managed_paths)
 |  | ||||||
|          if unexpected_path and any(p.startswith(path) for p in read_req_paths): |  | ||||||
|              display.warning( |  | ||||||
|                  f"The specified collections path '{path}' appears to be part of the pip Ansible package. " |  | ||||||
| diff --git a/lib/ansible/config/base.yml b/lib/ansible/config/base.yml
 |  | ||||||
| index 052a8f0834..206deb76d2 100644
 |  | ||||||
| --- a/lib/ansible/config/base.yml
 |  | ||||||
| +++ b/lib/ansible/config/base.yml
 |  | ||||||
| @@ -1366,6 +1366,15 @@ GALAXY_COLLECTION_SKELETON_IGNORE:
 |  | ||||||
|    ini: |  | ||||||
|    - {key: collection_skeleton_ignore, section: galaxy} |  | ||||||
|    type: list |  | ||||||
| +GALAXY_COLLECTIONS_PATH_WARNING:
 |  | ||||||
| +  name: "ansible-galaxy collection install colections path warnings"
 |  | ||||||
| +  description: "whether ``ansible-galaxy collection install`` should warn about ``--collections-path`` missing from configured :ref:`collections_paths`"
 |  | ||||||
| +  default: true
 |  | ||||||
| +  type: bool
 |  | ||||||
| +  env: [{name: ANSIBLE_GALAXY_COLLECTIONS_PATH_WARNING}]
 |  | ||||||
| +  ini:
 |  | ||||||
| +    - {key: collections_path_warning, section: galaxy}
 |  | ||||||
| +  version_added: "2.16"
 |  | ||||||
|  # TODO: unused? |  | ||||||
|  #GALAXY_SCMS: |  | ||||||
|  #  name: Galaxy SCMS |  | ||||||
| -- 
 |  | ||||||
| 2.41.0 |  | ||||||
| 
 |  | ||||||
| @ -1,35 +0,0 @@ | |||||||
| diff --color -Nur ansible-2.15.4.orig/lib/ansible/module_utils/facts/system/local.py ansible-2.15.4/lib/ansible/module_utils/facts/system/local.py
 |  | ||||||
| --- ansible-2.15.4.orig/lib/ansible/module_utils/facts/system/local.py	2023-09-11 15:11:17.000000000 -0700
 |  | ||||||
| +++ ansible-2.15.4/lib/ansible/module_utils/facts/system/local.py	2023-09-26 16:31:21.030496975 -0700
 |  | ||||||
| @@ -26,6 +26,7 @@
 |  | ||||||
|  from ansible.module_utils._text import to_text |  | ||||||
|  from ansible.module_utils.facts.utils import get_file_content |  | ||||||
|  from ansible.module_utils.facts.collector import BaseFactCollector |  | ||||||
| +from ansible.module_utils.six import PY3
 |  | ||||||
|  from ansible.module_utils.six.moves import configparser, StringIO |  | ||||||
|   |  | ||||||
|   |  | ||||||
| @@ -91,7 +92,10 @@
 |  | ||||||
|                  # if that fails read it with ConfigParser |  | ||||||
|                  cp = configparser.ConfigParser() |  | ||||||
|                  try: |  | ||||||
| -                    cp.readfp(StringIO(out))
 |  | ||||||
| +                    if PY3:
 |  | ||||||
| +                        cp.read_file(StringIO(out))
 |  | ||||||
| +                    else:
 |  | ||||||
| +                        cp.readfp(StringIO(out))
 |  | ||||||
|                  except configparser.Error: |  | ||||||
|                      fact = "error loading facts as JSON or ini - please check content: %s" % fn |  | ||||||
|                      module.warn(fact) |  | ||||||
| diff --color -Nur ansible-2.15.4.orig/lib/ansible/plugins/lookup/ini.py ansible-2.15.4/lib/ansible/plugins/lookup/ini.py
 |  | ||||||
| --- ansible-2.15.4.orig/lib/ansible/plugins/lookup/ini.py	2023-09-11 15:11:17.000000000 -0700
 |  | ||||||
| +++ ansible-2.15.4/lib/ansible/plugins/lookup/ini.py	2023-09-26 16:31:56.603461044 -0700
 |  | ||||||
| @@ -187,7 +187,7 @@
 |  | ||||||
|              config.seek(0, os.SEEK_SET) |  | ||||||
|   |  | ||||||
|              try: |  | ||||||
| -                self.cp.readfp(config)
 |  | ||||||
| +                self.cp.read_file(config)
 |  | ||||||
|              except configparser.DuplicateOptionError as doe: |  | ||||||
|                  raise AnsibleLookupError("Duplicate option in '{file}': {error}".format(file=paramvals['file'], error=to_native(doe))) |  | ||||||
|   |  | ||||||
| @ -10,9 +10,9 @@ | |||||||
| 
 | 
 | ||||||
| Name: ansible-core | Name: ansible-core | ||||||
| Summary: A radically simple IT automation system | Summary: A radically simple IT automation system | ||||||
| Version: 2.15.4 | Version: 2.16.0~b1 | ||||||
| %global uversion %{version_no_tilde %{quote:%nil}} | %global uversion %{version_no_tilde %{quote:%nil}} | ||||||
| Release: 2%{?dist} | Release: 1%{?dist} | ||||||
| # The main license is GPLv3+. Many of the files in lib/ansible/module_utils | # The main license is GPLv3+. Many of the files in lib/ansible/module_utils | ||||||
| # are BSD licensed. There are various files scattered throughout the codebase | # are BSD licensed. There are various files scattered throughout the codebase | ||||||
| # containing code under different licenses. | # containing code under different licenses. | ||||||
| @ -21,33 +21,6 @@ License: GPL-3.0-or-later AND BSD-2-Clause AND PSF-2.0 AND MIT AND Apache-2.0 | |||||||
| Source0: https://github.com/ansible/ansible/archive/v%{uversion}/%{name}-%{uversion}.tar.gz | Source0: https://github.com/ansible/ansible/archive/v%{uversion}/%{name}-%{uversion}.tar.gz | ||||||
| Source1: https://github.com/ansible/ansible-documentation/archive/v%{uversion}/ansible-documentation-%{uversion}.tar.gz | Source1: https://github.com/ansible/ansible-documentation/archive/v%{uversion}/ansible-documentation-%{uversion}.tar.gz | ||||||
| 
 | 
 | ||||||
| # Add GALAXY_COLLECTIONS_PATH_WARNINGS option. (#78487) |  | ||||||
| # Backport of https://github.com/ansible/ansible/pull/78487. |  | ||||||
| Patch: GALAXY_COLLECTIONS_PATH_WARNINGS.patch |  | ||||||
| 
 |  | ||||||
| # These patches are only applied on Rawhide to enable support for Python 3.12 |  | ||||||
| # See https://bugzilla.redhat.com/2196539 |  | ||||||
| # |  | ||||||
| # Essential # |  | ||||||
| # add Python 3.12 support to ansible-test (#80834) |  | ||||||
| # Slightly modified version of https://github.com/ansible/ansible/pull/80834 |  | ||||||
| Patch5000: support-Python-3.12-in-ansible-test.patch |  | ||||||
| # Fix unit test asserts (#80500) |  | ||||||
| Patch5001: https://github.com/ansible/ansible/commit/3ec828703f020551241b4169f6a3f07c701e240a.patch#/fix-unit-test-asserts.patch |  | ||||||
| # Fix galaxy CLI unit test assertions (#80504) |  | ||||||
| Patch5002: https://github.com/ansible/ansible/commit/43c5cbcaef34aeb0141b8ad24027496bf6ec2acd.patch#/fix-galaxy-cli-unit-test-asserts.patch |  | ||||||
| Patch5003: Disable-test-that-calls-compat-code-removed-in-3.12.patch |  | ||||||
| # Deprecations # |  | ||||||
| # ansible-test - Replace pytest-forked (#80525) |  | ||||||
| Patch6000: https://github.com/ansible/ansible/commit/676b731e6f7d60ce6fd48c0d1c883fc85f5c6537.patch#/ansible-test-replace-pytest-forked.patch |  | ||||||
| # replace deprecated ast.value.s with ast.value.value (#80968) |  | ||||||
| Patch6003: https://github.com/ansible/ansible/commit/742d47fa15a5418f98abf9aaf07edf466e871c81.patch#/replace-deprecated-ast.value.s.patch |  | ||||||
| # Avoid deprecated importlib.abc.TraversableResources (#81082) |  | ||||||
| Patch6004: https://github.com/ansible/ansible/commit/bd5b0b4293f454819766437cb6f8a7037affd49e.patch#/avoid-importlib-resources-abc-deprecation.patch |  | ||||||
| # Fix for readfp with python-3.12. Already upstream (rhbz#2239728) |  | ||||||
| # (rebased on top of above patches) |  | ||||||
| Patch6005: https://github.com/ansible/ansible/commit/a861b1adba5d4a12f61ed268f67a224bdaa5f835.patch |  | ||||||
| 
 |  | ||||||
| Url: https://ansible.com | Url: https://ansible.com | ||||||
| BuildArch: noarch | BuildArch: noarch | ||||||
| 
 | 
 | ||||||
| @ -83,6 +56,7 @@ Obsoletes: ansible-base < 2.10.6-1 | |||||||
| 
 | 
 | ||||||
| BuildRequires: make | BuildRequires: make | ||||||
| BuildRequires: python%{python3_pkgversion}-devel | BuildRequires: python%{python3_pkgversion}-devel | ||||||
|  | BuildRequires: tomcli >= 0.3.0 | ||||||
| # Needed to build manpages from source. | # Needed to build manpages from source. | ||||||
| BuildRequires: python%{python3_pkgversion}-docutils | BuildRequires: python%{python3_pkgversion}-docutils | ||||||
| 
 | 
 | ||||||
| @ -127,13 +101,10 @@ This package installs extensive documentation for ansible-core | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| %prep | %prep | ||||||
| %autosetup -N -n ansible-%{uversion} -a1 | %autosetup -p1 -n ansible-%{uversion} -a1 | ||||||
| %autopatch -M 4999 -p1 | # Relax setuptools constraint | ||||||
| # Python 3.12 specific patches | tomcli-set pyproject.toml lists replace \ | ||||||
| # Set `-D '_has_python312 1'` to test locally |     'build-system.requires' 'setuptools >=.*' 'setuptools' | ||||||
| %if 0%{?_has_python312} || v"0%{?python3_version}" >= v"3.12" |  | ||||||
| %autopatch -m 5000 -p1 |  | ||||||
| %endif |  | ||||||
| 
 | 
 | ||||||
| sed -i -s 's|/usr/bin/env python|%{python3}|' \ | sed -i -s 's|/usr/bin/env python|%{python3}|' \ | ||||||
|     bin/ansible-test \ |     bin/ansible-test \ | ||||||
| @ -288,6 +259,9 @@ install -Dpm 0644 licenses/* -t %{buildroot}%{_pkglicensedir} | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| %changelog | %changelog | ||||||
|  | * Wed Sep 27 2023 Maxwell G <maxwell@gtmx.me> - 2.16.0~b1-1 | ||||||
|  | - Update to 2.16.0~b1. | ||||||
|  | 
 | ||||||
| * Tue Sep 26 2023 Kevin Fenzi <kevin@scrye.com> - 2.15.4-2 | * Tue Sep 26 2023 Kevin Fenzi <kevin@scrye.com> - 2.15.4-2 | ||||||
| - Add patch to fix readfp with python-3.12. Fixes rhbz#2239728 | - Add patch to fix readfp with python-3.12. Fixes rhbz#2239728 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,310 +0,0 @@ | |||||||
| From 676b731e6f7d60ce6fd48c0d1c883fc85f5c6537 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Matt Clay <matt@mystile.com> |  | ||||||
| Date: Fri, 14 Apr 2023 15:13:58 -0700 |  | ||||||
| Subject: [PATCH] ansible-test - Replace pytest-forked (#80525) |  | ||||||
| 
 |  | ||||||
| - Unit tests now report warnings generated during test runs.
 |  | ||||||
| - Python 3.12 warnings about `os.fork` usage with threads (due to `pytest-xdist`) are suppressed.
 |  | ||||||
| - Added integration tests to verify forked test behavior.
 |  | ||||||
| ---
 |  | ||||||
|  .../fragments/ansible-test-pytest-forked.yml  |   5 + |  | ||||||
|  .../ansible-test-units-assertions/runme.sh    |   2 +- |  | ||||||
|  .../targets/ansible-test-units-forked/aliases |   5 + |  | ||||||
|  .../plugins/modules/test_ansible_forked.py    |  43 ++++++++ |  | ||||||
|  .../ansible-test-units-forked/runme.sh        |  45 ++++++++ |  | ||||||
|  .../ansible_test/_data/requirements/units.txt |   1 - |  | ||||||
|  .../_internal/commands/units/__init__.py      |   3 +- |  | ||||||
|  .../pylint/config/ansible-test-target.cfg     |   2 + |  | ||||||
|  .../target/pytest/plugins/ansible_forked.py   | 103 ++++++++++++++++++ |  | ||||||
|  9 files changed, 206 insertions(+), 3 deletions(-) |  | ||||||
|  create mode 100644 changelogs/fragments/ansible-test-pytest-forked.yml |  | ||||||
|  create mode 100644 test/integration/targets/ansible-test-units-forked/aliases |  | ||||||
|  create mode 100644 test/integration/targets/ansible-test-units-forked/ansible_collections/ns/col/tests/unit/plugins/modules/test_ansible_forked.py |  | ||||||
|  create mode 100755 test/integration/targets/ansible-test-units-forked/runme.sh |  | ||||||
|  create mode 100644 test/lib/ansible_test/_util/target/pytest/plugins/ansible_forked.py |  | ||||||
| 
 |  | ||||||
| diff --git a/changelogs/fragments/ansible-test-pytest-forked.yml b/changelogs/fragments/ansible-test-pytest-forked.yml
 |  | ||||||
| new file mode 100644 |  | ||||||
| index 00000000000000..f8fae8139460a3
 |  | ||||||
| --- /dev/null
 |  | ||||||
| +++ b/changelogs/fragments/ansible-test-pytest-forked.yml
 |  | ||||||
| @@ -0,0 +1,5 @@
 |  | ||||||
| +minor_changes:
 |  | ||||||
| +  - ansible-test - Replace the ``pytest-forked`` pytest plugin with a custom plugin.
 |  | ||||||
| +bugfixes:
 |  | ||||||
| +  - ansible-test - Unit tests now report warnings generated during test runs.
 |  | ||||||
| +                   Previously only warnings generated during test collection were reported.
 |  | ||||||
| diff --git a/test/integration/targets/ansible-test-units-assertions/runme.sh b/test/integration/targets/ansible-test-units-assertions/runme.sh
 |  | ||||||
| index 3511e765004a73..86fe5c818112f7 100755
 |  | ||||||
| --- a/test/integration/targets/ansible-test-units-assertions/runme.sh
 |  | ||||||
| +++ b/test/integration/targets/ansible-test-units-assertions/runme.sh
 |  | ||||||
| @@ -8,7 +8,7 @@ options=$("${TEST_DIR}"/../ansible-test/venv-pythons.py --only-versions)
 |  | ||||||
|  IFS=', ' read -r -a pythons <<< "${options}" |  | ||||||
|   |  | ||||||
|  for python in "${pythons[@]}"; do |  | ||||||
| -  if ansible-test units --color --truncate 0 --python "${python}" --requirements "${@}" 2>&1 | tee pytest.log; then
 |  | ||||||
| +  if ansible-test units --truncate 0 --python "${python}" --requirements "${@}" 2>&1 | tee pytest.log; then
 |  | ||||||
|      echo "Test did not fail as expected." |  | ||||||
|      exit 1 |  | ||||||
|    fi |  | ||||||
| diff --git a/test/integration/targets/ansible-test-units-forked/aliases b/test/integration/targets/ansible-test-units-forked/aliases
 |  | ||||||
| new file mode 100644 |  | ||||||
| index 00000000000000..79d7dbd7b09e91
 |  | ||||||
| --- /dev/null
 |  | ||||||
| +++ b/test/integration/targets/ansible-test-units-forked/aliases
 |  | ||||||
| @@ -0,0 +1,5 @@
 |  | ||||||
| +shippable/posix/group3  # runs in the distro test containers
 |  | ||||||
| +shippable/generic/group1  # runs in the default test container
 |  | ||||||
| +context/controller
 |  | ||||||
| +needs/target/collection
 |  | ||||||
| +needs/target/ansible-test
 |  | ||||||
| diff --git a/test/integration/targets/ansible-test-units-forked/ansible_collections/ns/col/tests/unit/plugins/modules/test_ansible_forked.py b/test/integration/targets/ansible-test-units-forked/ansible_collections/ns/col/tests/unit/plugins/modules/test_ansible_forked.py
 |  | ||||||
| new file mode 100644 |  | ||||||
| index 00000000000000..828099c65e4cf3
 |  | ||||||
| --- /dev/null
 |  | ||||||
| +++ b/test/integration/targets/ansible-test-units-forked/ansible_collections/ns/col/tests/unit/plugins/modules/test_ansible_forked.py
 |  | ||||||
| @@ -0,0 +1,43 @@
 |  | ||||||
| +"""Unit tests to verify the functionality of the ansible-forked pytest plugin."""
 |  | ||||||
| +from __future__ import absolute_import, division, print_function
 |  | ||||||
| +
 |  | ||||||
| +__metaclass__ = type
 |  | ||||||
| +
 |  | ||||||
| +import os
 |  | ||||||
| +import pytest
 |  | ||||||
| +import signal
 |  | ||||||
| +import sys
 |  | ||||||
| +import warnings
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +warnings.warn("This verifies that warnings generated during test collection are reported.")
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +@pytest.mark.xfail
 |  | ||||||
| +def test_kill_xfail():
 |  | ||||||
| +    os.kill(os.getpid(), signal.SIGKILL)  # causes pytest to report stdout and stderr
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +def test_kill():
 |  | ||||||
| +    os.kill(os.getpid(), signal.SIGKILL)  # causes pytest to report stdout and stderr
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +@pytest.mark.xfail
 |  | ||||||
| +def test_exception_xfail():
 |  | ||||||
| +    sys.stdout.write("This stdout message should be hidden due to xfail.")
 |  | ||||||
| +    sys.stderr.write("This stderr message should be hidden due to xfail.")
 |  | ||||||
| +    raise Exception("This error is expected, but should be hidden due to xfail.")
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +def test_exception():
 |  | ||||||
| +    sys.stdout.write("This stdout message should be reported since we're throwing an exception.")
 |  | ||||||
| +    sys.stderr.write("This stderr message should be reported since we're throwing an exception.")
 |  | ||||||
| +    raise Exception("This error is expected and should be visible.")
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +def test_warning():
 |  | ||||||
| +    warnings.warn("This verifies that warnings generated at test time are reported.")
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +def test_passed():
 |  | ||||||
| +    pass
 |  | ||||||
| diff --git a/test/integration/targets/ansible-test-units-forked/runme.sh b/test/integration/targets/ansible-test-units-forked/runme.sh
 |  | ||||||
| new file mode 100755 |  | ||||||
| index 00000000000000..c39f3c492440e7
 |  | ||||||
| --- /dev/null
 |  | ||||||
| +++ b/test/integration/targets/ansible-test-units-forked/runme.sh
 |  | ||||||
| @@ -0,0 +1,45 @@
 |  | ||||||
| +#!/usr/bin/env bash
 |  | ||||||
| +
 |  | ||||||
| +source ../collection/setup.sh
 |  | ||||||
| +
 |  | ||||||
| +set -x
 |  | ||||||
| +
 |  | ||||||
| +options=$("${TEST_DIR}"/../ansible-test/venv-pythons.py --only-versions)
 |  | ||||||
| +IFS=', ' read -r -a pythons <<< "${options}"
 |  | ||||||
| +
 |  | ||||||
| +for python in "${pythons[@]}"; do
 |  | ||||||
| +  echo "*** Checking Python ${python} ***"
 |  | ||||||
| +
 |  | ||||||
| +  if ansible-test units --truncate 0 --target-python "venv/${python}" "${@}" > output.log 2>&1 ; then
 |  | ||||||
| +    cat output.log
 |  | ||||||
| +    echo "Unit tests on Python ${python} did not fail as expected. See output above."
 |  | ||||||
| +    exit 1
 |  | ||||||
| +  fi
 |  | ||||||
| +
 |  | ||||||
| +  cat output.log
 |  | ||||||
| +  echo "Unit tests on Python ${python} failed as expected. See output above. Checking for expected output ..."
 |  | ||||||
| +
 |  | ||||||
| +  # Verify that the appropriate tests pased, failed or xfailed.
 |  | ||||||
| +  grep 'PASSED tests/unit/plugins/modules/test_ansible_forked.py::test_passed' output.log
 |  | ||||||
| +  grep 'PASSED tests/unit/plugins/modules/test_ansible_forked.py::test_warning' output.log
 |  | ||||||
| +  grep 'XFAIL tests/unit/plugins/modules/test_ansible_forked.py::test_kill_xfail' output.log
 |  | ||||||
| +  grep 'FAILED tests/unit/plugins/modules/test_ansible_forked.py::test_kill' output.log
 |  | ||||||
| +  grep 'FAILED tests/unit/plugins/modules/test_ansible_forked.py::test_exception' output.log
 |  | ||||||
| +  grep 'XFAIL tests/unit/plugins/modules/test_ansible_forked.py::test_exception_xfail' output.log
 |  | ||||||
| +
 |  | ||||||
| +  # Verify that warnings are properly surfaced.
 |  | ||||||
| +  grep 'UserWarning: This verifies that warnings generated at test time are reported.' output.log
 |  | ||||||
| +  grep 'UserWarning: This verifies that warnings generated during test collection are reported.' output.log
 |  | ||||||
| +
 |  | ||||||
| +  # Verify there are no unexpected warnings.
 |  | ||||||
| +  grep 'Warning' output.log | grep -v 'UserWarning: This verifies that warnings generated ' && exit 1
 |  | ||||||
| +
 |  | ||||||
| +  # Verify that details from failed tests are properly surfaced.
 |  | ||||||
| +  grep "^Test CRASHED with exit code -9.$" output.log
 |  | ||||||
| +  grep "^This stdout message should be reported since we're throwing an exception.$" output.log
 |  | ||||||
| +  grep "^This stderr message should be reported since we're throwing an exception.$" output.log
 |  | ||||||
| +  grep '^> *raise Exception("This error is expected and should be visible.")$' output.log
 |  | ||||||
| +  grep "^E *Exception: This error is expected and should be visible.$" output.log
 |  | ||||||
| +
 |  | ||||||
| +  echo "*** Done Checking Python ${python} ***"
 |  | ||||||
| +done
 |  | ||||||
| diff --git a/test/lib/ansible_test/_data/requirements/units.txt b/test/lib/ansible_test/_data/requirements/units.txt
 |  | ||||||
| index d2f56d35a92a5c..d723a65fc663d0 100644
 |  | ||||||
| --- a/test/lib/ansible_test/_data/requirements/units.txt
 |  | ||||||
| +++ b/test/lib/ansible_test/_data/requirements/units.txt
 |  | ||||||
| @@ -2,5 +2,4 @@ mock
 |  | ||||||
|  pytest |  | ||||||
|  pytest-mock |  | ||||||
|  pytest-xdist |  | ||||||
| -pytest-forked
 |  | ||||||
|  pyyaml  # required by the collection loader (only needed for collections) |  | ||||||
| diff --git a/test/lib/ansible_test/_internal/commands/units/__init__.py b/test/lib/ansible_test/_internal/commands/units/__init__.py
 |  | ||||||
| index 7d192e1be67148..78dd8498156615 100644
 |  | ||||||
| --- a/test/lib/ansible_test/_internal/commands/units/__init__.py
 |  | ||||||
| +++ b/test/lib/ansible_test/_internal/commands/units/__init__.py
 |  | ||||||
| @@ -253,7 +253,6 @@ def command_units(args: UnitsConfig) -> None:
 |  | ||||||
|   |  | ||||||
|          cmd = [ |  | ||||||
|              'pytest', |  | ||||||
| -            '--forked',
 |  | ||||||
|              '-r', 'a', |  | ||||||
|              '-n', str(args.num_workers) if args.num_workers else 'auto', |  | ||||||
|              '--color', 'yes' if args.color else 'no', |  | ||||||
| @@ -275,6 +274,8 @@ def command_units(args: UnitsConfig) -> None:
 |  | ||||||
|          if data_context().content.collection: |  | ||||||
|              plugins.append('ansible_pytest_collections') |  | ||||||
|   |  | ||||||
| +        plugins.append('ansible_forked')
 |  | ||||||
| +
 |  | ||||||
|          if plugins: |  | ||||||
|              env['PYTHONPATH'] += ':%s' % os.path.join(ANSIBLE_TEST_TARGET_ROOT, 'pytest/plugins') |  | ||||||
|              env['PYTEST_PLUGINS'] = ','.join(plugins) |  | ||||||
| diff --git a/test/lib/ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg b/test/lib/ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg
 |  | ||||||
| index e35301dd81c1bd..f8a0a8af3ff21c 100644
 |  | ||||||
| --- a/test/lib/ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg
 |  | ||||||
| +++ b/test/lib/ansible_test/_util/controller/sanity/pylint/config/ansible-test-target.cfg
 |  | ||||||
| @@ -57,3 +57,5 @@ preferred-modules =
 |  | ||||||
|  # Listing them here makes it possible to enable the import-error check. |  | ||||||
|  ignored-modules = |  | ||||||
|      py, |  | ||||||
| +    pytest,
 |  | ||||||
| +    _pytest.runner,
 |  | ||||||
| diff --git a/test/lib/ansible_test/_util/target/pytest/plugins/ansible_forked.py b/test/lib/ansible_test/_util/target/pytest/plugins/ansible_forked.py
 |  | ||||||
| new file mode 100644 |  | ||||||
| index 00000000000000..d00d9e93d1be00
 |  | ||||||
| --- /dev/null
 |  | ||||||
| +++ b/test/lib/ansible_test/_util/target/pytest/plugins/ansible_forked.py
 |  | ||||||
| @@ -0,0 +1,103 @@
 |  | ||||||
| +"""Run each test in its own fork. PYTEST_DONT_REWRITE"""
 |  | ||||||
| +# MIT License (see licenses/MIT-license.txt or https://opensource.org/licenses/MIT)
 |  | ||||||
| +# Based on code originally from:
 |  | ||||||
| +# https://github.com/pytest-dev/pytest-forked
 |  | ||||||
| +# https://github.com/pytest-dev/py
 |  | ||||||
| +# TIP: Disable pytest-xdist when debugging internal errors in this plugin.
 |  | ||||||
| +from __future__ import absolute_import, division, print_function
 |  | ||||||
| +
 |  | ||||||
| +__metaclass__ = type
 |  | ||||||
| +
 |  | ||||||
| +import os
 |  | ||||||
| +import pickle
 |  | ||||||
| +import tempfile
 |  | ||||||
| +import warnings
 |  | ||||||
| +
 |  | ||||||
| +from pytest import Item, hookimpl
 |  | ||||||
| +
 |  | ||||||
| +try:
 |  | ||||||
| +    from pytest import TestReport
 |  | ||||||
| +except ImportError:
 |  | ||||||
| +    from _pytest.runner import TestReport  # Backwards compatibility with pytest < 7. Remove once Python 2.7 is not supported.
 |  | ||||||
| +
 |  | ||||||
| +from _pytest.runner import runtestprotocol
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +@hookimpl(tryfirst=True)
 |  | ||||||
| +def pytest_runtest_protocol(item, nextitem):  # type: (Item, Item | None) -> object | None
 |  | ||||||
| +    """Entry point for enabling this plugin."""
 |  | ||||||
| +    # This is needed because pytest-xdist creates an OS thread (using execnet).
 |  | ||||||
| +    # See: https://github.com/pytest-dev/execnet/blob/d6aa1a56773c2e887515d63e50b1d08338cb78a7/execnet/gateway_base.py#L51
 |  | ||||||
| +    warnings.filterwarnings("ignore", "^This process .* is multi-threaded, use of .* may lead to deadlocks in the child.$", DeprecationWarning)
 |  | ||||||
| +
 |  | ||||||
| +    item_hook = item.ihook
 |  | ||||||
| +    item_hook.pytest_runtest_logstart(nodeid=item.nodeid, location=item.location)
 |  | ||||||
| +
 |  | ||||||
| +    reports = run_item(item, nextitem)
 |  | ||||||
| +
 |  | ||||||
| +    for report in reports:
 |  | ||||||
| +        item_hook.pytest_runtest_logreport(report=report)
 |  | ||||||
| +
 |  | ||||||
| +    item_hook.pytest_runtest_logfinish(nodeid=item.nodeid, location=item.location)
 |  | ||||||
| +
 |  | ||||||
| +    return True
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +def run_item(item, nextitem):  # type: (Item, Item | None) -> list[TestReport]
 |  | ||||||
| +    """Run the item in a child process and return a list of reports."""
 |  | ||||||
| +    with tempfile.NamedTemporaryFile() as temp_file:
 |  | ||||||
| +        pid = os.fork()
 |  | ||||||
| +
 |  | ||||||
| +        if not pid:
 |  | ||||||
| +            temp_file.delete = False
 |  | ||||||
| +            run_child(item, nextitem, temp_file.name)
 |  | ||||||
| +
 |  | ||||||
| +        return run_parent(item, pid, temp_file.name)
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +def run_child(item, nextitem, result_path):  # type: (Item, Item | None, str) -> None
 |  | ||||||
| +    """Run the item, record the result and exit. Called in the child process."""
 |  | ||||||
| +    with warnings.catch_warnings(record=True) as captured_warnings:
 |  | ||||||
| +        reports = runtestprotocol(item, nextitem=nextitem, log=False)
 |  | ||||||
| +
 |  | ||||||
| +    with open(result_path, "wb") as result_file:
 |  | ||||||
| +        pickle.dump((reports, captured_warnings), result_file)
 |  | ||||||
| +
 |  | ||||||
| +    os._exit(0)  # noqa
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +def run_parent(item, pid, result_path):  # type: (Item, int, str) -> list[TestReport]
 |  | ||||||
| +    """Wait for the child process to exit and return the test reports. Called in the parent process."""
 |  | ||||||
| +    exit_code = waitstatus_to_exitcode(os.waitpid(pid, 0)[1])
 |  | ||||||
| +
 |  | ||||||
| +    if exit_code:
 |  | ||||||
| +        reason = "Test CRASHED with exit code {}.".format(exit_code)
 |  | ||||||
| +        report = TestReport(item.nodeid, item.location, {x: 1 for x in item.keywords}, "failed", reason, "call", user_properties=item.user_properties)
 |  | ||||||
| +
 |  | ||||||
| +        if item.get_closest_marker("xfail"):
 |  | ||||||
| +            report.outcome = "skipped"
 |  | ||||||
| +            report.wasxfail = reason
 |  | ||||||
| +
 |  | ||||||
| +        reports = [report]
 |  | ||||||
| +    else:
 |  | ||||||
| +        with open(result_path, "rb") as result_file:
 |  | ||||||
| +            reports, captured_warnings = pickle.load(result_file)  # type: list[TestReport], list[warnings.WarningMessage]
 |  | ||||||
| +
 |  | ||||||
| +        for warning in captured_warnings:
 |  | ||||||
| +            warnings.warn_explicit(warning.message, warning.category, warning.filename, warning.lineno)
 |  | ||||||
| +
 |  | ||||||
| +    return reports
 |  | ||||||
| +
 |  | ||||||
| +
 |  | ||||||
| +def waitstatus_to_exitcode(status):  # type: (int) -> int
 |  | ||||||
| +    """Convert a wait status to an exit code."""
 |  | ||||||
| +    # This function was added in Python 3.9.
 |  | ||||||
| +    # See: https://docs.python.org/3/library/os.html#os.waitstatus_to_exitcode
 |  | ||||||
| +
 |  | ||||||
| +    if os.WIFEXITED(status):
 |  | ||||||
| +        return os.WEXITSTATUS(status)
 |  | ||||||
| +
 |  | ||||||
| +    if os.WIFSIGNALED(status):
 |  | ||||||
| +        return -os.WTERMSIG(status)
 |  | ||||||
| +
 |  | ||||||
| +    raise ValueError(status)
 |  | ||||||
| @ -1,63 +0,0 @@ | |||||||
| From bd5b0b4293f454819766437cb6f8a7037affd49e Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Maxwell G <maxwell@gtmx.me> |  | ||||||
| Date: Tue, 20 Jun 2023 13:54:06 -0500 |  | ||||||
| Subject: [PATCH] Avoid deprecated importlib.abc.TraversableResources (#81082) |  | ||||||
| 
 |  | ||||||
| * Avoid usage of deprecated importlib.abc.TraversableResources |  | ||||||
| 
 |  | ||||||
| This fixes ansible-compat test failures with Python 3.12. |  | ||||||
| 
 |  | ||||||
| * Add deprecated: marker for compat code |  | ||||||
| 
 |  | ||||||
| Co-authored-by: Matt Davis <6775756+nitzmahone@users.noreply.github.com> |  | ||||||
| 
 |  | ||||||
| * add declarative deprecation comment to < 3.9 case |  | ||||||
| 
 |  | ||||||
| Co-authored-by: Matt Clay <matt@mystile.com> |  | ||||||
| 
 |  | ||||||
| ---------
 |  | ||||||
| 
 |  | ||||||
| Co-authored-by: Matt Davis <6775756+nitzmahone@users.noreply.github.com> |  | ||||||
| Co-authored-by: Matt Clay <matt@mystile.com> |  | ||||||
| ---
 |  | ||||||
|  .../fragments/81082-deprecated-importlib-abc.yml    |  5 +++++ |  | ||||||
|  .../utils/collection_loader/_collection_finder.py   | 13 ++++++++++++- |  | ||||||
|  2 files changed, 17 insertions(+), 1 deletion(-) |  | ||||||
|  create mode 100644 changelogs/fragments/81082-deprecated-importlib-abc.yml |  | ||||||
| 
 |  | ||||||
| diff --git a/changelogs/fragments/81082-deprecated-importlib-abc.yml b/changelogs/fragments/81082-deprecated-importlib-abc.yml
 |  | ||||||
| new file mode 100644 |  | ||||||
| index 00000000000000..6dfd90a16bed66
 |  | ||||||
| --- /dev/null
 |  | ||||||
| +++ b/changelogs/fragments/81082-deprecated-importlib-abc.yml
 |  | ||||||
| @@ -0,0 +1,5 @@
 |  | ||||||
| +---
 |  | ||||||
| +minor_changes:
 |  | ||||||
| +  - Use ``importlib.resources.abc.TraversableResources`` instead of deprecated
 |  | ||||||
| +    ``importlib.abc.TraversableResources`` where available
 |  | ||||||
| +    (https:/github.com/ansible/ansible/pull/81082).
 |  | ||||||
| diff --git a/lib/ansible/utils/collection_loader/_collection_finder.py b/lib/ansible/utils/collection_loader/_collection_finder.py
 |  | ||||||
| index fc6744ffdef64e..16d0bcc6e8e92a 100644
 |  | ||||||
| --- a/lib/ansible/utils/collection_loader/_collection_finder.py
 |  | ||||||
| +++ b/lib/ansible/utils/collection_loader/_collection_finder.py
 |  | ||||||
| @@ -40,8 +40,19 @@ def import_module(name):  # type: ignore[misc]
 |  | ||||||
|      reload_module = reload  # type: ignore[name-defined]  # pylint:disable=undefined-variable |  | ||||||
|   |  | ||||||
|  try: |  | ||||||
| -    from importlib.abc import TraversableResources
 |  | ||||||
| +    try:
 |  | ||||||
| +        # Available on Python >= 3.11
 |  | ||||||
| +        # We ignore the import error that will trigger when running mypy with
 |  | ||||||
| +        # older Python versions.
 |  | ||||||
| +        from importlib.resources.abc import TraversableResources  # type: ignore[import]
 |  | ||||||
| +    except ImportError:
 |  | ||||||
| +        # Used with Python 3.9 and 3.10 only
 |  | ||||||
| +        # This member is still available as an alias up until Python 3.14 but
 |  | ||||||
| +        # is deprecated as of Python 3.12.
 |  | ||||||
| +        from importlib.abc import TraversableResources  # deprecated: description='TraversableResources move' python_version='3.10'
 |  | ||||||
|  except ImportError: |  | ||||||
| +    # Python < 3.9
 |  | ||||||
| +    # deprecated: description='TraversableResources fallback' python_version='3.8'
 |  | ||||||
|      TraversableResources = object  # type: ignore[assignment,misc] |  | ||||||
|   |  | ||||||
|  try: |  | ||||||
| @ -1,35 +0,0 @@ | |||||||
| From 43c5cbcaef34aeb0141b8ad24027496bf6ec2acd Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Matt Clay <matt@mystile.com> |  | ||||||
| Date: Wed, 12 Apr 2023 10:32:59 -0700 |  | ||||||
| Subject: [PATCH] Fix galaxy CLI unit test assertions (#80504) |  | ||||||
| 
 |  | ||||||
| ---
 |  | ||||||
|  test/units/cli/test_galaxy.py | 8 ++++++-- |  | ||||||
|  1 file changed, 6 insertions(+), 2 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/test/units/cli/test_galaxy.py b/test/units/cli/test_galaxy.py
 |  | ||||||
| index 8f7e891e7d091f..c21d75dcb9a5f1 100644
 |  | ||||||
| --- a/test/units/cli/test_galaxy.py
 |  | ||||||
| +++ b/test/units/cli/test_galaxy.py
 |  | ||||||
| @@ -168,7 +168,9 @@ def test_exit_without_ignore_without_flag(self):
 |  | ||||||
|          with patch.object(ansible.utils.display.Display, "display", return_value=None) as mocked_display: |  | ||||||
|              # testing that error expected is raised |  | ||||||
|              self.assertRaises(AnsibleError, gc.run) |  | ||||||
| -            self.assertTrue(mocked_display.called_once_with("- downloading role 'fake_role_name', owned by "))
 |  | ||||||
| +            assert mocked_display.call_count == 2
 |  | ||||||
| +            assert mocked_display.mock_calls[0].args[0] == "Starting galaxy role install process"
 |  | ||||||
| +            assert "fake_role_name was NOT installed successfully" in mocked_display.mock_calls[1].args[0]
 |  | ||||||
|   |  | ||||||
|      def test_exit_without_ignore_with_flag(self): |  | ||||||
|          ''' tests that GalaxyCLI exits without the error specified if the --ignore-errors flag is used  ''' |  | ||||||
| @@ -176,7 +178,9 @@ def test_exit_without_ignore_with_flag(self):
 |  | ||||||
|          gc = GalaxyCLI(args=["ansible-galaxy", "install", "--server=None", "fake_role_name", "--ignore-errors"]) |  | ||||||
|          with patch.object(ansible.utils.display.Display, "display", return_value=None) as mocked_display: |  | ||||||
|              gc.run() |  | ||||||
| -            self.assertTrue(mocked_display.called_once_with("- downloading role 'fake_role_name', owned by "))
 |  | ||||||
| +            assert mocked_display.call_count == 2
 |  | ||||||
| +            assert mocked_display.mock_calls[0].args[0] == "Starting galaxy role install process"
 |  | ||||||
| +            assert "fake_role_name was NOT installed successfully" in mocked_display.mock_calls[1].args[0]
 |  | ||||||
|   |  | ||||||
|      def test_parse_no_action(self): |  | ||||||
|          ''' testing the options parser when no action is given ''' |  | ||||||
| @ -1,40 +0,0 @@ | |||||||
| From 3ec828703f020551241b4169f6a3f07c701e240a Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Matt Clay <matt@mystile.com> |  | ||||||
| Date: Wed, 12 Apr 2023 10:04:42 -0700 |  | ||||||
| Subject: [PATCH] Fix unit test asserts (#80500) |  | ||||||
| 
 |  | ||||||
| ---
 |  | ||||||
|  test/units/galaxy/test_collection.py | 6 +++--- |  | ||||||
|  1 file changed, 3 insertions(+), 3 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/test/units/galaxy/test_collection.py b/test/units/galaxy/test_collection.py
 |  | ||||||
| index 04a6a43436bbd1..5d6f32456dda89 100644
 |  | ||||||
| --- a/test/units/galaxy/test_collection.py
 |  | ||||||
| +++ b/test/units/galaxy/test_collection.py
 |  | ||||||
| @@ -1060,7 +1060,7 @@ def test_verify_file_hash_deleted_file(manifest_info):
 |  | ||||||
|          with patch.object(collection.os.path, 'isfile', MagicMock(return_value=False)) as mock_isfile: |  | ||||||
|              collection._verify_file_hash(b'path/', 'file', digest, error_queue) |  | ||||||
|   |  | ||||||
| -            assert mock_isfile.called_once
 |  | ||||||
| +            mock_isfile.assert_called_once()
 |  | ||||||
|   |  | ||||||
|      assert len(error_queue) == 1 |  | ||||||
|      assert error_queue[0].installed is None |  | ||||||
| @@ -1083,7 +1083,7 @@ def test_verify_file_hash_matching_hash(manifest_info):
 |  | ||||||
|          with patch.object(collection.os.path, 'isfile', MagicMock(return_value=True)) as mock_isfile: |  | ||||||
|              collection._verify_file_hash(b'path/', 'file', digest, error_queue) |  | ||||||
|   |  | ||||||
| -            assert mock_isfile.called_once
 |  | ||||||
| +            mock_isfile.assert_called_once()
 |  | ||||||
|   |  | ||||||
|      assert error_queue == [] |  | ||||||
|   |  | ||||||
| @@ -1105,7 +1105,7 @@ def test_verify_file_hash_mismatching_hash(manifest_info):
 |  | ||||||
|          with patch.object(collection.os.path, 'isfile', MagicMock(return_value=True)) as mock_isfile: |  | ||||||
|              collection._verify_file_hash(b'path/', 'file', different_digest, error_queue) |  | ||||||
|   |  | ||||||
| -            assert mock_isfile.called_once
 |  | ||||||
| +            mock_isfile.assert_called_once()
 |  | ||||||
|   |  | ||||||
|      assert len(error_queue) == 1 |  | ||||||
|      assert error_queue[0].installed == digest |  | ||||||
| @ -1,124 +0,0 @@ | |||||||
| From 742d47fa15a5418f98abf9aaf07edf466e871c81 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Sloane Hertel <19572925+s-hertel@users.noreply.github.com> |  | ||||||
| Date: Tue, 6 Jun 2023 11:22:26 -0400 |  | ||||||
| Subject: [PATCH] replace deprecated ast.value.s with ast.value.value (#80968) |  | ||||||
| 
 |  | ||||||
| * replace deprecated ast.value.s with ast.value.value |  | ||||||
| 
 |  | ||||||
| the s attribute is deprecated since Python 3.8 and emits a warning in |  | ||||||
| 3.12 causing some test failures |  | ||||||
| ---
 |  | ||||||
|  .../fragments/80968-replace-deprecated-ast-attr.yml  |  2 ++ |  | ||||||
|  lib/ansible/parsing/plugin_docs.py                   |  4 ++-- |  | ||||||
|  lib/ansible/playbook/conditional.py                  |  6 +++--- |  | ||||||
|  .../sanity/validate-modules/validate_modules/main.py | 12 ++++++------ |  | ||||||
|  .../_util/controller/sanity/yamllint/yamllinter.py   |  6 +++--- |  | ||||||
|  5 files changed, 16 insertions(+), 14 deletions(-) |  | ||||||
|  create mode 100644 changelogs/fragments/80968-replace-deprecated-ast-attr.yml |  | ||||||
| 
 |  | ||||||
| diff --git a/changelogs/fragments/80968-replace-deprecated-ast-attr.yml b/changelogs/fragments/80968-replace-deprecated-ast-attr.yml
 |  | ||||||
| new file mode 100644 |  | ||||||
| index 00000000000000..13100ded3d1987
 |  | ||||||
| --- /dev/null
 |  | ||||||
| +++ b/changelogs/fragments/80968-replace-deprecated-ast-attr.yml
 |  | ||||||
| @@ -0,0 +1,2 @@
 |  | ||||||
| +bugfixes:
 |  | ||||||
| +  - Fix ``ast`` deprecation warnings for ``Str`` and ``value.s`` when using Python 3.12.
 |  | ||||||
| diff --git a/lib/ansible/parsing/plugin_docs.py b/lib/ansible/parsing/plugin_docs.py
 |  | ||||||
| index 7d3dca015cb341..253f62af68e2b1 100644
 |  | ||||||
| --- a/lib/ansible/parsing/plugin_docs.py
 |  | ||||||
| +++ b/lib/ansible/parsing/plugin_docs.py
 |  | ||||||
| @@ -151,10 +151,10 @@ def read_docstring_from_python_file(filename, verbose=True, ignore_errors=True):
 |  | ||||||
|                              if theid == 'EXAMPLES': |  | ||||||
|                                  # examples 'can' be yaml, but even if so, we dont want to parse as such here |  | ||||||
|                                  # as it can create undesired 'objects' that don't display well as docs. |  | ||||||
| -                                data[varkey] = to_text(child.value.s)
 |  | ||||||
| +                                data[varkey] = to_text(child.value.value)
 |  | ||||||
|                              else: |  | ||||||
|                                  # string should be yaml if already not a dict |  | ||||||
| -                                data[varkey] = AnsibleLoader(child.value.s, file_name=filename).get_single_data()
 |  | ||||||
| +                                data[varkey] = AnsibleLoader(child.value.value, file_name=filename).get_single_data()
 |  | ||||||
|   |  | ||||||
|                          display.debug('Documentation assigned: %s' % varkey) |  | ||||||
|   |  | ||||||
| diff --git a/lib/ansible/playbook/conditional.py b/lib/ansible/playbook/conditional.py
 |  | ||||||
| index 6b685ef6a8555d..163f9129c94935 100644
 |  | ||||||
| --- a/lib/ansible/playbook/conditional.py
 |  | ||||||
| +++ b/lib/ansible/playbook/conditional.py
 |  | ||||||
| @@ -144,9 +144,9 @@ def generic_visit(self, node, inside_call=False, inside_yield=False):
 |  | ||||||
|                          inside_call = True |  | ||||||
|                      elif isinstance(node, ast.Yield): |  | ||||||
|                          inside_yield = True |  | ||||||
| -                    elif isinstance(node, ast.Str):
 |  | ||||||
| +                    elif isinstance(node, ast.Constant) and isinstance(node.value, text_type):
 |  | ||||||
|                          if disable_lookups: |  | ||||||
| -                            if inside_call and node.s.startswith("__"):
 |  | ||||||
| +                            if inside_call and node.value.startswith("__"):
 |  | ||||||
|                                  # calling things with a dunder is generally bad at this point... |  | ||||||
|                                  raise AnsibleError( |  | ||||||
|                                      "Invalid access found in the conditional: '%s'" % conditional |  | ||||||
| @@ -154,7 +154,7 @@ def generic_visit(self, node, inside_call=False, inside_yield=False):
 |  | ||||||
|                              elif inside_yield: |  | ||||||
|                                  # we're inside a yield, so recursively parse and traverse the AST |  | ||||||
|                                  # of the result to catch forbidden syntax from executing |  | ||||||
| -                                parsed = ast.parse(node.s, mode='exec')
 |  | ||||||
| +                                parsed = ast.parse(node.value, mode='exec')
 |  | ||||||
|                                  cnv = CleansingNodeVisitor() |  | ||||||
|                                  cnv.visit(parsed) |  | ||||||
|                      # iterate over all child nodes |  | ||||||
| diff --git a/test/lib/ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py b/test/lib/ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py
 |  | ||||||
| index fd5ea3ae788e17..2b92a56c2055dd 100644
 |  | ||||||
| --- a/test/lib/ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py
 |  | ||||||
| +++ b/test/lib/ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py
 |  | ||||||
| @@ -808,22 +808,22 @@ def _get_py_docs(self):
 |  | ||||||
|                          continue |  | ||||||
|   |  | ||||||
|                      if grandchild.id == 'DOCUMENTATION': |  | ||||||
| -                        docs['DOCUMENTATION']['value'] = child.value.s
 |  | ||||||
| +                        docs['DOCUMENTATION']['value'] = child.value.value
 |  | ||||||
|                          docs['DOCUMENTATION']['lineno'] = child.lineno |  | ||||||
|                          docs['DOCUMENTATION']['end_lineno'] = ( |  | ||||||
| -                            child.lineno + len(child.value.s.splitlines())
 |  | ||||||
| +                            child.lineno + len(child.value.value.splitlines())
 |  | ||||||
|                          ) |  | ||||||
|                      elif grandchild.id == 'EXAMPLES': |  | ||||||
| -                        docs['EXAMPLES']['value'] = child.value.s
 |  | ||||||
| +                        docs['EXAMPLES']['value'] = child.value.value
 |  | ||||||
|                          docs['EXAMPLES']['lineno'] = child.lineno |  | ||||||
|                          docs['EXAMPLES']['end_lineno'] = ( |  | ||||||
| -                            child.lineno + len(child.value.s.splitlines())
 |  | ||||||
| +                            child.lineno + len(child.value.value.splitlines())
 |  | ||||||
|                          ) |  | ||||||
|                      elif grandchild.id == 'RETURN': |  | ||||||
| -                        docs['RETURN']['value'] = child.value.s
 |  | ||||||
| +                        docs['RETURN']['value'] = child.value.value
 |  | ||||||
|                          docs['RETURN']['lineno'] = child.lineno |  | ||||||
|                          docs['RETURN']['end_lineno'] = ( |  | ||||||
| -                            child.lineno + len(child.value.s.splitlines())
 |  | ||||||
| +                            child.lineno + len(child.value.value.splitlines())
 |  | ||||||
|                          ) |  | ||||||
|   |  | ||||||
|          return docs |  | ||||||
| diff --git a/test/lib/ansible_test/_util/controller/sanity/yamllint/yamllinter.py b/test/lib/ansible_test/_util/controller/sanity/yamllint/yamllinter.py
 |  | ||||||
| index d6de6117b2328a..ed1afcf3a5efc0 100644
 |  | ||||||
| --- a/test/lib/ansible_test/_util/controller/sanity/yamllint/yamllinter.py
 |  | ||||||
| +++ b/test/lib/ansible_test/_util/controller/sanity/yamllint/yamllinter.py
 |  | ||||||
| @@ -181,15 +181,15 @@ def check_assignment(statement, doc_types=None):
 |  | ||||||
|                  if doc_types and target.id not in doc_types: |  | ||||||
|                      continue |  | ||||||
|   |  | ||||||
| -                fmt_match = fmt_re.match(statement.value.s.lstrip())
 |  | ||||||
| +                fmt_match = fmt_re.match(statement.value.value.lstrip())
 |  | ||||||
|                  fmt = 'yaml' |  | ||||||
|                  if fmt_match: |  | ||||||
|                      fmt = fmt_match.group(1) |  | ||||||
|   |  | ||||||
|                  docs[target.id] = dict( |  | ||||||
| -                    yaml=statement.value.s,
 |  | ||||||
| +                    yaml=statement.value.value,
 |  | ||||||
|                      lineno=statement.lineno, |  | ||||||
| -                    end_lineno=statement.lineno + len(statement.value.s.splitlines()),
 |  | ||||||
| +                    end_lineno=statement.lineno + len(statement.value.value.splitlines()),
 |  | ||||||
|                      fmt=fmt.lower(), |  | ||||||
|                  ) |  | ||||||
|   |  | ||||||
							
								
								
									
										4
									
								
								sources
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								sources
									
									
									
									
									
								
							| @ -1,2 +1,2 @@ | |||||||
| SHA512 (ansible-core-2.15.4.tar.gz) = e21e2cd84d7bb0268530a9ca8aca8e0a319f59aa57d59a6126234407b379cfa0de4d83ac7d3e87fdc769f5edad4cb283f8fdcc53bc57c8103e1b743549ef3913 | SHA512 (ansible-core-2.16.0b1.tar.gz) = cde4d27b5e22ba61588341d455f18ff10ec95a10b2cd78bc66b7538eafafb60d88f138110f2fc87e9662dbfa1743f3f3ed94d0a933a223ea16a6cdc9c69bc227 | ||||||
| SHA512 (ansible-documentation-2.15.4.tar.gz) = 44339d6ab31122a06e1cc105058fadb85558ea856af4ff082fbe684c2b2a894af2f2b9faf4ec8490caf7a5b7bd61e069644e238277b73db5342f6665b04adfbd | SHA512 (ansible-documentation-2.16.0b1.tar.gz) = c7e72a2eee03c7a4529c8677a3e3b43d80bd154a5dfdfe2ae0d6706a4947056d568bac5f145b79efe0fe0ab9d3a950258645f1bf4c164a40bae16a895f1a17bf | ||||||
|  | |||||||
| @ -1,120 +0,0 @@ | |||||||
| From c10e3d21fcb54dd0a9dfe44d97355195166510a9 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: s-hertel <19572925+s-hertel@users.noreply.github.com> |  | ||||||
| Date: Tue, 16 May 2023 13:48:12 -0400 |  | ||||||
| Subject: [PATCH] add Python 3.12 support to ansible-test |  | ||||||
| 
 |  | ||||||
| skip Python 3.12 tests on windows/networking until the default container is |  | ||||||
| updated |  | ||||||
| 
 |  | ||||||
| add interpreter fallback? |  | ||||||
| ---
 |  | ||||||
|  lib/ansible/config/base.yml                                   | 1 + |  | ||||||
|  setup.cfg                                                     | 1 + |  | ||||||
|  test/lib/ansible_test/_data/requirements/ansible-test.txt     | 2 +- |  | ||||||
|  test/lib/ansible_test/_internal/bootstrap.py                  | 4 ++++ |  | ||||||
|  test/lib/ansible_test/_internal/coverage_util.py              | 2 +- |  | ||||||
|  test/lib/ansible_test/_internal/python_requirements.py        | 4 ++-- |  | ||||||
|  test/lib/ansible_test/_util/target/common/constants.py        | 1 + |  | ||||||
|  test/lib/ansible_test/_util/target/setup/bootstrap.sh         | 2 +- |  | ||||||
|  10 files changed, 16 insertions(+), 6 deletions(-) |  | ||||||
| 
 |  | ||||||
| diff --git a/lib/ansible/config/base.yml b/lib/ansible/config/base.yml
 |  | ||||||
| index 206deb76d2e916..469fbc6846b6d9 100644
 |  | ||||||
| --- a/lib/ansible/config/base.yml
 |  | ||||||
| +++ b/lib/ansible/config/base.yml
 |  | ||||||
| @@ -1557,6 +1557,7 @@ _INTERPRETER_PYTHON_DISTRO_MAP:
 |  | ||||||
|  INTERPRETER_PYTHON_FALLBACK: |  | ||||||
|    name: Ordered list of Python interpreters to check for in discovery |  | ||||||
|    default: |  | ||||||
| +  - python3.12
 |  | ||||||
|    - python3.11 |  | ||||||
|    - python3.10 |  | ||||||
|    - python3.9 |  | ||||||
| diff --git a/setup.cfg b/setup.cfg
 |  | ||||||
| index e020ee3b15caea..af79337f91e9de 100644
 |  | ||||||
| --- a/setup.cfg
 |  | ||||||
| +++ b/setup.cfg
 |  | ||||||
| @@ -30,6 +30,7 @@ classifiers =
 |  | ||||||
|      Programming Language :: Python :: 3.9 |  | ||||||
|      Programming Language :: Python :: 3.10 |  | ||||||
|      Programming Language :: Python :: 3.11 |  | ||||||
| +    Programming Language :: Python :: 3.12
 |  | ||||||
|      Programming Language :: Python :: 3 :: Only |  | ||||||
|      Topic :: System :: Installation/Setup |  | ||||||
|      Topic :: System :: Systems Administration |  | ||||||
| diff --git a/test/lib/ansible_test/_data/requirements/ansible-test.txt b/test/lib/ansible_test/_data/requirements/ansible-test.txt
 |  | ||||||
| index f7cb9c27780856..8b1772fb915bc3 100644
 |  | ||||||
| --- a/test/lib/ansible_test/_data/requirements/ansible-test.txt
 |  | ||||||
| +++ b/test/lib/ansible_test/_data/requirements/ansible-test.txt
 |  | ||||||
| @@ -1,4 +1,4 @@
 |  | ||||||
|  # The test-constraints sanity test verifies this file, but changes must be made manually to keep it in up-to-date. |  | ||||||
|  virtualenv == 16.7.12 ; python_version < '3' |  | ||||||
| -coverage == 6.5.0 ; python_version >= '3.7' and python_version <= '3.11'
 |  | ||||||
| +coverage == 6.5.0 ; python_version >= '3.7' and python_version <= '3.12'
 |  | ||||||
|  coverage == 4.5.4 ; python_version >= '2.6' and python_version <= '3.6' |  | ||||||
| diff --git a/test/lib/ansible_test/_internal/bootstrap.py b/test/lib/ansible_test/_internal/bootstrap.py
 |  | ||||||
| index b0cfb601d94497..1bd357679bb72c 100644
 |  | ||||||
| --- a/test/lib/ansible_test/_internal/bootstrap.py
 |  | ||||||
| +++ b/test/lib/ansible_test/_internal/bootstrap.py
 |  | ||||||
| @@ -90,6 +90,10 @@ def get_variables(self) -> dict[str, t.Union[str, list[str]]]:
 |  | ||||||
|          """The variables to template in the bootstrapping script.""" |  | ||||||
|          variables = super().get_variables() |  | ||||||
|   |  | ||||||
| +        # remove once the default docker container is updated
 |  | ||||||
| +        if self.platform in ('ios', 'vyos', 'windows'):
 |  | ||||||
| +            variables['python_versions'] = [version for version in self.python_versions if version != '3.12']
 |  | ||||||
| +
 |  | ||||||
|          variables.update( |  | ||||||
|              platform=self.platform, |  | ||||||
|              platform_version=self.platform_version, |  | ||||||
| diff --git a/test/lib/ansible_test/_internal/coverage_util.py b/test/lib/ansible_test/_internal/coverage_util.py
 |  | ||||||
| index 0af1cac4e97c63..f9276d323c50fc 100644
 |  | ||||||
| --- a/test/lib/ansible_test/_internal/coverage_util.py
 |  | ||||||
| +++ b/test/lib/ansible_test/_internal/coverage_util.py
 |  | ||||||
| @@ -69,7 +69,7 @@ class CoverageVersion:
 |  | ||||||
|   |  | ||||||
|  COVERAGE_VERSIONS = ( |  | ||||||
|      # IMPORTANT: Keep this in sync with the ansible-test.txt requirements file. |  | ||||||
| -    CoverageVersion('6.5.0', 7, (3, 7), (3, 11)),
 |  | ||||||
| +    CoverageVersion('6.5.0', 7, (3, 7), (3, 12)),
 |  | ||||||
|      CoverageVersion('4.5.4', 0, (2, 6), (3, 6)), |  | ||||||
|  ) |  | ||||||
|  """ |  | ||||||
| diff --git a/test/lib/ansible_test/_internal/python_requirements.py b/test/lib/ansible_test/_internal/python_requirements.py
 |  | ||||||
| index fc88b637c2b242..1a07334d8637c5 100644
 |  | ||||||
| --- a/test/lib/ansible_test/_internal/python_requirements.py
 |  | ||||||
| +++ b/test/lib/ansible_test/_internal/python_requirements.py
 |  | ||||||
| @@ -434,8 +434,8 @@ def get_venv_packages(python: PythonConfig) -> dict[str, str]:
 |  | ||||||
|      #       See: https://github.com/ansible/base-test-container/blob/main/files/installer.py |  | ||||||
|   |  | ||||||
|      default_packages = dict( |  | ||||||
| -        pip='21.3.1',
 |  | ||||||
| -        setuptools='60.8.2',
 |  | ||||||
| +        pip='23.1.2',
 |  | ||||||
| +        setuptools='67.7.2',
 |  | ||||||
|          wheel='0.37.1', |  | ||||||
|      ) |  | ||||||
|   |  | ||||||
| diff --git a/test/lib/ansible_test/_util/target/common/constants.py b/test/lib/ansible_test/_util/target/common/constants.py
 |  | ||||||
| index 9bddfaf439563e..f3c3857ef97dbf 100644
 |  | ||||||
| --- a/test/lib/ansible_test/_util/target/common/constants.py
 |  | ||||||
| +++ b/test/lib/ansible_test/_util/target/common/constants.py
 |  | ||||||
| @@ -17,4 +17,5 @@
 |  | ||||||
|      '3.9', |  | ||||||
|      '3.10', |  | ||||||
|      '3.11', |  | ||||||
| +    '3.12',
 |  | ||||||
|  ) |  | ||||||
| diff --git a/test/lib/ansible_test/_util/target/setup/bootstrap.sh b/test/lib/ansible_test/_util/target/setup/bootstrap.sh
 |  | ||||||
| index ea17dad38751cc..367dcfcb4ce17e 100644
 |  | ||||||
| --- a/test/lib/ansible_test/_util/target/setup/bootstrap.sh
 |  | ||||||
| +++ b/test/lib/ansible_test/_util/target/setup/bootstrap.sh
 |  | ||||||
| @@ -53,7 +53,7 @@ install_pip() {
 |  | ||||||
|                  pip_bootstrap_url="https://ci-files.testing.ansible.com/ansible-test/get-pip-20.3.4.py" |  | ||||||
|                  ;; |  | ||||||
|              *) |  | ||||||
| -                pip_bootstrap_url="https://ci-files.testing.ansible.com/ansible-test/get-pip-21.3.1.py"
 |  | ||||||
| +                pip_bootstrap_url="https://ci-files.testing.ansible.com/ansible-test/get-pip-23.1.2.py"
 |  | ||||||
|                  ;; |  | ||||||
|          esac |  | ||||||
|   |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user