Skip to content

Commit

Permalink
Merge pull request #968 from nolar/python-3.11
Browse files Browse the repository at this point in the history
Upgrade to Python 3.11 in CI
  • Loading branch information
nolar committed Nov 1, 2022
2 parents 928a4f2 + 50f1ff5 commit a251e84
Show file tree
Hide file tree
Showing 34 changed files with 93 additions and 89 deletions.
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

0 comments on commit a251e84

Please sign in to comment.