From 0a34d525ef7a7b12f0f092088a3e337e098cbb6b Mon Sep 17 00:00:00 2001 From: Jonathan GAYVALLET Date: Wed, 30 Oct 2024 14:25:18 +0100 Subject: [PATCH 1/3] Fix tests and mypy dependencies Signed-off-by: Jonathan GAYVALLET --- pytest.ini | 1 + requirements.txt | 2 +- tests/peering/test_keepalive.py | 6 +++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pytest.ini b/pytest.ini index afd6b82b..e961ed79 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,4 +1,5 @@ [pytest] asyncio_mode = auto +asyncio_default_fixture_loop_scope = function addopts = --strict-markers diff --git a/requirements.txt b/requirements.txt index 7db4ec87..a9b0b6ad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -21,5 +21,5 @@ pytest-asyncio pytest-cov pytest-mock pytest-timeout -types-pkg_resources +types-setuptools types-PyYAML diff --git a/tests/peering/test_keepalive.py b/tests/peering/test_keepalive.py index 8b8eee32..12545401 100644 --- a/tests/peering/test_keepalive.py +++ b/tests/peering/test_keepalive.py @@ -1,6 +1,8 @@ import pytest from kopf._core.engines.peering import keepalive +from itertools import chain, repeat +from unittest import mock class StopInfiniteCycleException(Exception): @@ -11,7 +13,9 @@ async def test_background_task_runs(mocker, settings, namespaced_peering_resourc touch_mock = mocker.patch('kopf._core.engines.peering.touch') sleep_mock = mocker.patch('asyncio.sleep') - sleep_mock.side_effect = [None, None, StopInfiniteCycleException] + # restore the default behavior after exhausting test values. + # pytest-aiohttp calls asyncio.sleep during teardown, before the mock is removed. + sleep_mock.side_effect = chain([None, None, StopInfiniteCycleException], repeat(mock.DEFAULT)) randint_mock = mocker.patch('random.randint') randint_mock.side_effect = [7, 5, 9] From f506593e8972c467166bc469062d2d1021ac5830 Mon Sep 17 00:00:00 2001 From: Jonathan GAYVALLET Date: Wed, 30 Oct 2024 11:14:32 +0100 Subject: [PATCH 2/3] add python 3.13 support the logging.Handler class changed in 3.13 and will now always try to acquire the lock in its `handle` method. Removed the optimization that created the handler without a lock when running python >= 3.13. Also configure the CI to run on Python 3.13. Signed-off-by: Jonathan GAYVALLET --- .github/workflows/ci.yaml | 6 +++--- kopf/_core/engines/posting.py | 12 +++++++----- requirements.txt | 2 +- setup.py | 1 + 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0d5a5309..0e096030 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -18,7 +18,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: "3.12" + python-version: "3.13" - run: pip install -r requirements.txt - run: pre-commit run --all-files - run: mypy kopf --strict @@ -38,10 +38,10 @@ jobs: fail-fast: false matrix: install-extras: [ "", "full-auth" ] - python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ] + python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12", "3.13" ] include: - install-extras: "uvloop" - python-version: "3.12" + python-version: "3.13" name: Python ${{ matrix.python-version }} ${{ matrix.install-extras }} runs-on: ubuntu-22.04 timeout-minutes: 5 # usually 2-3 mins diff --git a/kopf/_core/engines/posting.py b/kopf/_core/engines/posting.py index 3c83954d..1aaa4443 100644 --- a/kopf/_core/engines/posting.py +++ b/kopf/_core/engines/posting.py @@ -183,11 +183,13 @@ class K8sPoster(logging.Handler): """ A handler to post all log messages as K8s events. """ - - def createLock(self) -> None: - # Save some time on unneeded locks. Events are posted in the background. - # We only put events to the queue, which is already lock-protected. - self.lock = None + if sys.version_info[:2] < (3, 13): + # Disable this optimisation for Python >= 3.13. + # The `handle` no longer support having `None` as lock. + def createLock(self) -> None: + # Save some time on unneeded locks. Events are posted in the background. + # We only put events to the queue, which is already lock-protected. + self.lock = None def filter(self, record: logging.LogRecord) -> bool: # Only those which have a k8s object referred (see: `ObjectLogger`). diff --git a/requirements.txt b/requirements.txt index a9b0b6ad..88ee4ebe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -21,5 +21,5 @@ pytest-asyncio pytest-cov pytest-mock pytest-timeout -types-setuptools types-PyYAML +types-setuptools diff --git a/setup.py b/setup.py index 4beebb1c..822892a6 100644 --- a/setup.py +++ b/setup.py @@ -38,6 +38,7 @@ 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', From 1b9f760fcdea5c6dd3e4da1c5e93e1691871d7ce Mon Sep 17 00:00:00 2001 From: Sergey Vasilyev Date: Mon, 18 Nov 2024 20:24:42 +0100 Subject: [PATCH 3/3] Align test_keepalive.py with pre-commit rules --- tests/peering/test_keepalive.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/peering/test_keepalive.py b/tests/peering/test_keepalive.py index 12545401..e6b01a6f 100644 --- a/tests/peering/test_keepalive.py +++ b/tests/peering/test_keepalive.py @@ -1,8 +1,9 @@ +from itertools import chain, repeat +from unittest import mock + import pytest from kopf._core.engines.peering import keepalive -from itertools import chain, repeat -from unittest import mock class StopInfiniteCycleException(Exception):