commit: 8ab50ae15e2aa43bfd764a8af322fab92bb989b8 Author: Sam James <sam <AT> gentoo <DOT> org> AuthorDate: Sat May 24 19:36:35 2025 +0000 Commit: Sam James <sam <AT> gentoo <DOT> org> CommitDate: Sat May 24 19:36:35 2025 +0000 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=8ab50ae1
dev-python/aiocache: enable py3.13 Closes: https://bugs.gentoo.org/952315 Signed-off-by: Sam James <sam <AT> gentoo.org> dev-python/aiocache/aiocache-0.12.3-r1.ebuild | 73 +++++++ .../aiocache/files/aiocache-0.12.3-py313.patch | 239 +++++++++++++++++++++ 2 files changed, 312 insertions(+) diff --git a/dev-python/aiocache/aiocache-0.12.3-r1.ebuild b/dev-python/aiocache/aiocache-0.12.3-r1.ebuild new file mode 100644 index 000000000000..270ad52a1dde --- /dev/null +++ b/dev-python/aiocache/aiocache-0.12.3-r1.ebuild @@ -0,0 +1,73 @@ +# Copyright 1999-2025 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +EAPI=8 + +DISTUTILS_USE_PEP517=setuptools +PYTHON_COMPAT=( python3_{11..13} ) + +inherit distutils-r1 pypi + +DESCRIPTION="Asyncio cache manager" +HOMEPAGE=" + https://github.com/aio-libs/aiocache/ + https://pypi.org/project/aiocache/ +" + +LICENSE="Apache-2.0" +SLOT="0" +KEYWORDS="~amd64 ~x86" + +BDEPEND=" + test? ( + dev-db/redis + dev-python/marshmallow[${PYTHON_USEDEP}] + >=dev-python/msgpack-0.5.5[${PYTHON_USEDEP}] + dev-python/pytest-asyncio[${PYTHON_USEDEP}] + dev-python/pytest-mock[${PYTHON_USEDEP}] + >=dev-python/redis-4.2.0[${PYTHON_USEDEP}] + ) +" + +PATCHES=( + "${FILESDIR}"/${P}-py313.patch +) + +distutils_enable_tests pytest + +python_test() { + local EPYTEST_DESELECT=( + # broken by newer dev-python/redis (?), removed upstream + tests/ut/backends/test_redis.py::TestRedisBackend::test_close + ) + local EPYTEST_IGNORE=( + # benchmarks + tests/performance + # requires aiomcache + tests/ut/backends/test_memcached.py + ) + + local -x PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 + epytest -o addopts= -m "not memcached" -p asyncio -p pytest_mock +} + +src_test() { + local redis_pid="${T}"/redis.pid + local redis_port=6379 + + # Spawn Redis for testing purposes + einfo "Spawning Redis" + einfo "NOTE: Port ${redis_port} must be free" + "${EPREFIX}"/usr/sbin/redis-server - <<- EOF || die "Unable to start redis server" + daemonize yes + pidfile ${redis_pid} + port ${redis_port} + bind 127.0.0.1 ::1 + EOF + + # Run the tests + distutils-r1_src_test + + # Clean up afterwards + kill "$(<"${redis_pid}")" || die +} diff --git a/dev-python/aiocache/files/aiocache-0.12.3-py313.patch b/dev-python/aiocache/files/aiocache-0.12.3-py313.patch new file mode 100644 index 000000000000..5df233144a62 --- /dev/null +++ b/dev-python/aiocache/files/aiocache-0.12.3-py313.patch @@ -0,0 +1,239 @@ +https://github.com/aio-libs/aiocache/commit/47ac136b65db9cb4106ed68f764ad257db0277bb + +From 47ac136b65db9cb4106ed68f764ad257db0277bb Mon Sep 17 00:00:00 2001 +From: Sam Bull <[email protected]> +Date: Mon, 25 Nov 2024 09:26:30 +0000 +Subject: [PATCH] Update for Python 3.13 (#864) + +Co-authored-by: Andrew Svetlov <[email protected]> +--- + .github/workflows/ci.yml | 8 ++++---- + .pre-commit-config.yaml | 4 ++-- + .readthedocs.yml | 24 ++++++++++++++++++++++++ + aiocache/backends/redis.py | 3 ++- + examples/frameworks/aiohttp_example.py | 2 +- + requirements-dev.txt | 7 ++++--- + requirements.txt | 18 +++++++++--------- + setup.cfg | 2 ++ + setup.py | 7 ++++--- + tests/performance/server.py | 11 +++++++---- + tests/ut/backends/test_redis.py | 2 +- + tests/ut/test_decorators.py | 20 ++++++++++---------- + 12 files changed, 70 insertions(+), 38 deletions(-) + create mode 100644 .readthedocs.yml + +diff --git a/aiocache/backends/redis.py b/aiocache/backends/redis.py +index d0e3bd65..ce115516 100644 +--- a/aiocache/backends/redis.py ++++ b/aiocache/backends/redis.py +@@ -51,6 +51,7 @@ def __init__( + warnings.warn( + "Parameter 'pool_min_size' is deprecated since aiocache 0.12", + DeprecationWarning, ++ stacklevel=2, + ) + + self.endpoint = endpoint +@@ -188,7 +189,7 @@ async def _redlock_release(self, key, value): + return await self._raw("eval", self.RELEASE_SCRIPT, 1, key, value) + + async def _close(self, *args, _conn=None, **kwargs): +- await self.client.close() ++ await self.client.aclose() + + + class RedisCache(RedisBackend): +diff --git a/examples/frameworks/aiohttp_example.py b/examples/frameworks/aiohttp_example.py +index e612b30a..7220c711 100644 +--- a/examples/frameworks/aiohttp_example.py ++++ b/examples/frameworks/aiohttp_example.py +@@ -25,7 +25,7 @@ def __init__(self, *args, **kwargs): + async def get_from_cache(self, key): + try: + value = await self.cache.get(key) +- if type(value) == web.Response: ++ if type(value) is web.Response: + return web.Response( + body=value.body, + status=value.status, +diff --git a/requirements-dev.txt b/requirements-dev.txt +index 82a078fb..a4380ba4 100644 +--- a/requirements-dev.txt ++++ b/requirements-dev.txt +@@ -1,10 +1,11 @@ + -r requirements.txt + +-flake8==6.0.0 ++flake8==7.1.1 + flake8-bandit==4.1.1 +-flake8-bugbear==22.12.6 ++flake8-bugbear==24.10.31 + flake8-import-order==0.18.2 +-flake8-requirements==1.7.6 ++flake8-requirements==2.2.1 + mypy==0.991; implementation_name=="cpython" + types-redis==4.4.0.0 + types-ujson==5.7.0.0 ++sphinx==8.1.3 +diff --git a/requirements.txt b/requirements.txt +index 31dfe1a2..6a1e5ba4 100644 +--- a/requirements.txt ++++ b/requirements.txt +@@ -1,11 +1,11 @@ + -e . + +-aiomcache==0.8.0 +-aiohttp==3.8.3 +-marshmallow==3.19.0 +-msgpack==1.0.4 +-pytest==7.2.0 +-pytest-asyncio==0.20.3 +-pytest-cov==4.0.0 +-pytest-mock==3.10.0 +-redis==4.4.2 ++aiomcache==0.8.2 ++aiohttp==3.9.5 ++marshmallow==3.21.3 ++msgpack==1.0.8 ++pytest==7.4.4 ++pytest-asyncio==0.23.7 ++pytest-cov==5.0.0 ++pytest-mock==3.14.0 ++redis==5.0.5 +diff --git a/setup.py b/setup.py +index ed54028b..c8bcbada 100644 +--- a/setup.py ++++ b/setup.py +@@ -22,17 +22,18 @@ + long_description=readme, + classifiers=[ + "Programming Language :: Python", +- "Programming Language :: Python :: 3.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.12", ++ "Programming Language :: Python :: 3.13", + "Framework :: AsyncIO", + ], ++ python_requires=">=3.9", + packages=("aiocache",), + install_requires=None, + extras_require={ +- "redis": ["redis>=4.2.0"], ++ "redis": ["redis>=5"], + "memcached": ["aiomcache>=0.5.2"], + "msgpack": ["msgpack>=0.5.5"], + }, +diff --git a/tests/performance/server.py b/tests/performance/server.py +index 8de8c6b8..7fcfd319 100644 +--- a/tests/performance/server.py ++++ b/tests/performance/server.py +@@ -28,22 +28,25 @@ async def close(self, *_): + await self.cache.close() + + ++cache_key = web.AppKey("cache", CacheManager) ++ ++ + async def handler_get(req): + try: +- data = await req.app["cache"].get("testkey") ++ data = await req.app[cache_key].get("testkey") + if data: + return web.Response(text=data) + except asyncio.TimeoutError: + return web.Response(status=404) + + data = str(uuid.uuid4()) +- await req.app["cache"].set("testkey", data) ++ await req.app[cache_key].set("testkey", data) + return web.Response(text=str(data)) + + + def run_server(backend: str) -> None: + app = web.Application() +- app["cache"] = CacheManager(backend) +- app.on_shutdown.append(app["cache"].close) ++ app[cache_key] = CacheManager(backend) ++ app.on_shutdown.append(app[cache_key].close) + app.router.add_route("GET", "/", handler_get) + web.run_app(app) +diff --git a/tests/ut/backends/test_redis.py b/tests/ut/backends/test_redis.py +index a26e4086..2837cbcf 100644 +--- a/tests/ut/backends/test_redis.py ++++ b/tests/ut/backends/test_redis.py +@@ -233,7 +233,7 @@ async def test_redlock_release(self, mocker, redis): + + async def test_close(self, redis): + await redis._close() +- assert redis.client.close.call_count == 1 ++ assert redis.client.aclose.call_count == 1 + + + class TestRedisCache: +diff --git a/tests/ut/test_decorators.py b/tests/ut/test_decorators.py +index e4a1a07e..a59fb31c 100644 +--- a/tests/ut/test_decorators.py ++++ b/tests/ut/test_decorators.py +@@ -154,8 +154,8 @@ async def test_calls_fn_set_when_get_none(self, mocker, decorator, decorator_cal + + async def test_calls_fn_raises_exception(self, decorator, decorator_call): + decorator.cache.get.return_value = None +- stub.side_effect = Exception() +- with pytest.raises(Exception): ++ stub.side_effect = RuntimeError() ++ with pytest.raises(RuntimeError): + assert await decorator_call() + + async def test_cache_write_waits_for_future(self, decorator, decorator_call): +@@ -167,11 +167,10 @@ async def test_cache_write_waits_for_future(self, decorator, decorator_call): + async def test_cache_write_doesnt_wait_for_future(self, mocker, decorator, decorator_call): + mocker.spy(decorator, "set_in_cache") + with patch.object(decorator, "get_from_cache", autospec=True, return_value=None): +- with patch("aiocache.decorators.asyncio.ensure_future", autospec=True): +- await decorator_call(aiocache_wait_for_write=False, value="value") ++ await decorator_call(aiocache_wait_for_write=False, value="value") + + decorator.set_in_cache.assert_not_awaited() +- decorator.set_in_cache.assert_called_once_with("stub()[('value', 'value')]", "value") ++ # decorator.set_in_cache.assert_called_once_with("stub()[('value', 'value')]", "value") + + async def test_set_calls_set(self, decorator, decorator_call): + await decorator.set_in_cache("key", "value") +@@ -287,10 +286,11 @@ async def test_calls_get_and_returns(self, decorator, decorator_call): + assert decorator.cache.set.call_count == 0 + assert stub.call_count == 0 + ++ @pytest.mark.xfail(reason="Mess in stubs") + async def test_calls_fn_raises_exception(self, decorator, decorator_call): + decorator.cache.get.return_value = None +- stub.side_effect = Exception() +- with pytest.raises(Exception): ++ stub.side_effect = RuntimeError() ++ with pytest.raises(RuntimeError): + assert await decorator_call() + + async def test_calls_redlock(self, decorator, decorator_call): +@@ -483,7 +483,7 @@ async def test_cache_write_doesnt_wait_for_future(self, mocker, decorator, decor + aiocache_wait_for_write=False) + + decorator.set_in_cache.assert_not_awaited() +- decorator.set_in_cache.assert_called_once_with({"a": ANY, "b": ANY}, stub_dict, ANY, ANY) ++ # decorator.set_in_cache.assert_called_once_with({"a": ANY, "b": ANY}, stub_dict, ANY, ANY) + + async def test_calls_fn_with_only_missing_keys(self, mocker, decorator, decorator_call): + mocker.spy(decorator, "set_in_cache") +@@ -496,8 +496,8 @@ async def test_calls_fn_with_only_missing_keys(self, mocker, decorator, decorato + + async def test_calls_fn_raises_exception(self, decorator, decorator_call): + decorator.cache.multi_get.return_value = [None] +- stub_dict.side_effect = Exception() +- with pytest.raises(Exception): ++ stub_dict.side_effect = RuntimeError() ++ with pytest.raises(RuntimeError): + assert await decorator_call(keys=[]) + + async def test_cache_read_disabled(self, decorator, decorator_call): +
