Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to Python 3.11 in CI #968

Merged
merged 2 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.10"
python-version: "3.11"
- run: pip install -r requirements.txt
- run: pre-commit run --all-files
- run: mypy kopf --strict
Expand All @@ -38,7 +38,7 @@ jobs:
fail-fast: false
matrix:
install-extras: [ "", "full-auth" ]
python-version: [ "3.7", "3.8", "3.9", "3.10" ]
python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11" ]
name: Python ${{ matrix.python-version }} ${{ matrix.install-extras }}
runs-on: ubuntu-22.04
timeout-minutes: 5 # usually 2-3 mins
Expand Down Expand Up @@ -108,7 +108,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.10"
python-version: "3.11"
- uses: nolar/setup-k3d-k3s@v1
with:
version: ${{ matrix.k3s }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.10"
python-version: "3.11"
- run: pip install --upgrade setuptools wheel twine
- run: python setup.py sdist bdist_wheel
- uses: pypa/gh-action-pypi-publish@release/v1
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/thorough.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.10"
python-version: "3.11"
- run: pip install -r requirements.txt
- run: pre-commit run --all-files
- run: mypy kopf --strict
Expand All @@ -42,7 +42,7 @@ jobs:
fail-fast: false
matrix:
install-extras: [ "", "full-auth" ]
python-version: [ "3.7", "3.8", "3.9", "3.10" ]
python-version: [ "3.7", "3.8", "3.9", "3.10", "3.11" ]
name: Python ${{ matrix.python-version }} ${{ matrix.install-extras }}
runs-on: ubuntu-22.04
timeout-minutes: 5 # usually 2-3 mins
Expand Down Expand Up @@ -112,7 +112,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.10"
python-version: "3.11"
- uses: nolar/setup-k3d-k3s@v1
with:
version: ${{ matrix.k3s }}
Expand All @@ -134,7 +134,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.10"
python-version: "3.11"
- run: tools/install-minikube.sh
- run: pip install -r requirements.txt -r examples/requirements.txt
- run: pytest --color=yes --timeout=30 --only-e2e
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ We assume that when the operator is executed in the cluster, it must be packaged
into a docker image with a CI/CD tool of your preference.

```dockerfile
FROM python:3.7
FROM python:3.11
ADD . /src
RUN pip install kopf
CMD kopf run /src/handlers.py --verbose
Expand Down
4 changes: 2 additions & 2 deletions docs/deployment.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ But normally, the operators are usually deployed directly to the clusters.
Docker image
============

First of all, the operator must be packaged as a docker image with Python 3.7:
First of all, the operator must be packaged as a docker image with Python 3.7 or newer:

.. code-block:: dockerfile
:caption: Dockerfile
:name: dockerfile

FROM python:3.7
FROM python:3.11
ADD . /src
RUN pip install kopf
CMD kopf run /src/handlers.py --verbose
Expand Down
4 changes: 4 additions & 0 deletions kopf/_cogs/structs/diffs.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ def __init__(self, __items: Iterable[DiffItem]):
super().__init__()
self._items = tuple(DiffItem(*item) for item in __items)

def __hash__(self) -> int:
# Hashes mark diffs as immutable to be usable as dataclasses' defaults in Python 3.11.
return hash(self._items)

def __repr__(self) -> str:
return repr(self._items)

Expand Down
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
[pytest]
; The standalone `mock` instead of stdlib `unittest.mock` is only for AsyncMock in Python 3.7.
mock_use_standalone_module = true
asyncio_mode = auto
addopts =
--strict-markers
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
-e .
aresponses
astpath[xpath]
asynctest
certbuilder
certvalidator
codecov
Expand All @@ -13,6 +12,9 @@ freezegun
import-linter
isort
lxml
# Generally, `unittest.mock` is enough, but it lacks `AsyncMock` for Py 3.7.
# TODO: Once 3.7 is removed (Jun 2023), roll back to unittest.mock.
mock
# Mypy requires typed-ast, which is broken on PyPy 3.7 (could work in PyPy 3.8).
mypy==0.982; implementation_name == "cpython"
pre-commit
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3 :: Only',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
Expand Down
2 changes: 1 addition & 1 deletion tests/admission/test_admission_server.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import contextlib
from unittest.mock import Mock

import pytest
from mock import Mock

import kopf
from kopf._cogs.aiokits.aiovalues import Container
Expand Down
3 changes: 1 addition & 2 deletions tests/admission/test_serving_handler_selection.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from unittest.mock import Mock

import pytest
from mock import Mock

import kopf
from kopf._cogs.structs.ids import HandlerId
Expand Down
3 changes: 1 addition & 2 deletions tests/admission/test_serving_kwargs_passthrough.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from unittest.mock import Mock

import pytest
from mock import Mock

import kopf
from kopf._core.engines.admission import serve_admission_request
Expand Down
14 changes: 7 additions & 7 deletions tests/apis/test_iterjsonlines.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import asynctest
from mock import Mock

from kopf._cogs.clients.api import iter_jsonlines

Expand All @@ -8,7 +8,7 @@ async def iter_chunked(n: int):
if False: # to make this function a generator
yield b''

content = asynctest.Mock(iter_chunked=iter_chunked)
content = Mock(iter_chunked=iter_chunked)
lines = []
async for line in iter_jsonlines(content):
lines.append(line)
Expand All @@ -20,7 +20,7 @@ async def test_empty_chunk():
async def iter_chunked(n: int):
yield b''

content = asynctest.Mock(iter_chunked=iter_chunked)
content = Mock(iter_chunked=iter_chunked)
lines = []
async for line in iter_jsonlines(content):
lines.append(line)
Expand All @@ -32,7 +32,7 @@ async def test_one_chunk_one_line():
async def iter_chunked(n: int):
yield b'hello'

content = asynctest.Mock(iter_chunked=iter_chunked)
content = Mock(iter_chunked=iter_chunked)
lines = []
async for line in iter_jsonlines(content):
lines.append(line)
Expand All @@ -44,7 +44,7 @@ async def test_one_chunk_two_lines():
async def iter_chunked(n: int):
yield b'hello\nworld'

content = asynctest.Mock(iter_chunked=iter_chunked)
content = Mock(iter_chunked=iter_chunked)
lines = []
async for line in iter_jsonlines(content):
lines.append(line)
Expand All @@ -56,7 +56,7 @@ async def test_one_chunk_empty_lines():
async def iter_chunked(n: int):
yield b'\n\nhello\n\nworld\n\n'

content = asynctest.Mock(iter_chunked=iter_chunked)
content = Mock(iter_chunked=iter_chunked)
lines = []
async for line in iter_jsonlines(content):
lines.append(line)
Expand All @@ -70,7 +70,7 @@ async def iter_chunked(n: int):
yield b'o\n\nwor'
yield b'ld\n\n'

content = asynctest.Mock(iter_chunked=iter_chunked)
content = Mock(iter_chunked=iter_chunked)
lines = []
async for line in iter_jsonlines(content):
lines.append(line)
Expand Down
2 changes: 1 addition & 1 deletion tests/basic-structs/test_memories.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from unittest.mock import Mock
from mock import Mock

from kopf._cogs.structs.bodies import Body
from kopf._cogs.structs.ephemera import Memo
Expand Down
2 changes: 1 addition & 1 deletion tests/causation/test_kwargs.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import dataclasses
import logging
from typing import Type
from unittest.mock import Mock

import pytest
from mock import Mock

from kopf._cogs.configs.configuration import OperatorSettings
from kopf._cogs.structs import diffs
Expand Down
18 changes: 3 additions & 15 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@
import sys
import time
from typing import Set
from unittest.mock import Mock

import aiohttp.web
import asynctest
import pytest
import pytest_mock
from mock import AsyncMock, Mock

import kopf
from kopf._cogs.clients.auth import APIContext
Expand All @@ -33,7 +31,6 @@ def pytest_configure(config):
config.addinivalue_line('filterwarnings', 'error')

# Warnings from the testing tools out of our control should not fail the tests.
config.addinivalue_line('filterwarnings', 'ignore:"@coroutine":DeprecationWarning:asynctest.mock')
config.addinivalue_line('filterwarnings', 'ignore:The loop argument:DeprecationWarning:aiohttp')
config.addinivalue_line('filterwarnings', 'ignore:The loop argument:DeprecationWarning:asyncio')
config.addinivalue_line('filterwarnings', 'ignore:is deprecated, use current_thread:DeprecationWarning:threading')
Expand Down Expand Up @@ -75,15 +72,6 @@ def _is_e2e(item):
items[:] = etc + e2e


# Substitute the regular mock with the async-aware mock in the `mocker` fixture.
@pytest.fixture(scope='session', autouse=True)
def enforce_asyncio_mocker(pytestconfig):
pytest_mock.plugin.get_mock_module = lambda config: asynctest
pytest_mock.get_mock_module = pytest_mock.plugin.get_mock_module
fixture = pytest_mock.MockerFixture(pytestconfig)
assert fixture.mock_module is asynctest, "Mock replacement failed!"


@pytest.fixture(params=[
('kopf.dev', 'v1', 'kopfpeerings', True),
('zalando.org', 'v1', 'kopfpeerings', True),
Expand Down Expand Up @@ -283,7 +271,7 @@ def test_me(resp_mocker):
assert callback.call_count == 1
"""
def resp_maker(*args, **kwargs):
actual_response = asynctest.MagicMock(*args, **kwargs)
actual_response = AsyncMock(*args, **kwargs)
async def resp_mock_effect(request):
nonlocal actual_response

Expand All @@ -300,7 +288,7 @@ async def resp_mock_effect(request):
response = await response
return response

return asynctest.CoroutineMock(side_effect=resp_mock_effect)
return AsyncMock(side_effect=resp_mock_effect)
return resp_maker


Expand Down
2 changes: 2 additions & 0 deletions tests/diffs/test_protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,5 @@ def test_diff_comparison_to_the_same():
DiffItem(DiffOperation.REMOVE, ('key3',), 'old3', None),
])
assert d1 == d2
assert hash(d1) == hash(d2)
assert d1 is not d2
2 changes: 1 addition & 1 deletion tests/handling/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@
"""
import dataclasses
from typing import Callable
from unittest.mock import Mock

import pytest
from mock import Mock

import kopf
from kopf._core.intents.causes import ChangingCause
Expand Down
7 changes: 3 additions & 4 deletions tests/handling/daemons/conftest.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import asyncio
import contextlib
import time
import unittest.mock

import freezegun
import pytest
from mock import MagicMock, patch

import kopf
from kopf._cogs.aiokits.aiotoggles import ToggleSet
Expand All @@ -19,7 +19,7 @@ class DaemonDummy:

def __init__(self):
super().__init__()
self.mock = unittest.mock.MagicMock()
self.mock = MagicMock()
self.kwargs = {}
self.steps = {
'called': asyncio.Event(),
Expand Down Expand Up @@ -107,8 +107,7 @@ def frozen_time():
with freezegun.freeze_time("2020-01-01 00:00:00") as frozen:
# Use freezegun-supported time instead of system clocks -- for testing purposes only.
# NB: Patch strictly after the time is frozen -- to use fake_time(), not real time().
with unittest.mock.patch('time.monotonic', time.time), \
unittest.mock.patch('time.perf_counter', time.time):
with patch('time.monotonic', time.time), patch('time.perf_counter', time.time):
yield frozen


Expand Down
2 changes: 1 addition & 1 deletion tests/handling/subhandling/test_subhandling.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import asyncio
import logging
from unittest.mock import Mock

import pytest
from mock import Mock

import kopf
from kopf._cogs.structs.ephemera import Memo
Expand Down
3 changes: 2 additions & 1 deletion tests/handling/test_parametrization.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
from unittest.mock import Mock

from mock import Mock

import kopf
from kopf._cogs.structs.ephemera import Memo
Expand Down
3 changes: 1 addition & 2 deletions tests/hierarchies/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from unittest.mock import Mock

import pytest
from mock import Mock


class CustomIterable:
Expand Down
2 changes: 1 addition & 1 deletion tests/hierarchies/test_owner_referencing.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import copy
from unittest.mock import call

import pytest
from mock import call

import kopf
from kopf._cogs.structs.bodies import Body, RawBody, RawMeta
Expand Down
Loading