diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..2901f15 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,45 @@ +name: build + +on: [push, pull_request] + +jobs: + build: + name: Python ${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.12'] + env: + COVERAGE_OPTIONS: "-a" + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install Tox and any other packages + run: pip install tox tox-gh-actions + - name: Test with tox + run: tox + + code_quality: + name: Code Quality + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.12 + uses: actions/setup-python@v2 + with: + python-version: '3.12' + - name: Install Tox + run: pip install tox + - name: isort + run: tox -e isort + - name: readme + run: tox -e readme + - name: flake8 + run: tox -e flake8 + - name: check-manifest + run: tox -e check-manifest diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ff8b126..0000000 --- a/.travis.yml +++ /dev/null @@ -1,41 +0,0 @@ -sudo: false -language: python -python: - - 3.6 - - 3.7 - - 3.8 -cache: pip -env: - - DJANGO=3.2 - - DJANGO=dev - -matrix: - include: - - python: 3.8 - env: TOXENV=flake8 - - python: 3.8 - env: TOXENV=isort - - python: 3.8 - env: TOXENV=readme - - python: 3.8 - env: TOXENV=check-manifest - allow_failures: - - env: DJANGO=dev -install: -- travis_retry python3 -m pip install tox-travis -script: -- tox -deploy: - provider: pypi - username: __token__ - password: - secure: "HBbDdcrrzRrSXbQGz3cz24/xNIW77tVlHQ+D6DS5raOSV7en5CPaiWZ50YkMQa08nfBOR1RBT8JivrC05qz1+TqMwOz0+rinFeGPmu9gLY8f+1kx0UZnmXG7GHsm6dBGOP6nIHA40+rtK/YLuhskdd2hEBIOAuAxXuCSd1UQ/3bj/nuspDwcot9OdJiyn+Xl+cjI39Gt8WlF7ZBjgFRw1hNSIJ2f0or38zf+SSDY6QgKiJZCn+4sooy0assCms84LSKumSl7Ya50IWwBGJgJaNPxikqgTf3rDP9bT25OLtJw78zJnO4QC2PJ9Y7j2tzeYkelHJM794uAtKNaW1SanlYdBXQoE7m1CE8DszZxCtN/siuz+30whFJ885pPaSN3m5uJct/v9GxBEAHtoCrwwdfrTvzVCU43PGwPZvO768k465rRGUnBInLybO5hTq6myajecZB2WhVXMh7/KMcXlVtnD5PvIhxLkLPVIGBK+1wFfvH/4ijZl8Dhz5PXP53AcX/Ohdli7+kd9DQEvieE2bhDpBaJq2r7B4etW/bjz76GQ704uzuF5JXXEibaT1fox8nqJzghuWfcXJvoTa20iR1quuHg0Z4qBIYh76CUXafi4iIZ0fCcIDVPWM7KSp1rvt4BgCdi1csQdTasw0l0WGoKdOSu+LlNSrqzPLoXQlE=" - distributions: sdist bdist_wheel - skip_upload_docs: true - on: - repo: harikitech/django-elastipymemcache - tags: true - python: 3.8 - condition: "$DJANGO = 3.2" -notifications: - email: false diff --git a/django_elastipymemcache/__init__.py b/django_elastipymemcache/__init__.py index f40c6d0..25e6d8b 100644 --- a/django_elastipymemcache/__init__.py +++ b/django_elastipymemcache/__init__.py @@ -1,2 +1,2 @@ -VERSION = (2, 0, 4) +VERSION = (2, 0, 5) __version__ = '.'.join(map(str, VERSION)) diff --git a/django_elastipymemcache/backend.py b/django_elastipymemcache/backend.py index fadc172..aef6b50 100644 --- a/django_elastipymemcache/backend.py +++ b/django_elastipymemcache/backend.py @@ -84,7 +84,7 @@ def client_servers(self): socket.gaierror, socket.timeout, ) as e: - logger.warn( + logger.warning( 'Cannot connect to cluster %s, err: %s', self.configuration_endpoint_client.server, e, diff --git a/django_elastipymemcache/client.py b/django_elastipymemcache/client.py index cf6847e..7a86683 100644 --- a/django_elastipymemcache/client.py +++ b/django_elastipymemcache/client.py @@ -1,7 +1,7 @@ import logging -from distutils.version import StrictVersion from django.utils.encoding import smart_str +from packaging.version import parse from pymemcache.client.base import Client, _readline from pymemcache.exceptions import MemcacheUnknownError @@ -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' @@ -26,7 +26,10 @@ def _extract_cluster_info(self, line): nodes = [] for raw_node in raw_nodes.split(b' '): host, ip, port = raw_node.split(b'|') - nodes.append((smart_str(ip or host), int(port))) + nodes.append('{host}:{port}'.format( + host=smart_str(ip or host), + port=int(port) + )) return { 'version': int(raw_version), 'nodes': nodes, @@ -63,7 +66,7 @@ def get_cluster_info(self): return self._fetch_cluster_info_cmd(cmd, 'config cluster') except Exception as e: if self.ignore_cluster_errors: - logger.warn('Failed to get cluster: %s', e) + logger.warning('Failed to get cluster: %s', e) return { 'version': None, 'nodes': [( diff --git a/requirements.txt b/requirements.txt index 5292a93..c83a9fa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ -check-manifest==0.42 -coverage==5.2.1 -flake8==3.8.3 -isort==5.5.0 -mock==4.0.2 -nose==1.3.7 -pymemcache==3.4.3 -readme-renderer==26.0 +check-manifest==0.48 +coverage==6.4.4 +flake8==5.0.4 +isort==5.10.1 +mock==4.0.3 +pymemcache==3.5.2 +pytest==7.1.2 +readme-renderer==37.0 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index ca864d7..363fcea 100644 --- a/setup.cfg +++ b/setup.cfg @@ -15,3 +15,13 @@ ignore = [coverage:run] branch = True omit = tests/* + +[flake8] +exclude = + .git, + .tox, + .venv, + .eggs, + migrations, + venv, + __pycache__ diff --git a/tests/test_backend.py b/tests/test_backend.py index 650162d..21a3fed 100644 --- a/tests/test_backend.py +++ b/tests/test_backend.py @@ -1,71 +1,74 @@ +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 nose.tools import eq_ from django_elastipymemcache.client import ConfigurationEndpointClient -@raises(InvalidCacheBackendError) -def test_multiple_servers(): - from django_elastipymemcache.backend import ElastiPymemcache - ElastiPymemcache('h1:0,h2:0', {}) +class ErrorTestCase(TestCase): + def test_multiple_servers(self): + with self.assertRaises(InvalidCacheBackendError): + from django_elastipymemcache.backend import ElastiPymemcache + ElastiPymemcache('h1:0,h2:0', {}) + def test_wrong_server_format(self): + with self.assertRaises(InvalidCacheBackendError): + from django_elastipymemcache.backend import ElastiPymemcache + ElastiPymemcache('h', {}) -@raises(InvalidCacheBackendError) -def test_wrong_server_format(): - from django_elastipymemcache.backend import ElastiPymemcache - ElastiPymemcache('h', {}) +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 + } + backend._class = Mock() + assert backend._cache + get_cluster_info.assert_called() + backend._class.assert_called_once() + + eq_(backend._class.call_args[0], (servers,)) + + @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 + } -@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._class = Mock() - assert backend._cache - get_cluster_info.assert_called() - backend._class.assert_called_once() - eq_(backend._class.call_args[0], (servers,)) + backend = ElastiPymemcache('h:0', {}) + backend._class = Mock() + backend.set('key1', 'val') + backend.get('key1') + backend.set('key2', 'val') + backend.get('key2') + backend._class.assert_called_once() + eq_(backend._class.call_args[0], (servers,)) + assert backend._cache.get.call_count == 2 + assert backend._cache.set.call_count == 2 -@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._class = Mock() - backend.set('key1', 'val') - backend.get('key1') - backend.set('key2', 'val') - backend.get('key2') - backend._class.assert_called_once() - eq_(backend._class.call_args[0], (servers,)) - eq_(backend._cache.get.call_count, 2) - eq_(backend._cache.set.call_count, 2) - - get_cluster_info.assert_called_once() + get_cluster_info.assert_called_once() @patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_failed_to_connect_servers(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() - eq_(backend.client_servers, []) + assert backend.get_cluster_nodes() == [] @patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_invalidate_cache(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 = { @@ -73,7 +76,7 @@ def test_invalidate_cache(get_cluster_info): } backend = ElastiPymemcache('h:0', {}) - # backend._class = Mock() + backend._lib.Client = Mock() assert backend._cache backend._cache.get = Mock() backend._cache.get.side_effect = Exception() @@ -81,22 +84,19 @@ def test_invalidate_cache(get_cluster_info): backend.get('key1', 'val') except Exception: pass - # This should have removed the _cache instance - assert '_cache' not in backend.__dict__ - # Again - backend._cache.get = Mock() - backend._cache.get.side_effect = Exception() + # invalidate cached client + container = getattr(backend, '_local', backend) + container._client = None try: backend.get('key1', 'val') except Exception: pass - assert '_cache' not in backend.__dict__ - assert backend._cache - eq_(get_cluster_info.call_count, 3) + assert backend._cache.get.call_count == 2 + assert get_cluster_info.call_count == 3 @patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_add(get_cluster_info): +def test_client_add(self, get_cluster_info): from django_elastipymemcache.backend import ElastiPymemcache servers = [('h1', 0), ('h2', 0)] @@ -106,11 +106,11 @@ def test_client_add(get_cluster_info): backend = ElastiPymemcache('h:0', {}) ret = backend.add('key1', 'value1') - eq_(ret, False) + assert ret is False @patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_delete(get_cluster_info): +def test_client_delete(self, get_cluster_info): from django_elastipymemcache.backend import ElastiPymemcache servers = [('h1', 0), ('h2', 0)] @@ -121,13 +121,13 @@ def test_client_delete(get_cluster_info): backend = ElastiPymemcache('h:0', {}) ret = backend.delete('key1') if django.get_version() >= '3.1': - eq_(ret, False) + assert ret is False else: - eq_(ret, None) + assert ret is None @patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_get_many(get_cluster_info): +def test_client_get_many(self, get_cluster_info): from django_elastipymemcache.backend import ElastiPymemcache servers = [('h1', 0), ('h2', 0)] @@ -137,13 +137,13 @@ def test_client_get_many(get_cluster_info): backend = ElastiPymemcache('h:0', {}) ret = backend.get_many(['key1']) - eq_(ret, {}) + 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']) - eq_(ret, {}) + assert ret == {} with patch('pymemcache.client.hash.HashClient._safely_run_func') as p2: p2.return_value = { @@ -151,7 +151,7 @@ def test_client_get_many(get_cluster_info): } ret = backend.get_many(['key3']) - eq_(ret, {'key3': 1509111630.048594}) + assert ret == {'key3': 1509111630.048594} # If False value is included, include it. with patch('pymemcache.client.hash.HashClient.get_multi') as p: @@ -161,47 +161,40 @@ def test_client_get_many(get_cluster_info): ':1:key3': 1509111630.058594, } ret = backend.get_many(['key1', 'key2', 'key3']) - eq_( - ret, - { - 'key1': 1509111630.048594, - 'key2': False, - 'key3': 1509111630.058594 - }, - ) - - # Even None is valid. Only key not found is not returned. - with patch('pymemcache.client.hash.HashClient.get_multi') as p: + assert ret == { + 'key1': 1509111630.048594, + 'key2': False, + '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']) - eq_( - ret, - { - 'key1': None, - 'key2': 1509111630.048594, - }, - ) + assert ret == {'key2': 1509111630.048594} +@patch('pymemcache.client.base.Client.set_many') @patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_set_many(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'}) - eq_(ret, ['key1', 'key2']) + assert ret == ['key1', 'key2'] @patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_delete_many(get_cluster_info): +def test_client_delete_many(self, get_cluster_info): from django_elastipymemcache.backend import ElastiPymemcache servers = [('h1', 0), ('h2', 0)] @@ -211,11 +204,11 @@ def test_client_delete_many(get_cluster_info): backend = ElastiPymemcache('h:0', {}) ret = backend.delete_many(['key1', 'key2']) - eq_(ret, None) + assert ret is None @patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_incr(get_cluster_info): +def test_client_incr(self, get_cluster_info): from django_elastipymemcache.backend import ElastiPymemcache servers = [('h1', 0), ('h2', 0)] @@ -225,11 +218,11 @@ def test_client_incr(get_cluster_info): backend = ElastiPymemcache('h:0', {}) ret = backend.incr('key1', 1) - eq_(ret, False) + assert ret is False @patch.object(ConfigurationEndpointClient, 'get_cluster_info') -def test_client_decr(get_cluster_info): +def test_client_decr(self, get_cluster_info): from django_elastipymemcache.backend import ElastiPymemcache servers = [('h1', 0), ('h2', 0)] @@ -239,4 +232,4 @@ def test_client_decr(get_cluster_info): backend = ElastiPymemcache('h:0', {}) ret = backend.decr('key1', 1) - eq_(ret, False) + assert ret is False diff --git a/tests/test_client.py b/tests/test_client.py index 57a4f9c..5ee51a5 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,11 +1,12 @@ import collections +import socket as s 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 @@ -18,104 +19,123 @@ ] -@patch('socket.getaddrinfo', return_value=[range(5)]) +@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() - 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'), ]) -@patch('socket.getaddrinfo', return_value=[range(5)]) +@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() - 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.getaddrinfo', return_value=[range(5)]) +@patch('socket.getaddrinfo') @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', - ]) - client = socket.return_value - client.recv.side_effect = lambda *args, **kwargs: recv_bufs.popleft() - ConfigurationEndpointClient(('h', 0)).get_cluster_info() +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() -@raises(MemcacheUnknownError) -@patch('socket.getaddrinfo', return_value=[range(5)]) +@patch('socket.getaddrinfo') @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', - ]) +def test_cannot_parse_version(socket, getaddrinfo): + 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() + 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() -@raises(MemcacheUnknownError) -@patch('socket.getaddrinfo', return_value=[range(5)]) +@patch('socket.getaddrinfo') @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', - ]) +def test_cannot_parse_nodes(socket, getaddrinfo): + 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() + 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', return_value=[range(5)]) +@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( ('h', 0), ignore_cluster_errors=True, ).get_cluster_info() - eq_(cluster_info['nodes'], [('h', 0)]) + assert cluster_info['nodes'] == ['h:0'] diff --git a/tox.ini b/tox.ini index 758bce1..cc095f7 100644 --- a/tox.ini +++ b/tox.ini @@ -1,48 +1,56 @@ [tox] envlist = - py{36,37,38}-dj32, - py{36,37,38}-djdev, + py{312}-dj52, flake8, isort, - readme + readme, check-manifest -[travis:env] -DJANGO = - 3.2: dj32 - dev: djdev +[gh-actions] +python = + 3.12: py312 [testenv] -passenv = TOXENV CI TRAVIS TRAVIS_* CODECOV_* +passenv = TOXENV, CI, TRAVIS, TRAVIS_*, CODECOV_* deps = - dj32: Django<3.3 + dj32: Django>=3.2,<4.0 + dj40: Django>=4.0,<4.1 + dj41: Django>=4.1,<4.2 + dj52: Django>=5.2 + django-pymemcache<2.0 djdev: https://github.com/django/django/archive/master.tar.gz -r{toxinidir}/requirements.txt - py37-dj32: codecov + py310-dj41: codecov setenv = PYTHONPATH = {toxinidir} commands = - coverage run --source=django_elastipymemcache -m nose --verbose - py37-dj32: coverage report - py37-dj32: coverage xml - py37-dj32: codecov + coverage run --source=django_elastipymemcache -m pytest --verbose + py312-dj52: coverage report + py312-dj52: coverage xml + py312-dj52: codecov [testenv:flake8] -basepython = python3.7 +skip_install = true +basepython = python3.12 commands = flake8 deps = flake8 [testenv:isort] -basepython = python3.7 +skip_install = true +basepython = python3.12 commands = isort --verbose --check-only --diff django_elastipymemcache tests setup.py deps = isort [testenv:readme] -basepython = python3.7 +skip_install = true +basepython = python3.12 commands = python setup.py check -r -s -deps = readme_renderer +deps = + setuptools + readme_renderer [testenv:check-manifest] -basepython = python3.7 +skip_install = true +basepython = python3.12 commands = check-manifest {toxinidir} deps = check-manifest