From 86737b7a186d834bdd70cb3965ba6d5f45c561e6 Mon Sep 17 00:00:00 2001 From: Shinya Ohyanagi Date: Mon, 22 Aug 2022 20:22:16 +0900 Subject: [PATCH 01/12] Goodbye nose, hello pytest --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 666e122..6ecf618 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,6 @@ coverage==5.2.1 flake8==3.8.3 isort==5.5.0 mock==4.0.2 -nose==1.3.7 pymemcache==3.3.0 +pytest==7.1.2 readme-renderer==26.0 From d25c95bf15094e30326c9fca5660942ccabf9515 Mon Sep 17 00:00:00 2001 From: Shinya Ohyanagi Date: Mon, 22 Aug 2022 20:22:35 +0900 Subject: [PATCH 02/12] Replace nose to pytest --- tests/test_backend.py | 401 ++++++++++++++++++++---------------------- tests/test_client.py | 70 ++++---- 2 files changed, 228 insertions(+), 243 deletions(-) diff --git a/tests/test_backend.py b/tests/test_backend.py index 628f263..ad6eca9 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -1,241 +1,220 @@ +from unittest import TestCase from unittest.mock import Mock, patch import django from django.core.cache import InvalidCacheBackendError -from nose.tools import eq_, raises - from django_elastipymemcache.client import ConfigurationEndpointClient -@raises(InvalidCacheBackendError) -def test_multiple_servers(): - from django_elastipymemcache.backend import ElastiPymemcache - ElastiPymemcache('h1:0,h2:0', {}) - - -@raises(InvalidCacheBackendError) -def test_wrong_server_format(): - from django_elastipymemcache.backend import ElastiPymemcache - ElastiPymemcache('h', {}) - - -@patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_split_servers(get_cluster_info): - from django_elastipymemcache.backend import ElastiPymemcache - backend = ElastiPymemcache('h:0', {}) - servers = [('h1', 0), ('h2', 0)] - get_cluster_info.return_value = { - 'nodes': servers - } - backend._lib.Client = Mock() - assert backend._cache - get_cluster_info.assert_called() - backend._lib.Client.assert_called_once_with( - servers, - ignore_exc=True, - ) - - -@patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_node_info_cache(get_cluster_info): - from django_elastipymemcache.backend import ElastiPymemcache - servers = ['h1:0', 'h2:0'] - get_cluster_info.return_value = { - 'nodes': servers - } - - backend = ElastiPymemcache('h:0', {}) - backend._lib.Client = Mock() - backend.set('key1', 'val') - backend.get('key1') - backend.set('key2', 'val') - backend.get('key2') - backend._lib.Client.assert_called_once_with( - servers, - ignore_exc=True, - ) - eq_(backend._cache.get.call_count, 2) - eq_(backend._cache.set.call_count, 2) - - get_cluster_info.assert_called_once() - - -@patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_failed_to_connect_servers(get_cluster_info): - from django_elastipymemcache.backend import ElastiPymemcache - backend = ElastiPymemcache('h:0', {}) - get_cluster_info.side_effect = OSError() - eq_(backend.get_cluster_nodes(), []) - - -@patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_invalidate_cache(get_cluster_info): - from django_elastipymemcache.backend import ElastiPymemcache - servers = ['h1:0', 'h2:0'] - get_cluster_info.return_value = { - 'nodes': servers - } - - backend = ElastiPymemcache('h:0', {}) - backend._lib.Client = Mock() - assert backend._cache - backend._cache.get = Mock() - backend._cache.get.side_effect = Exception() - try: - backend.get('key1', 'val') - except Exception: - pass - # invalidate cached client - container = getattr(backend, '_local', backend) - container._client = None - try: - backend.get('key1', 'val') - except Exception: - pass - eq_(backend._cache.get.call_count, 2) - eq_(get_cluster_info.call_count, 3) - - -@patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_add(get_cluster_info): - from django_elastipymemcache.backend import ElastiPymemcache - - servers = ['h1:0', 'h2:0'] - get_cluster_info.return_value = { - 'nodes': servers - } - - backend = ElastiPymemcache('h:0', {}) - ret = backend.add('key1', 'value1') - eq_(ret, False) - - -@patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_delete(get_cluster_info): - from django_elastipymemcache.backend import ElastiPymemcache - - servers = ['h1:0', 'h2:0'] - get_cluster_info.return_value = { - 'nodes': servers - } - - backend = ElastiPymemcache('h:0', {}) - ret = backend.delete('key1') - if django.get_version() >= '3.1': - eq_(ret, False) - else: - eq_(ret, None) - - -@patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_get_many(get_cluster_info): - from django_elastipymemcache.backend import ElastiPymemcache - - servers = ['h1:0', 'h2:0'] - get_cluster_info.return_value = { - 'nodes': servers - } - - backend = ElastiPymemcache('h:0', {}) - ret = backend.get_many(['key1']) - eq_(ret, {}) - - # When server does not found... - with patch('pymemcache.client.hash.HashClient._get_client') as p: - p.return_value = None - ret = backend.get_many(['key2']) - eq_(ret, {}) - - with patch('pymemcache.client.hash.HashClient._safely_run_func') as p2: - p2.return_value = { - ':1:key3': 1509111630.048594 - } +class ErrorTestCase(TestCase): + def test_multiple_servers(self): + with self.assertRaises(InvalidCacheBackendError): + from django_elastipymemcache.backend import ElastiPymemcache + ElastiPymemcache('h1:0,h2:0', {}) - ret = backend.get_many(['key3']) - eq_(ret, {'key3': 1509111630.048594}) + def test_wrong_server_format(self): + with self.assertRaises(InvalidCacheBackendError): + from django_elastipymemcache.backend import ElastiPymemcache + ElastiPymemcache('h', {}) - # If False value is included, ignore it. - with patch('pymemcache.client.hash.HashClient.get_many') as p: - p.return_value = { - ':1:key1': 1509111630.048594, - ':1:key2': False, - ':1:key3': 1509111630.058594, + +class BackendTestCase(TestCase): + @patch.object(ConfigurationEndpointClient, 'get_cluster_info') + def test_split_servers(self, get_cluster_info): + from django_elastipymemcache.backend import ElastiPymemcache + backend = ElastiPymemcache('h:0', {}) + servers = [('h1', 0), ('h2', 0)] + get_cluster_info.return_value = { + 'nodes': servers } - ret = backend.get_many(['key1', 'key2', 'key3']) - eq_( - ret, - { - 'key1': 1509111630.048594, - 'key3': 1509111630.058594 - }, + backend._lib.Client = Mock() + assert backend._cache + get_cluster_info.assert_called() + backend._lib.Client.assert_called_once_with( + servers, + ignore_exc=True, ) - with patch('pymemcache.client.hash.HashClient.get_many') as p: - p.return_value = { - ':1:key1': None, - ':1:key2': 1509111630.048594, - ':1:key3': False, + @patch.object(ConfigurationEndpointClient, 'get_cluster_info') + def test_node_info_cache(self, get_cluster_info): + from django_elastipymemcache.backend import ElastiPymemcache + servers = ['h1:0', 'h2:0'] + get_cluster_info.return_value = { + 'nodes': servers } - ret = backend.get_many(['key1', 'key2', 'key3']) - eq_( - ret, - { - 'key2': 1509111630.048594, - }, + + backend = ElastiPymemcache('h:0', {}) + backend._lib.Client = Mock() + backend.set('key1', 'val') + backend.get('key1') + backend.set('key2', 'val') + backend.get('key2') + backend._lib.Client.assert_called_once_with( + servers, + ignore_exc=True, ) + assert backend._cache.get.call_count == 2 + assert backend._cache.set.call_count == 2 + + get_cluster_info.assert_called_once() + + @patch.object(ConfigurationEndpointClient, 'get_cluster_info') + def test_failed_to_connect_servers(self, get_cluster_info): + from django_elastipymemcache.backend import ElastiPymemcache + backend = ElastiPymemcache('h:0', {}) + get_cluster_info.side_effect = OSError() + assert backend.get_cluster_nodes() == [] + + @patch.object(ConfigurationEndpointClient, 'get_cluster_info') + def test_invalidate_cache(self, get_cluster_info): + from django_elastipymemcache.backend import ElastiPymemcache + servers = ['h1:0', 'h2:0'] + get_cluster_info.return_value = { + 'nodes': servers + } + + backend = ElastiPymemcache('h:0', {}) + backend._lib.Client = Mock() + assert backend._cache + backend._cache.get = Mock() + backend._cache.get.side_effect = Exception() + try: + backend.get('key1', 'val') + except Exception: + pass + # invalidate cached client + container = getattr(backend, '_local', backend) + container._client = None + try: + backend.get('key1', 'val') + except Exception: + pass + assert backend._cache.get.call_count == 2 + assert get_cluster_info.call_count == 3 + + @patch.object(ConfigurationEndpointClient, 'get_cluster_info') + def test_client_add(self, get_cluster_info): + from django_elastipymemcache.backend import ElastiPymemcache + + servers = ['h1:0', 'h2:0'] + get_cluster_info.return_value = { + 'nodes': servers + } + backend = ElastiPymemcache('h:0', {}) + ret = backend.add('key1', 'value1') + assert ret is False -@patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_set_many(get_cluster_info): - from django_elastipymemcache.backend import ElastiPymemcache + @patch.object(ConfigurationEndpointClient, 'get_cluster_info') + def test_client_delete(self, get_cluster_info): + from django_elastipymemcache.backend import ElastiPymemcache - servers = ['h1:0', 'h2:0'] - get_cluster_info.return_value = { - 'nodes': servers - } + servers = ['h1:0', 'h2:0'] + get_cluster_info.return_value = { + 'nodes': servers + } - backend = ElastiPymemcache('h:0', {}) - ret = backend.set_many({'key1': 'value1', 'key2': 'value2'}) - eq_(ret, ['key1', 'key2']) + backend = ElastiPymemcache('h:0', {}) + ret = backend.delete('key1') + if django.get_version() >= '3.1': + assert ret is False + else: + assert ret is None + @patch.object(ConfigurationEndpointClient, 'get_cluster_info') + def test_client_get_many(self, get_cluster_info): + from django_elastipymemcache.backend import ElastiPymemcache -@patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_delete_many(get_cluster_info): - from django_elastipymemcache.backend import ElastiPymemcache + servers = ['h1:0', 'h2:0'] + get_cluster_info.return_value = { + 'nodes': servers + } - servers = ['h1:0', 'h2:0'] - get_cluster_info.return_value = { - 'nodes': servers - } + backend = ElastiPymemcache('h:0', {}) + ret = backend.get_many(['key1']) + assert ret == {} + + # When server does not found... + with patch('pymemcache.client.hash.HashClient._get_client') as p: + p.return_value = None + ret = backend.get_many(['key2']) + assert ret == {} + + with patch('pymemcache.client.hash.HashClient._safely_run_func') as p2: + p2.return_value = { + ':1:key3': 1509111630.048594 + } + + ret = backend.get_many(['key3']) + assert ret == {'key3': 1509111630.048594} + + # If False value is included, ignore it. + with patch('pymemcache.client.hash.HashClient.get_many') as p: + p.return_value = { + ':1:key1': 1509111630.048594, + ':1:key2': False, + ':1:key3': 1509111630.058594, + } + ret = backend.get_many(['key1', 'key2', 'key3']) + assert ret == {'key1': 1509111630.048594, 'key3': 1509111630.058594} + + with patch('pymemcache.client.hash.HashClient.get_many') as p: + p.return_value = { + ':1:key1': None, + ':1:key2': 1509111630.048594, + ':1:key3': False, + } + ret = backend.get_many(['key1', 'key2', 'key3']) + assert ret == {'key2': 1509111630.048594} + + @patch.object(ConfigurationEndpointClient, 'get_cluster_info') + def test_client_set_many(self, get_cluster_info): + from django_elastipymemcache.backend import ElastiPymemcache + + servers = ['h1:0', 'h2:0'] + get_cluster_info.return_value = { + 'nodes': servers + } - backend = ElastiPymemcache('h:0', {}) - ret = backend.delete_many(['key1', 'key2']) - eq_(ret, None) + backend = ElastiPymemcache('h:0', {}) + ret = backend.set_many({'key1': 'value1', 'key2': 'value2'}) + assert ret == ['key1', 'key2'] + @patch.object(ConfigurationEndpointClient, 'get_cluster_info') + def test_client_delete_many(self, get_cluster_info): + from django_elastipymemcache.backend import ElastiPymemcache -@patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_incr(get_cluster_info): - from django_elastipymemcache.backend import ElastiPymemcache + servers = ['h1:0', 'h2:0'] + get_cluster_info.return_value = { + 'nodes': servers + } - servers = ['h1:0', 'h2:0'] - get_cluster_info.return_value = { - 'nodes': servers - } + backend = ElastiPymemcache('h:0', {}) + ret = backend.delete_many(['key1', 'key2']) + assert ret is None - backend = ElastiPymemcache('h:0', {}) - ret = backend.incr('key1', 1) - eq_(ret, False) + @patch.object(ConfigurationEndpointClient, 'get_cluster_info') + def test_client_incr(self, get_cluster_info): + from django_elastipymemcache.backend import ElastiPymemcache + servers = ['h1:0', 'h2:0'] + get_cluster_info.return_value = { + 'nodes': servers + } + + backend = ElastiPymemcache('h:0', {}) + ret = backend.incr('key1', 1) + assert ret is False -@patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_decr(get_cluster_info): - from django_elastipymemcache.backend import ElastiPymemcache + @patch.object(ConfigurationEndpointClient, 'get_cluster_info') + def test_client_decr(self, get_cluster_info): + from django_elastipymemcache.backend import ElastiPymemcache - servers = ['h1:0', 'h2:0'] - get_cluster_info.return_value = { - 'nodes': servers - } + servers = ['h1:0', 'h2:0'] + get_cluster_info.return_value = { + 'nodes': servers + } - backend = ElastiPymemcache('h:0', {}) - ret = backend.decr('key1', 1) - eq_(ret, False) + backend = ElastiPymemcache('h:0', {}) + ret = backend.decr('key1', 1) + assert ret is False diff --git a/tests/test_client.py b/tests/test_client.py index 724e0ad..5b675d9 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,11 +1,11 @@ import collections from unittest.mock import call, patch -from nose.tools import eq_, raises from pymemcache.exceptions import ( MemcacheUnknownCommandError, MemcacheUnknownError, ) +from pytest import raises from django_elastipymemcache.client import ConfigurationEndpointClient @@ -27,7 +27,10 @@ def test_get_cluster_info(socket): client = socket.return_value client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() cluster_info = ConfigurationEndpointClient(('h', 0)).get_cluster_info() - eq_(cluster_info['nodes'], ['10.82.235.120:11211', '10.80.249.27:11211']) + assert cluster_info['nodes'] == [ + '10.82.235.120:11211', + '10.80.249.27:11211', + ] client.sendall.assert_has_calls([ call(b'version\r\n'), call(b'config get cluster\r\n'), @@ -43,54 +46,57 @@ def test_get_cluster_info_before_1_4_13(socket): client = socket.return_value client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() cluster_info = ConfigurationEndpointClient(('h', 0)).get_cluster_info() - eq_(cluster_info['nodes'], ['10.82.235.120:11211', '10.80.249.27:11211']) + assert cluster_info['nodes'] == [ + '10.82.235.120:11211', + '10.80.249.27:11211', + ] client.sendall.assert_has_calls([ call(b'version\r\n'), call(b'get AmazonElastiCache:cluster\r\n'), ]) -@raises(MemcacheUnknownCommandError) @patch('socket.socket') def test_no_configuration_protocol_support_with_errors(socket): - recv_bufs = collections.deque([ - b'VERSION 1.4.13\r\n', - b'ERROR\r\n', - ]) + with raises(MemcacheUnknownCommandError): + recv_bufs = collections.deque([ + b'VERSION 1.4.13\r\n', + b'ERROR\r\n', + ]) - client = socket.return_value - client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() - ConfigurationEndpointClient(('h', 0)).get_cluster_info() + client = socket.return_value + client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() + ConfigurationEndpointClient(('h', 0)).get_cluster_info() -@raises(MemcacheUnknownError) @patch('socket.socket') def test_cannot_parse_version(socket): - recv_bufs = collections.deque([ - b'VERSION 1.4.34\r\n', - b'CONFIG cluster 0 147\r\n', - b'fail\nhost|ip|11211 host|ip|11211\n\r\n', - b'END\r\n', - ]) + with raises(MemcacheUnknownError): + recv_bufs = collections.deque([ + b'VERSION 1.4.34\r\n', + b'CONFIG cluster 0 147\r\n', + b'fail\nhost|ip|11211 host|ip|11211\n\r\n', + b'END\r\n', + ]) - client = socket.return_value - client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() - ConfigurationEndpointClient(('h', 0)).get_cluster_info() + client = socket.return_value + client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() + ConfigurationEndpointClient(('h', 0)).get_cluster_info() -@raises(MemcacheUnknownError) @patch('socket.socket') def test_cannot_parse_nodes(socket): - recv_bufs = collections.deque([ - b'VERSION 1.4.34\r\n', - b'CONFIG cluster 0 147\r\n', - b'1\nfail\n\r\n', - b'END\r\n', - ]) + with raises(MemcacheUnknownError): + recv_bufs = collections.deque([ + b'VERSION 1.4.34\r\n', + b'CONFIG cluster 0 147\r\n', + b'1\nfail\n\r\n', + b'END\r\n', + ]) - client = socket.return_value - client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() - ConfigurationEndpointClient(('h', 0)).get_cluster_info() + client = socket.return_value + client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() + ConfigurationEndpointClient(('h', 0)).get_cluster_info() @patch('socket.socket') @@ -107,4 +113,4 @@ def test_ignore_erros(socket): ('h', 0), ignore_cluster_errors=True, ).get_cluster_info() - eq_(cluster_info['nodes'], ['h:0']) + assert cluster_info['nodes'] == ['h:0'] From 0ad83f71a1ec333ce479f4bd83d981b8cf21d3d1 Mon Sep 17 00:00:00 2001 From: Shinya Ohyanagi Date: Mon, 22 Aug 2022 20:41:20 +0900 Subject: [PATCH 03/12] Fix flake8 errors --- tests/test_backend.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/test_backend.py b/tests/test_backend.py index ad6eca9..f8f84c5 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -3,6 +3,7 @@ import django from django.core.cache import InvalidCacheBackendError + from django_elastipymemcache.client import ConfigurationEndpointClient @@ -156,7 +157,10 @@ def test_client_get_many(self, get_cluster_info): ':1:key3': 1509111630.058594, } ret = backend.get_many(['key1', 'key2', 'key3']) - assert ret == {'key1': 1509111630.048594, 'key3': 1509111630.058594} + assert ret == { + 'key1': 1509111630.048594, + 'key3': 1509111630.058594 + } with patch('pymemcache.client.hash.HashClient.get_many') as p: p.return_value = { From b2c7921dde3cd09979fe96f3a647b8171476c837 Mon Sep 17 00:00:00 2001 From: Shinya Ohyanagi Date: Mon, 22 Aug 2022 20:42:03 +0900 Subject: [PATCH 04/12] Fix 3.8 to 3.10 --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3a654b9..957e7bd 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -29,10 +29,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python 3.8 + - name: Set up Python 3.10 uses: actions/setup-python@v2 with: - python-version: 3.8 + python-version: 3.10 - name: Install Tox run: pip install tox - name: isort From cff3db8618b16b2b64875f0f1828892b008e4569 Mon Sep 17 00:00:00 2001 From: Shinya Ohyanagi Date: Mon, 22 Aug 2022 20:42:16 +0900 Subject: [PATCH 05/12] Add python3.9 and 3.10 --- tox.ini | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tox.ini b/tox.ini index f4f90e1..6251e47 100644 --- a/tox.ini +++ b/tox.ini @@ -1,12 +1,12 @@ [tox] envlist = - py{37,38}-dj32, - py{37,38}-dj40, - py{37,38}-dj41, - py{37,38}-djdev, + py{37,38,39,310}-dj32, + py{37,38,39,310}-dj40, + py{37,38,39,310}-dj41, + py{37,38,39,310}-djdev, flake8, isort, - readme + readme, check-manifest [travis:env] @@ -25,31 +25,31 @@ deps = django-pymemcache<2.0 djdev: https://github.com/django/django/archive/master.tar.gz -r{toxinidir}/requirements.txt - py38-dj32: codecov + py310-dj41: codecov setenv = - PYTHONPATH = {toxinidir} + PYTHONPATH = {toxinidir}coverage run commands = - coverage run --source=django_elastipymemcache -m nose --verbose - py38-dj32: coverage report - py38-dj32: coverage xml - py38-dj32: codecov + coverage run --source=django_elastipymemcache -m pytest --verbose + py310-dj41: coverage report + py310-dj41: coverage xml + py310-dj41: codecov [testenv:flake8] -basepython = python3.8 +basepython = python3.10 commands = flake8 deps = flake8 [testenv:isort] -basepython = python3.8 +basepython = python3.10 commands = isort --verbose --check-only --diff django_elastipymemcache tests setup.py deps = isort [testenv:readme] -basepython = python3.8 +basepython = python3.10 commands = python setup.py check -r -s deps = readme_renderer [testenv:check-manifest] -basepython = python3.8 +basepython = python3.10 commands = check-manifest {toxinidir} deps = check-manifest From a85b3b6e91b89c304419e3be6ac84db580e9074a Mon Sep 17 00:00:00 2001 From: Shinya Ohyanagi Date: Mon, 22 Aug 2022 20:47:02 +0900 Subject: [PATCH 06/12] Fix add quote --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 957e7bd..4566b9f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -32,7 +32,7 @@ jobs: - name: Set up Python 3.10 uses: actions/setup-python@v2 with: - python-version: 3.10 + python-version: '3.10' - name: Install Tox run: pip install tox - name: isort From db40fc01b326638400e2bd6c6b76f2f904d74909 Mon Sep 17 00:00:00 2001 From: shkumagai Date: Tue, 23 Aug 2022 21:37:53 +0900 Subject: [PATCH 07/12] update tox settings --- tox.ini | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/tox.ini b/tox.ini index 6251e47..cd46d6b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,33 +1,33 @@ [tox] envlist = py{37,38,39,310}-dj32, - py{37,38,39,310}-dj40, - py{37,38,39,310}-dj41, - py{37,38,39,310}-djdev, + py{38,39,310}-dj40, + py{38,39,310}-dj41, + py{38,39,310}-djdev, flake8, isort, readme, check-manifest -[travis:env] -DJANGO = - 3.2: dj32 - 4.0: dj40 - 4.1: dj41 - dev: djdev +[gh-actions] +python = + 3.7: py37 + 3.8: py38 + 3.9: py39 + 3.10: py310 [testenv] passenv = TOXENV CI TRAVIS TRAVIS_* CODECOV_* deps = - dj32: Django<4.0 - dj40: Django<4.1 - dj41: Django<4.2 + dj32: Django>=3.2,<4.0 + dj40: Django>=4.0,<4.1 + dj41: Django>=4.1,<4.2 django-pymemcache<2.0 djdev: https://github.com/django/django/archive/master.tar.gz -r{toxinidir}/requirements.txt py310-dj41: codecov setenv = - PYTHONPATH = {toxinidir}coverage run + PYTHONPATH = {toxinidir} commands = coverage run --source=django_elastipymemcache -m pytest --verbose py310-dj41: coverage report @@ -35,21 +35,25 @@ commands = py310-dj41: codecov [testenv:flake8] +skip_install = true basepython = python3.10 commands = flake8 deps = flake8 [testenv:isort] +skip_install = true basepython = python3.10 commands = isort --verbose --check-only --diff django_elastipymemcache tests setup.py deps = isort [testenv:readme] +skip_install = true basepython = python3.10 commands = python setup.py check -r -s deps = readme_renderer [testenv:check-manifest] +skip_install = true basepython = python3.10 commands = check-manifest {toxinidir} deps = check-manifest From 9a5a5b09143cbfc28949dbc2e54ca28e286d5706 Mon Sep 17 00:00:00 2001 From: shkumagai Date: Thu, 25 Aug 2022 00:11:29 +0900 Subject: [PATCH 08/12] apply mock to 'socket.getaddrinfo' method which began to use to support IPv6 in the pymemcache client since v3.4.0 --- tests/test_client.py | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/tests/test_client.py b/tests/test_client.py index 5b675d9..5ee51a5 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,4 +1,5 @@ import collections +import socket as s from unittest.mock import call, patch from pymemcache.exceptions import ( @@ -18,12 +19,16 @@ ] +@patch('socket.getaddrinfo') @patch('socket.socket') -def test_get_cluster_info(socket): +def test_get_cluster_info(socket, getaddrinfo): recv_bufs = collections.deque([ b'VERSION 1.4.14\r\n', ] + EXAMPLE_RESPONSE) + getaddrinfo.return_value = [ + (s.AF_INET, s.SOCK_STREAM, 0, '', ('127.0.0.1', 0)), + ] client = socket.return_value client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() cluster_info = ConfigurationEndpointClient(('h', 0)).get_cluster_info() @@ -37,12 +42,16 @@ def test_get_cluster_info(socket): ]) +@patch('socket.getaddrinfo') @patch('socket.socket') -def test_get_cluster_info_before_1_4_13(socket): +def test_get_cluster_info_before_1_4_13(socket, getaddrinfo): recv_bufs = collections.deque([ b'VERSION 1.4.13\r\n', ] + EXAMPLE_RESPONSE) + getaddrinfo.return_value = [ + (s.AF_INET, s.SOCK_STREAM, 0, '', ('127.0.0.1', 0)), + ] client = socket.return_value client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() cluster_info = ConfigurationEndpointClient(('h', 0)).get_cluster_info() @@ -56,21 +65,26 @@ def test_get_cluster_info_before_1_4_13(socket): ]) +@patch('socket.getaddrinfo') @patch('socket.socket') -def test_no_configuration_protocol_support_with_errors(socket): +def test_no_configuration_protocol_support_with_errors(socket, getaddrinfo): with raises(MemcacheUnknownCommandError): recv_bufs = collections.deque([ b'VERSION 1.4.13\r\n', b'ERROR\r\n', ]) + getaddrinfo.return_value = [ + (s.AF_INET, s.SOCK_STREAM, 0, '', ('127.0.0.1', 0)), + ] client = socket.return_value client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() ConfigurationEndpointClient(('h', 0)).get_cluster_info() +@patch('socket.getaddrinfo') @patch('socket.socket') -def test_cannot_parse_version(socket): +def test_cannot_parse_version(socket, getaddrinfo): with raises(MemcacheUnknownError): recv_bufs = collections.deque([ b'VERSION 1.4.34\r\n', @@ -79,13 +93,17 @@ def test_cannot_parse_version(socket): b'END\r\n', ]) + getaddrinfo.return_value = [ + (s.AF_INET, s.SOCK_STREAM, 0, '', ('127.0.0.1', 0)), + ] client = socket.return_value client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() ConfigurationEndpointClient(('h', 0)).get_cluster_info() +@patch('socket.getaddrinfo') @patch('socket.socket') -def test_cannot_parse_nodes(socket): +def test_cannot_parse_nodes(socket, getaddrinfo): with raises(MemcacheUnknownError): recv_bufs = collections.deque([ b'VERSION 1.4.34\r\n', @@ -94,19 +112,26 @@ def test_cannot_parse_nodes(socket): b'END\r\n', ]) + getaddrinfo.return_value = [ + (s.AF_INET, s.SOCK_STREAM, 0, '', ('127.0.0.1', 0)), + ] client = socket.return_value client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() ConfigurationEndpointClient(('h', 0)).get_cluster_info() +@patch('socket.getaddrinfo') @patch('socket.socket') -def test_ignore_erros(socket): +def test_ignore_erros(socket, getaddrinfo): recv_bufs = collections.deque([ b'VERSION 1.4.34\r\n', b'fail\nfail\n\r\n', b'END\r\n', ]) + getaddrinfo.return_value = [ + (s.AF_INET, s.SOCK_STREAM, 0, '', ('127.0.0.1', 0)), + ] client = socket.return_value client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() cluster_info = ConfigurationEndpointClient( From 29801fad25a05de30160760472ee52defa6f5ffb Mon Sep 17 00:00:00 2001 From: shkumagai Date: Thu, 25 Aug 2022 00:17:03 +0900 Subject: [PATCH 09/12] apply mock to 'pymemcache.client.base.Client.set_many' method --- tests/test_backend.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_backend.py b/tests/test_backend.py index f8f84c5..a61237e 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -171,14 +171,16 @@ def test_client_get_many(self, get_cluster_info): ret = backend.get_many(['key1', 'key2', 'key3']) assert ret == {'key2': 1509111630.048594} + @patch('pymemcache.client.base.Client.set_many') @patch.object(ConfigurationEndpointClient, 'get_cluster_info') - def test_client_set_many(self, get_cluster_info): + def test_client_set_many(self, get_cluster_info, set_many): from django_elastipymemcache.backend import ElastiPymemcache servers = ['h1:0', 'h2:0'] get_cluster_info.return_value = { 'nodes': servers } + set_many.side_effect = [[':1:key1'], [':1:key2']] backend = ElastiPymemcache('h:0', {}) ret = backend.set_many({'key1': 'value1', 'key2': 'value2'}) From 31611874a39468f75006dcc10f842161cdea2a73 Mon Sep 17 00:00:00 2001 From: Shinya Ohyanagi Date: Mon, 23 Sep 2024 22:00:21 +0900 Subject: [PATCH 10/12] Fix replace packaging.version for distutils is deprecated --- django_elastipymemcache/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/django_elastipymemcache/client.py b/django_elastipymemcache/client.py index b381026..ab7ef97 100644 --- a/django_elastipymemcache/client.py +++ b/django_elastipymemcache/client.py @@ -1,5 +1,5 @@ import logging -from distutils.version import StrictVersion +from packaging.version import parse from django.utils.encoding import smart_str from pymemcache.client.base import Client, _readline @@ -17,7 +17,7 @@ def __init__(self, *args, ignore_cluster_errors=False, **kwargs): return client def _get_cluster_info_cmd(self): - if StrictVersion(smart_str(self.version())) < StrictVersion('1.4.14'): + if parse(smart_str(self.version())) < parse('1.4.14'): return b'get AmazonElastiCache:cluster\r\n' return b'config get cluster\r\n' From 2c01454dadc04846bf3d1b5d1ff83ea75d3b9e5c Mon Sep 17 00:00:00 2001 From: Shinya Ohyanagi Date: Mon, 23 Sep 2024 22:37:47 +0900 Subject: [PATCH 11/12] Fix isort error --- django_elastipymemcache/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django_elastipymemcache/client.py b/django_elastipymemcache/client.py index ab7ef97..4f6a2f5 100644 --- a/django_elastipymemcache/client.py +++ b/django_elastipymemcache/client.py @@ -1,7 +1,7 @@ import logging -from packaging.version import parse from django.utils.encoding import smart_str +from packaging.version import parse from pymemcache.client.base import Client, _readline from pymemcache.exceptions import MemcacheUnknownError From d9ac26abd9898764c09cb3e98776e0e0fd08a824 Mon Sep 17 00:00:00 2001 From: Shinya Ohyanagi Date: Mon, 23 Sep 2024 22:38:02 +0900 Subject: [PATCH 12/12] Fix apply tox v4 syntax --- tox.ini | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index cd46d6b..a541841 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,8 @@ envlist = py{37,38,39,310}-dj32, py{38,39,310}-dj40, py{38,39,310}-dj41, - py{38,39,310}-djdev, + py{38,39,310}-dj42, + py{310}-djdev, flake8, isort, readme, @@ -17,7 +18,7 @@ python = 3.10: py310 [testenv] -passenv = TOXENV CI TRAVIS TRAVIS_* CODECOV_* +passenv = TOXENV, CI, TRAVIS, TRAVIS_*, CODECOV_* deps = dj32: Django>=3.2,<4.0 dj40: Django>=4.0,<4.1