diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9500530f..8bc3a829 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -124,8 +124,7 @@ jobs: matrix: tool: - 'black' - - 'flake8' - - 'isort' + - 'ruff' - 'mypy' steps: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f177968b..dd43f432 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,22 +9,15 @@ repos: - id: check-symlinks - id: debug-statements -- repo: https://github.com/asottile/pyupgrade - rev: v3.15.0 +# from readme - ruff with autofix must run before +# other formatters, such as black +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.0.292 hooks: - - id: pyupgrade + - id: ruff + args: [ --fix, --exit-non-zero-on-fix , --show-fixes] - repo: https://github.com/psf/black rev: 23.9.1 hooks: - id: black - -- repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 - hooks: - - id: flake8 - -- repo: https://github.com/PyCQA/isort - rev: 5.12.0 - hooks: - - id: isort diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 00000000..9c85337e --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,139 @@ +# https://beta.ruff.rs/docs/rules/ +select = [ + # rules from pyflakes + "F", + + # rules from pycodestyle + "E", "W", + + # rules from mccabe + "C90", + + # rules from isort + "I", + + # rules from pyupgrade + "UP", + + # rules from flake8-2020 + "YTT", + + # rules from flake8-annotations +# "ANN", + + # rules from flake8-bandit + "S", + + # rules from flake8-blind-except + "BLE", + + # rules from flake8-boolean-trap + # TODO: "FBT", + + # rules from flake8-bugbear + "B", + + # rules from flake8-builtins + "A", + + # rules from flake8-commas + "COM", + + # rules from flake8-comprehensions + "C4", + + # rules from flake8-datetimez + # TODO: "DTZ", + + # rules from flake8-debugger + "T10", + + # rules from flake8-django + "DJ", + + # rules from flake8-errmsg + "EM", + + # rules from flake8-executable + "EXE", + + # rules from flake8-implicit-str-concat + "ISC", + + # rules from flake8-import-conventions + "ICN", + + # rules from flake8-logging-format + "G", + + # rules from flake8-no-pep420 + "INP", + + # rules from flake8-pie + # TODO: "PIE", + + # rules from flake8-print + "T20", + + # rules from flake8-pyi + "PYI", + + # rules from flake8-pytest-style + # TODO: "PT", + + # rules from flake8-raise + "RSE", + + # rules from flake8-return + "RET", + + # rules from flake8-self + # TODO: "SLF", + + # rules from flake8-simplify + "SIM", + + # rules from flake8-tidy-imports + "TID", + + # rules from flake8-type-checking + "TCH", + + # rules from flake8-gettext + "INT", + + # rules from flake8-unused-arguments + # TODO: "ARG", + + # rules from flake8-use-pathlib + "PTH", + + # removes unused noqa comments + "RUF100", +] + +ignore = [ + "COM812", # missing trailing comma, covered by black + "ANN101", # ignore missing type annotation in self parameter + "S311", # ignore Standard pseudo-random generators because they are not used for cryptographic purposes +] + +fix = true + +# TODO: enable this when python3.6 will stop being supported, +# from april 2024 https://docs.djangoproject.com/en/4.2/releases/3.2/ +#target-version = "py36" + +[flake8-tidy-imports] +## Disallow all relative imports. +ban-relative-imports = "all" + +[per-file-ignores] +# ignore assert statements in tests +"tests/*.py" = ["S101"] + +# ignore SECRET_KEY in settings files in tests +"tests/settings/*.py" = ["S105"] + +# pickle is used on purpose and its use is discouraged +"django_redis/serializers/pickle.py" = ["S301"] diff --git a/changelog.d/692.misc b/changelog.d/692.misc new file mode 100644 index 00000000..2083a1a7 --- /dev/null +++ b/changelog.d/692.misc @@ -0,0 +1 @@ +Replace isort and flake8 with ruff \ No newline at end of file diff --git a/django_redis/__init__.py b/django_redis/__init__.py index 7157dc68..579f1d44 100644 --- a/django_redis/__init__.py +++ b/django_redis/__init__.py @@ -11,10 +11,11 @@ def get_redis_connection(alias="default", write=True): cache = caches[alias] + error_message = "This backend does not support this feature" if not hasattr(cache, "client"): - raise NotImplementedError("This backend does not support this feature") + raise NotImplementedError(error_message) if not hasattr(cache.client, "get_client"): - raise NotImplementedError("This backend does not support this feature") + raise NotImplementedError(error_message) return cache.client.get_client(write) diff --git a/django_redis/cache.py b/django_redis/cache.py index 0b4d5890..732ca9df 100644 --- a/django_redis/cache.py +++ b/django_redis/cache.py @@ -7,7 +7,7 @@ from django.core.cache.backends.base import BaseCache from django.utils.module_loading import import_string -from .exceptions import ConnectionInterrupted +from django_redis.exceptions import ConnectionInterrupted CONNECTION_INTERRUPTED = object() @@ -33,7 +33,7 @@ def _decorator(self, *args, **kwargs): self.logger.exception("Exception ignored") return return_value - raise e.__cause__ + raise e.__cause__ # noqa: B904 return _decorator @@ -77,7 +77,7 @@ def client(self): return self._client @omit_exception - def set(self, *args, **kwargs): + def set(self, *args, **kwargs): # noqa: A003 return self.client.set(*args, **kwargs) @omit_exception diff --git a/django_redis/client/__init__.py b/django_redis/client/__init__.py index ba40c4a8..d8e7fe54 100644 --- a/django_redis/client/__init__.py +++ b/django_redis/client/__init__.py @@ -1,6 +1,6 @@ -from .default import DefaultClient -from .herd import HerdClient -from .sentinel import SentinelClient -from .sharded import ShardClient +from django_redis.client.default import DefaultClient +from django_redis.client.herd import HerdClient +from django_redis.client.sentinel import SentinelClient +from django_redis.client.sharded import ShardClient __all__ = ["DefaultClient", "HerdClient", "SentinelClient", "ShardClient"] diff --git a/django_redis/client/default.py b/django_redis/client/default.py index 6886b46b..15a5067a 100644 --- a/django_redis/client/default.py +++ b/django_redis/client/default.py @@ -2,6 +2,7 @@ import re import socket from collections import OrderedDict +from contextlib import suppress from datetime import datetime from typing import Any, Dict, Iterator, List, Optional, Union @@ -12,9 +13,9 @@ from redis import Redis from redis.exceptions import ConnectionError, ResponseError, TimeoutError -from .. import pool -from ..exceptions import CompressorError, ConnectionInterrupted -from ..util import CacheKey +from django_redis import pool +from django_redis.exceptions import CompressorError, ConnectionInterrupted +from django_redis.util import CacheKey _main_exceptions = (TimeoutError, ResponseError, ConnectionError, socket.timeout) @@ -37,7 +38,8 @@ def __init__(self, server, params: Dict[str, Any], backend: BaseCache) -> None: ) if not self._server: - raise ImproperlyConfigured("Missing connections string") + error_message = "Missing connections string" + raise ImproperlyConfigured(error_message) if not isinstance(self._server, (list, tuple, set)): self._server = self._server.split(",") @@ -75,7 +77,7 @@ def get_next_client_index( behavior. """ if tried is None: - tried = list() + tried = [] if tried and len(tried) < len(self._server): not_tried = [i for i in range(0, len(self._server)) if i not in tried] @@ -106,8 +108,8 @@ def get_client( if show_index: return self._clients[index], index - else: - return self._clients[index] + + return self._clients[index] def connect(self, index: int = 0) -> Redis: """ @@ -123,7 +125,7 @@ def disconnect(self, index=0, client=None): client = self._clients[index] return self.connection_factory.disconnect(client) if client else None - def set( + def set( # noqa: A003 self, key: Any, value: Any, @@ -164,13 +166,11 @@ def set( # not expire (in our case delete) the value if it exists. # Obviously expire not existent value is noop. return not self.has_key(key, version=version, client=client) - else: - # redis doesn't support negative timeouts in ex flags - # so it seems that it's better to just delete the key - # than to set it and than expire in a pipeline - return bool( - self.delete(key, client=client, version=version) - ) + + # redis doesn't support negative timeouts in ex flags + # so it seems that it's better to just delete the key + # than to set it and than expire in a pipeline + return bool(self.delete(key, client=client, version=version)) return bool(client.set(nkey, nvalue, nx=nx, px=timeout, xx=xx)) except _main_exceptions as e: @@ -417,7 +417,7 @@ def delete_many( keys = [self.make_key(k, version=version) for k in keys] if not keys: - return + return None try: return client.delete(*keys) @@ -444,11 +444,9 @@ def decode(self, value: Union[bytes, int]) -> Any: try: value = int(value) except (ValueError, TypeError): - try: + # Handle little values, chosen to be not compressed + with suppress(CompressorError): value = self._compressor.decompress(value) - except CompressorError: - # Handle little values, chosen to be not compressed - pass value = self._serializer.loads(value) return value @@ -459,8 +457,7 @@ def encode(self, value: Any) -> Union[bytes, Any]: if isinstance(value, bool) or not isinstance(value, int): value = self._serializer.dumps(value) - value = self._compressor.compress(value) - return value + return self._compressor.compress(value) return value @@ -548,8 +545,9 @@ def _incr( """ value = client.eval(lua, 1, key, delta) if value is None: - raise ValueError("Key '%s' not found" % key) - except ResponseError: + error_message = f"Key '{key}' not found" + raise ValueError(error_message) + except ResponseError as e: # if cached value or total value is greater than 64 bit signed # integer. # elif int is encoded. so redis sees the data as string. @@ -561,7 +559,8 @@ def _incr( # returns -2 if the key does not exist # means, that key have expired if timeout == -2: - raise ValueError("Key '%s' not found" % key) + error_message = f"Key '{key}' not found" + raise ValueError(error_message) from e value = self.get(key, version=version, client=client) + delta self.set(key, value, version=version, timeout=timeout, client=client) except _main_exceptions as e: @@ -621,13 +620,13 @@ def ttl( if t >= 0: return t - elif t == -1: + if t == -1: return None - elif t == -2: + if t == -2: return 0 - else: - # Should never reach here - return None + + # Should never reach here + return None def pttl(self, key, version=None, client=None): """ @@ -645,13 +644,13 @@ def pttl(self, key, version=None, client=None): if t >= 0: return t - elif t == -1: + if t == -1: return None - elif t == -2: + if t == -2: return 0 - else: - # Should never reach here - return None + + # Should never reach here + return None def has_key( self, key: Any, version: Optional[int] = None, client: Optional[Redis] = None @@ -737,7 +736,7 @@ def make_pattern( return CacheKey(self._backend.key_func(pattern, prefix, version_str)) - def close(self, **kwargs): + def close(self): close_flag = self._options.get( "CLOSE_CONNECTION", getattr(settings, "DJANGO_REDIS_CLOSE_CONNECTION", False), @@ -772,7 +771,7 @@ def touch( key = self.make_key(key, version=version) if timeout is None: return bool(client.persist(key)) - else: - # Convert to milliseconds - timeout = int(timeout * 1000) - return bool(client.pexpire(key, timeout)) + + # Convert to milliseconds + timeout = int(timeout * 1000) + return bool(client.pexpire(key, timeout)) diff --git a/django_redis/client/herd.py b/django_redis/client/herd.py index 0c52480f..70cb0459 100644 --- a/django_redis/client/herd.py +++ b/django_redis/client/herd.py @@ -6,8 +6,8 @@ from django.conf import settings from redis.exceptions import ConnectionError, ResponseError, TimeoutError -from ..exceptions import ConnectionInterrupted -from .default import DEFAULT_TIMEOUT, DefaultClient +from django_redis.client.default import DEFAULT_TIMEOUT, DefaultClient +from django_redis.exceptions import ConnectionInterrupted _main_exceptions = (ConnectionError, ResponseError, TimeoutError, socket.timeout) @@ -57,7 +57,7 @@ def _unpack(self, value): return unpacked, False - def set( + def set( # noqa: A003 self, key, value, @@ -147,10 +147,10 @@ def set_many( raise ConnectionInterrupted(connection=client) from e def incr(self, *args, **kwargs): - raise NotImplementedError() + raise NotImplementedError def decr(self, *args, **kwargs): - raise NotImplementedError() + raise NotImplementedError def touch(self, key, timeout=DEFAULT_TIMEOUT, version=None, client=None): if client is None: diff --git a/django_redis/client/sentinel.py b/django_redis/client/sentinel.py index 709f4e53..d4f418dc 100644 --- a/django_redis/client/sentinel.py +++ b/django_redis/client/sentinel.py @@ -3,7 +3,7 @@ from django.core.exceptions import ImproperlyConfigured from redis.sentinel import SentinelConnectionPool -from .default import DefaultClient +from django_redis.client.default import DefaultClient def replace_query(url, query): @@ -33,9 +33,10 @@ def __init__(self, server, params, backend): def connect(self, *args, **kwargs): connection = super().connect(*args, **kwargs) if not isinstance(connection.connection_pool, SentinelConnectionPool): - raise ImproperlyConfigured( + error_message = ( "Settings DJANGO_REDIS_CONNECTION_FACTORY or " "CACHE[].OPTIONS.CONNECTION_POOL_CLASS is not configured correctly." ) + raise ImproperlyConfigured(error_message) return connection diff --git a/django_redis/client/sharded.py b/django_redis/client/sharded.py index a30e177e..7c34e6e7 100644 --- a/django_redis/client/sharded.py +++ b/django_redis/client/sharded.py @@ -5,10 +5,10 @@ from redis.exceptions import ConnectionError -from ..exceptions import ConnectionInterrupted -from ..hash_ring import HashRing -from ..util import CacheKey -from .default import DEFAULT_TIMEOUT, DefaultClient +from django_redis.client.default import DEFAULT_TIMEOUT, DefaultClient +from django_redis.exceptions import ConnectionInterrupted +from django_redis.hash_ring import HashRing +from django_redis.util import CacheKey class ShardClient(DefaultClient): @@ -37,8 +37,7 @@ def get_server_name(self, _key): g = self._findhash.match(key) if g is not None and len(g.groups()) > 0: key = g.groups()[0] - name = self._ring.get_node(key) - return name + return self._ring.get_node(key) def get_server(self, key): name = self.get_server_name(key) @@ -79,7 +78,7 @@ def get_many(self, keys, version=None): recovered_data[map_keys[key]] = value return recovered_data - def set( + def set( # noqa: A003 self, key, value, timeout=DEFAULT_TIMEOUT, version=None, client=None, nx=False ): """ @@ -272,13 +271,14 @@ def decr(self, key, delta=1, version=None, client=None): return super().decr(key=key, delta=delta, version=version, client=client) def iter_keys(self, key, version=None): - raise NotImplementedError("iter_keys not supported on sharded client") + error_message = "iter_keys not supported on sharded client" + raise NotImplementedError(error_message) def keys(self, search, version=None): pattern = self.make_pattern(search, version=version) keys = [] try: - for server, connection in self._serverdict.items(): + for connection in self._serverdict.values(): keys.extend(connection.keys(pattern)) except ConnectionError as e: # FIXME: technically all clients should be passed as `connection`. @@ -299,12 +299,12 @@ def delete_pattern( kwargs["count"] = itersize keys = [] - for server, connection in self._serverdict.items(): + for connection in self._serverdict.values(): keys.extend(key for key in connection.scan_iter(**kwargs)) res = 0 if keys: - for server, connection in self._serverdict.items(): + for connection in self._serverdict.values(): res += connection.delete(*keys) return res diff --git a/django_redis/compressors/identity.py b/django_redis/compressors/identity.py index 4946886f..c7114203 100644 --- a/django_redis/compressors/identity.py +++ b/django_redis/compressors/identity.py @@ -1,4 +1,4 @@ -from .base import BaseCompressor +from django_redis.compressors.base import BaseCompressor class IdentityCompressor(BaseCompressor): diff --git a/django_redis/compressors/lz4.py b/django_redis/compressors/lz4.py index ffcd4794..32183321 100644 --- a/django_redis/compressors/lz4.py +++ b/django_redis/compressors/lz4.py @@ -1,8 +1,8 @@ from lz4.frame import compress as _compress from lz4.frame import decompress as _decompress -from ..exceptions import CompressorError -from .base import BaseCompressor +from django_redis.compressors.base import BaseCompressor +from django_redis.exceptions import CompressorError class Lz4Compressor(BaseCompressor): @@ -16,5 +16,5 @@ def compress(self, value: bytes) -> bytes: def decompress(self, value: bytes) -> bytes: try: return _decompress(value) - except Exception as e: - raise CompressorError(e) + except Exception as e: # noqa: BLE001 + raise CompressorError from e diff --git a/django_redis/compressors/lzma.py b/django_redis/compressors/lzma.py index b8c17bcf..1ab1a024 100644 --- a/django_redis/compressors/lzma.py +++ b/django_redis/compressors/lzma.py @@ -1,7 +1,7 @@ import lzma -from ..exceptions import CompressorError -from .base import BaseCompressor +from django_redis.compressors.base import BaseCompressor +from django_redis.exceptions import CompressorError class LzmaCompressor(BaseCompressor): @@ -17,4 +17,4 @@ def decompress(self, value: bytes) -> bytes: try: return lzma.decompress(value) except lzma.LZMAError as e: - raise CompressorError(e) + raise CompressorError from e diff --git a/django_redis/compressors/zlib.py b/django_redis/compressors/zlib.py index 014fc77e..98767325 100644 --- a/django_redis/compressors/zlib.py +++ b/django_redis/compressors/zlib.py @@ -1,7 +1,7 @@ import zlib -from ..exceptions import CompressorError -from .base import BaseCompressor +from django_redis.compressors.base import BaseCompressor +from django_redis.exceptions import CompressorError class ZlibCompressor(BaseCompressor): @@ -17,4 +17,4 @@ def decompress(self, value: bytes) -> bytes: try: return zlib.decompress(value) except zlib.error as e: - raise CompressorError(e) + raise CompressorError from e diff --git a/django_redis/compressors/zstd.py b/django_redis/compressors/zstd.py index ddf49d0d..82a09187 100644 --- a/django_redis/compressors/zstd.py +++ b/django_redis/compressors/zstd.py @@ -1,7 +1,7 @@ import pyzstd -from ..exceptions import CompressorError -from .base import BaseCompressor +from django_redis.compressors.base import BaseCompressor +from django_redis.exceptions import CompressorError class ZStdCompressor(BaseCompressor): @@ -16,4 +16,4 @@ def decompress(self, value: bytes) -> bytes: try: return pyzstd.decompress(value) except pyzstd.ZstdError as e: - raise CompressorError(e) + raise CompressorError from e diff --git a/django_redis/pool.py b/django_redis/pool.py index c5704076..979c463c 100644 --- a/django_redis/pool.py +++ b/django_redis/pool.py @@ -48,16 +48,16 @@ def make_connection_params(self, url): socket_timeout = self.options.get("SOCKET_TIMEOUT", None) if socket_timeout: - assert isinstance( - socket_timeout, (int, float) - ), "Socket timeout should be float or integer" + if not isinstance(socket_timeout, (int, float)): + error_message = "Socket timeout should be float or integer" + raise ImproperlyConfigured(error_message) kwargs["socket_timeout"] = socket_timeout socket_connect_timeout = self.options.get("SOCKET_CONNECT_TIMEOUT", None) if socket_connect_timeout: - assert isinstance( - socket_connect_timeout, (int, float) - ), "Socket connect timeout should be float or integer" + if not isinstance(socket_connect_timeout, (int, float)): + error_message = "Socket connect timeout should be float or integer" + raise ImproperlyConfigured(error_message) kwargs["socket_connect_timeout"] = socket_connect_timeout return kwargs @@ -68,8 +68,7 @@ def connect(self, url: str) -> Redis: return a new connection. """ params = self.make_connection_params(url) - connection = self.get_connection(params) - return connection + return self.get_connection(params) def disconnect(self, connection): """ @@ -140,9 +139,8 @@ def __init__(self, options): sentinels = options.get("SENTINELS") if not sentinels: - raise ImproperlyConfigured( - "SENTINELS must be provided as a list of (host, port)." - ) + error_message = "SENTINELS must be provided as a list of (host, port)." + raise ImproperlyConfigured(error_message) # provide the connection pool kwargs to the sentinel in case it # needs to use the socket options for the sentinels themselves diff --git a/django_redis/serializers/json.py b/django_redis/serializers/json.py index 06e62542..8be9bb29 100644 --- a/django_redis/serializers/json.py +++ b/django_redis/serializers/json.py @@ -3,7 +3,7 @@ from django.core.serializers.json import DjangoJSONEncoder -from .base import BaseSerializer +from django_redis.serializers.base import BaseSerializer class JSONSerializer(BaseSerializer): diff --git a/django_redis/serializers/msgpack.py b/django_redis/serializers/msgpack.py index d41591f6..6af58a67 100644 --- a/django_redis/serializers/msgpack.py +++ b/django_redis/serializers/msgpack.py @@ -2,7 +2,7 @@ import msgpack -from .base import BaseSerializer +from django_redis.serializers.base import BaseSerializer class MSGPackSerializer(BaseSerializer): diff --git a/django_redis/serializers/pickle.py b/django_redis/serializers/pickle.py index c304360d..e63d3c9a 100644 --- a/django_redis/serializers/pickle.py +++ b/django_redis/serializers/pickle.py @@ -3,7 +3,7 @@ from django.core.exceptions import ImproperlyConfigured -from .base import BaseSerializer +from django_redis.serializers.base import BaseSerializer class PickleSerializer(BaseSerializer): @@ -18,12 +18,14 @@ def setup_pickle_version(self, options) -> None: try: self._pickle_version = int(options["PICKLE_VERSION"]) if self._pickle_version > pickle.HIGHEST_PROTOCOL: - raise ImproperlyConfigured( + error_message = ( f"PICKLE_VERSION can't be higher than pickle.HIGHEST_PROTOCOL:" f" {pickle.HIGHEST_PROTOCOL}" ) - except (ValueError, TypeError): - raise ImproperlyConfigured("PICKLE_VERSION value must be an integer") + raise ImproperlyConfigured(error_message) + except (ValueError, TypeError) as e: + error_message = "PICKLE_VERSION value must be an integer" + raise ImproperlyConfigured(error_message) from e def dumps(self, value: Any) -> bytes: return pickle.dumps(value, self._pickle_version) diff --git a/setup.cfg b/setup.cfg index fa2d0f50..77582ff1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -53,23 +53,11 @@ omit = precision = 1 skip_covered = true -[flake8] -ignore = - W503 - W601 - E203 -max-line-length = 88 - -[isort] -profile = black -multi_line_output = 3 - [tox:tox] minversion = 3.15.0 envlist = black - flake8 - isort + ruff mypy # tests against released versions py{36,37,38,39,310,311}-dj{22,31,32,41,42}-redislatest @@ -81,7 +69,7 @@ envlist = python = 3.6: py36 3.7: py37 - 3.8: py38, black, flake8, isort, mypy + 3.8: py38, black, ruff, mypy 3.9: py39 3.10: py310 3.11: py311 @@ -128,19 +116,17 @@ deps = lz4>=0.15 pyzstd>=0.15 -[testenv:{black,flake8,isort,mypy}] +[testenv:{black,ruff,mypy}] basepython = python3 envdir={toxworkdir}/lint commands = black: black --target-version py36 {posargs:--check --diff} setup.py django_redis/ tests/ - flake8: flake8 {posargs} setup.py django_redis/ tests/ - isort: isort {posargs:--check-only --diff} django_redis/ tests/ + ruff: ruff {posargs:check --show-fixes} django_redis/ tests/ mypy: mypy {posargs:--cobertura-xml-report .} django_redis tests deps = black django-stubs - flake8 - isort >= 5.0.2 + ruff lxml mypy # typing dependencies diff --git a/tests/settings/__init__.py b/tests/settings/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_hashring.py b/tests/test_hashring.py index b890adb7..42f5b9ff 100644 --- a/tests/test_hashring.py +++ b/tests/test_hashring.py @@ -4,14 +4,14 @@ class Node: - def __init__(self, id): - self.id = id + def __init__(self, identifier): + self.identifier = identifier def __str__(self): - return f"node:{self.id}" + return f"node:{self.identifier}" def __repr__(self): - return f"" + return f"" @pytest.fixture @@ -24,7 +24,7 @@ def test_hashring(hash_ring): for key in [f"test{x}" for x in range(10)]: node = hash_ring.get_node(key) - ids.append(node.id) + ids.append(node.identifier) assert ids == [0, 2, 1, 2, 2, 2, 2, 0, 1, 1] diff --git a/tests/test_session.py b/tests/test_session.py index 36745035..bcea9c39 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -369,7 +369,7 @@ class SessionTests(SessionTestsMixin, unittest.TestCase): @pytest.mark.skipif( django.VERSION >= (4, 2), - reason="PickleSerializer is removed as of https://code.djangoproject.com/ticket/29708", # noqa: E501 + reason="PickleSerializer is removed as of https://code.djangoproject.com/ticket/29708", ) def test_actual_expiry(self): if isinstance(