From bdc0159104dec3b47ea4ea562d88348598ad0b88 Mon Sep 17 00:00:00 2001 From: David Shrewsbury Date: Mon, 1 Jul 2024 15:11:55 -0400 Subject: [PATCH 1/4] Add Python 3.13 testing --- .github/workflows/ci.yml | 6 ++++++ src/ansible_runner/utils/base64io.py | 6 ++++-- test/requirements.txt | 2 ++ tox.ini | 20 ++++++++------------ 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8729f14e..e43ec1e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,6 +65,9 @@ jobs: - name: '3.12' tox_env: integration-py312 + - name: '3.13.0-alpha - 3.13.0' + tox_env: integration-py313 + steps: - name: Checkout uses: actions/checkout@v4 @@ -122,6 +125,9 @@ jobs: - name: '3.12' tox_env: unit-py312 + - name: '3.13.0-alpha - 3.13.0' + tox_env: unit-py313 + steps: - name: Checkout uses: actions/checkout@v4 diff --git a/src/ansible_runner/utils/base64io.py b/src/ansible_runner/utils/base64io.py index 0a2422f1..6a65b5ab 100644 --- a/src/ansible_runner/utils/base64io.py +++ b/src/ansible_runner/utils/base64io.py @@ -78,6 +78,10 @@ def __init__(self, wrapped: IO) -> None: :raises TypeError: if ``wrapped`` does not have attributes needed to determine the stream's state """ + # set before the attr check as we may reach close() after that check fails + self.__read_buffer = b"" + self.__write_buffer = b"" + required_attrs = ("read", "write", "close", "closed", "flush") if not all(hasattr(wrapped, attr) for attr in required_attrs): raise TypeError( @@ -85,8 +89,6 @@ def __init__(self, wrapped: IO) -> None: ) super().__init__() self.__wrapped = wrapped - self.__read_buffer = b"" - self.__write_buffer = b"" def __enter__(self): """Return self on enter.""" diff --git a/test/requirements.txt b/test/requirements.txt index 565292c1..51c95c5d 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -8,4 +8,6 @@ pytest-xdist==2.5.0 types-pyyaml flake8==6.1.0 yamllint==1.32.0 +# cffi pre-release to make cryptography work with python 3.13 (remove when 3.13 is released) +cffi==1.17.0rc1 cryptography diff --git a/tox.ini b/tox.ini index ef540923..df270257 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = linters, ansible{27, 28, 29, -base} +envlist = linters requires = tox>4 setuptools>=64 @@ -9,21 +9,17 @@ pytest_cov_args = --cov --cov-report html --cov-report term --cov-report xml [testenv] description = Run tests with {basepython} -deps = ansible27: ansible<2.8 - ansible28: ansible<2.9 - ansible29: ansible<2.10 - ansible-base: ansible-base - py{,3,39,310,311}: ansible-core - integration{,-py39,-py310,-py311,-py312}: ansible-core - build - -r {toxinidir}/test/requirements.txt +deps = + ansible-core + integration{,-py39,-py310,-py311,-py312}: build + -r {toxinidir}/test/requirements.txt passenv = HOME RUNNER_TEST_IMAGE_NAME usedevelop = True commands = pytest -vv -n auto {posargs} -[testenv:linters{,-py39,-py310,-py311,-py312}] +[testenv:linters{,-py39,-py310,-py311,-py312,-py313}] description = Run code linters commands = flake8 --version @@ -33,11 +29,11 @@ commands = mypy src/ansible_runner pylint src/ansible_runner test -[testenv:unit{,-py39,-py310,-py311,-py312}] +[testenv:unit{,-py39,-py310,-py311,-py312,-py313}] description = Run unit tests commands = pytest -vv -n auto {posargs:test/unit} {[shared]pytest_cov_args} -[testenv:integration{,-py39,-py310,-py311,-py312}] +[testenv:integration{,-py39,-py310,-py311,-py312,-py313}] description = Run integration tests commands = pytest -vv -n auto {posargs:test/integration} {[shared]pytest_cov_args} From 43f82710b76af430b7ad6b6fdaeb49d99dea6361 Mon Sep 17 00:00:00 2001 From: David Shrewsbury Date: Thu, 11 Jul 2024 12:06:35 -0400 Subject: [PATCH 2/4] Add test serialization --- pytest.ini | 1 + test/conftest.py | 12 ++++++++++++ test/integration/test_transmit_worker_process.py | 4 ++++ tox.ini | 4 +++- 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/pytest.ini b/pytest.ini index f5094836..89e70cf9 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,6 +1,7 @@ [pytest] markers = test_all_runtimes: Generate a test for each supported container runtime + serial: Tests that need to run serially testpaths = test addopts = -r a diff --git a/test/conftest.py b/test/conftest.py index 6d22a36e..a3941eb5 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -102,3 +102,15 @@ def project_fixtures(tmp_path): yield dest shutil.rmtree(dest, ignore_errors=True) + + +def pytest_collection_modifyitems(session, config, items): + # pylint: disable=W0613 + # mark serial items as skipped if it looks like we're running with some obvious kinds of parallelism + numproc = getattr(config.known_args_namespace, 'numprocesses', None) + + if isinstance(numproc, int) and numproc > 1: + for serial_item in (i for i in items if any(i.iter_markers(name='serial'))): + serial_item.add_marker( + pytest.mark.skip(reason='test requires serial execution (add --numprocesses 0 to allow)') + ) diff --git a/test/integration/test_transmit_worker_process.py b/test/integration/test_transmit_worker_process.py index 540e5dc6..f136fe93 100644 --- a/test/integration/test_transmit_worker_process.py +++ b/test/integration/test_transmit_worker_process.py @@ -109,6 +109,10 @@ def test_remote_job_interface(self, tmp_path, project_fixtures, job_type): incoming_buffer.close() self.check_artifacts(str(process_dir), job_type) + # The keepalive tests will run serially since Python 3.13 somehow causes a longer delay + # in the tests, thus causing the keepalive timeout count to exceed the hardcoded value + # of 5. + @pytest.mark.serial @pytest.mark.parametrize("keepalive_setting", [ 0, # keepalive explicitly disabled, default 1, # emit keepalives every 1s diff --git a/tox.ini b/tox.ini index df270257..031b9708 100644 --- a/tox.ini +++ b/tox.ini @@ -35,7 +35,9 @@ commands = pytest -vv -n auto {posargs:test/unit} {[shared]pytest_cov_args} [testenv:integration{,-py39,-py310,-py311,-py312,-py313}] description = Run integration tests -commands = pytest -vv -n auto {posargs:test/integration} {[shared]pytest_cov_args} +commands = + pytest -vv -n auto -m "not serial" {posargs:test/integration} {[shared]pytest_cov_args} + pytest -n 0 -m "serial" {posargs:test/integration} {[shared]pytest_cov_args} [testenv:docs] description = Build documentation From e911f7858fa03a0e1527aa41d09b4f2fa6cd133d Mon Sep 17 00:00:00 2001 From: David Shrewsbury Date: Fri, 12 Jul 2024 14:49:20 -0400 Subject: [PATCH 3/4] Revert serial support and increase keepalive wobble --- pytest.ini | 1 - test/conftest.py | 12 ------------ .../integration/test_transmit_worker_process.py | 6 +----- tox.ini | 17 ++++++++++------- 4 files changed, 11 insertions(+), 25 deletions(-) diff --git a/pytest.ini b/pytest.ini index 89e70cf9..f5094836 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,7 +1,6 @@ [pytest] markers = test_all_runtimes: Generate a test for each supported container runtime - serial: Tests that need to run serially testpaths = test addopts = -r a diff --git a/test/conftest.py b/test/conftest.py index a3941eb5..6d22a36e 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -102,15 +102,3 @@ def project_fixtures(tmp_path): yield dest shutil.rmtree(dest, ignore_errors=True) - - -def pytest_collection_modifyitems(session, config, items): - # pylint: disable=W0613 - # mark serial items as skipped if it looks like we're running with some obvious kinds of parallelism - numproc = getattr(config.known_args_namespace, 'numprocesses', None) - - if isinstance(numproc, int) and numproc > 1: - for serial_item in (i for i in items if any(i.iter_markers(name='serial'))): - serial_item.add_marker( - pytest.mark.skip(reason='test requires serial execution (add --numprocesses 0 to allow)') - ) diff --git a/test/integration/test_transmit_worker_process.py b/test/integration/test_transmit_worker_process.py index f136fe93..cc70a6ac 100644 --- a/test/integration/test_transmit_worker_process.py +++ b/test/integration/test_transmit_worker_process.py @@ -109,10 +109,6 @@ def test_remote_job_interface(self, tmp_path, project_fixtures, job_type): incoming_buffer.close() self.check_artifacts(str(process_dir), job_type) - # The keepalive tests will run serially since Python 3.13 somehow causes a longer delay - # in the tests, thus causing the keepalive timeout count to exceed the hardcoded value - # of 5. - @pytest.mark.serial @pytest.mark.parametrize("keepalive_setting", [ 0, # keepalive explicitly disabled, default 1, # emit keepalives every 1s @@ -197,7 +193,7 @@ def test_keepalive_setting(self, tmp_path, project_fixtures, keepalive_setting): pytest.fail(f'unparseable JSON in output (likely corrupted by keepalive): {line}') else: # account for some wobble in the number of keepalives for artifact gather, etc - assert 1 <= incoming_data.count('"event": "keepalive"') < 5 + assert 1 <= incoming_data.count('"event": "keepalive"') < 15 @pytest.mark.parametrize("job_type", ['run', 'adhoc']) def test_remote_job_by_sockets(self, tmp_path, project_fixtures, job_type): diff --git a/tox.ini b/tox.ini index 031b9708..fcd81cbb 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = linters +envlist = linters, ansible{27, 28, 29, -base} requires = tox>4 setuptools>=64 @@ -9,10 +9,14 @@ pytest_cov_args = --cov --cov-report html --cov-report term --cov-report xml [testenv] description = Run tests with {basepython} -deps = - ansible-core - integration{,-py39,-py310,-py311,-py312}: build - -r {toxinidir}/test/requirements.txt +deps = ansible27: ansible<2.8 + ansible28: ansible<2.9 + ansible29: ansible<2.10 + ansible-base: ansible-base + py{,3,39,310,311,312,313}: ansible-core + integration{,-py39,-py310,-py311,-py312,-py313}: ansible-core + build + -r {toxinidir}/test/requirements.txt passenv = HOME RUNNER_TEST_IMAGE_NAME @@ -36,8 +40,7 @@ commands = pytest -vv -n auto {posargs:test/unit} {[shared]pytest_cov_args} [testenv:integration{,-py39,-py310,-py311,-py312,-py313}] description = Run integration tests commands = - pytest -vv -n auto -m "not serial" {posargs:test/integration} {[shared]pytest_cov_args} - pytest -n 0 -m "serial" {posargs:test/integration} {[shared]pytest_cov_args} + pytest -vv -n auto {posargs:test/integration} {[shared]pytest_cov_args} [testenv:docs] description = Build documentation From 546fbe4fe0c1437b2c76ee4c84a78b09028aa3c6 Mon Sep 17 00:00:00 2001 From: David Shrewsbury Date: Tue, 23 Jul 2024 14:47:37 -0400 Subject: [PATCH 4/4] use allow-prereleases instead in GHA --- .github/workflows/ci.yml | 6 ++++-- test/requirements.txt | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e43ec1e6..1c9fb821 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,7 @@ jobs: - name: '3.12' tox_env: integration-py312 - - name: '3.13.0-alpha - 3.13.0' + - name: '3.13' tox_env: integration-py313 steps: @@ -76,6 +76,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.py_version.name }} + allow-prereleases: true - name: Install tox run: | @@ -125,7 +126,7 @@ jobs: - name: '3.12' tox_env: unit-py312 - - name: '3.13.0-alpha - 3.13.0' + - name: '3.13' tox_env: unit-py313 steps: @@ -136,6 +137,7 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.py_version.name }} + allow-prereleases: true - name: Install tox run: | diff --git a/test/requirements.txt b/test/requirements.txt index 51c95c5d..7ab8f9fc 100644 --- a/test/requirements.txt +++ b/test/requirements.txt @@ -9,5 +9,5 @@ types-pyyaml flake8==6.1.0 yamllint==1.32.0 # cffi pre-release to make cryptography work with python 3.13 (remove when 3.13 is released) -cffi==1.17.0rc1 +cffi==1.17.0rc1; python_version == "3.13" cryptography