Skip to content

Commit

Permalink
Use pymemcache.MockMemcacheClient.
Browse files Browse the repository at this point in the history
  • Loading branch information
iurisilvio committed Aug 3, 2023
1 parent e0f4b30 commit b5bebd1
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 47 deletions.
25 changes: 23 additions & 2 deletions django_cache_mock/backends/memcached.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import logging
from functools import cached_property

import mockcache
from django.core.cache.backends.memcached import BaseMemcachedCache
from django.core.cache.backends.memcached import BaseMemcachedCache, PyMemcacheCache

logger = logging.getLogger(__name__)


class MockcacheCache(BaseMemcachedCache):
_dbs = {}

def __init__(self, server, params):
import mockcache

super().__init__(
server,
params,
Expand All @@ -30,3 +34,20 @@ def _cache(self):
client = super()._cache
client.dictionary = self._dbs.setdefault(self.location, {})
return client


class PyMemcacheMockMemcacheCache(PyMemcacheCache):
_dbs = {}

def __init__(self, server, params):
from pymemcache.test.utils import MockMemcacheClient

super().__init__(server, params)
self._class = MockMemcacheClient
self.location = server

@cached_property
def _cache(self):
client = super()._cache
client._contents = self._dbs.setdefault(self.location, {})
return client
43 changes: 15 additions & 28 deletions django_cache_mock/backends/redis.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,9 @@

from django.utils.functional import SimpleLazyObject

logger = logging.getLogger(__name__)

from django_cache_mock.exceptions import LazyLibImportError

class LazyRedisCacheImportError(Exception):
parent_exception = None

def __init__(self, server, params):
raise self from self.parent_exception
logger = logging.getLogger(__name__)


try:
Expand Down Expand Up @@ -42,7 +37,7 @@ def _cache(self):
except ImportError as _import_error:
logger.debug("Django built-in redis cache not found.")

class BaseDjangoBuiltInRedisCache(LazyRedisCacheImportError):
class BaseDjangoBuiltInRedisCache(LazyLibImportError):
parent_exception = _import_error


Expand Down Expand Up @@ -83,30 +78,22 @@ def client(self):
except ImportError as _import_error:
logger.debug("django-redis is not installed.")

class BaseDjangoRedisRedisCache(LazyRedisCacheImportError):
class BaseDjangoRedisRedisCache(LazyLibImportError):
parent_exception = _import_error


try:
import redislite

class RedisLiteMixin:
library = redislite
client_class = redislite.StrictRedis

def __init__(self, server, params):
self.dbfilename = server or "redislite.db"
super().__init__(server, params)

@property
def redis_client_cls_kwargs(self):
return {"dbfilename": self.dbfilename}
class RedisLiteMixin:
def __init__(self, server, params):
import redislite

except ImportError as _import_error:
logger.debug("redislite is not installed.")
self.library = redislite
self.client_class = redislite.StrictRedis
self.dbfilename = server or "redislite.db"
super().__init__(server, params)

class RedisLiteMixin(LazyRedisCacheImportError):
parent_exception = _import_error
@property
def redis_client_cls_kwargs(self):
return {"dbfilename": self.dbfilename}


try:
Expand All @@ -127,7 +114,7 @@ def redis_client_cls_kwargs(self):
except ImportError as _import_error:
logger.debug("fakeredis is not installed.")

class FakeRedisMixin(LazyRedisCacheImportError):
class FakeRedisMixin(LazyLibImportError):
parent_exception = _import_error


Expand Down
5 changes: 5 additions & 0 deletions django_cache_mock/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class LazyLibImportError(Exception):
parent_exception = None

def __init__(self, server, params):
raise self from self.parent_exception
7 changes: 4 additions & 3 deletions django_cache_mock/mock.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging

SUPPORTED_BACKENDS = {
"pymemcache": "django_cache_mock.backends.memcached.PyMemcacheMockMemcacheCache",
"mockcache": "django_cache_mock.backends.memcached.MockcacheCache",
"fakeredis": "django_cache_mock.backends.redis.FakeRedisCache",
"redislite": "django_cache_mock.backends.redis.RedisLiteCache",
Expand All @@ -15,8 +16,8 @@
logger = logging.getLogger(__name__)


def patch(caches, cache_alias, backend, params=None, *, force=False):
current_config = caches[cache_alias]
def patch(caches_config, cache_alias, backend, params=None, *, force=False):
current_config = caches_config[cache_alias]
current_location = current_config.get("LOCATION")

if params is None:
Expand All @@ -32,7 +33,7 @@ def patch(caches, cache_alias, backend, params=None, *, force=False):
params["BACKEND"] = SUPPORTED_BACKENDS[backend]
logger.info(f"Cache {cache_alias} mocked with {backend}.")
logger.debug(f"{params=}.")
caches[cache_alias] = params
caches_config[cache_alias] = params
return True


Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ packages = [{include = "django_cache_mock"}]
[tool.poetry.dependencies]
python = "^3.8"
django = "^3 || ^4"
mockcache3 = { version = "*", optional = true }
pymemcache = { version = "*", optional = true }
mockcache3 = { version = "^2", optional = true }
fakeredis = { version = "*", optional = true }
redislite = { version = "*", optional = true }
django-redis = { version = "*", optional = true }
Expand All @@ -21,6 +22,7 @@ pytest-cov = "*"
pytest-ruff = "*"

[tool.poetry.extras]
pymemcache = ["pymemcache"]
mockcache = ["mockcache3"]
fakeredis = ["fakeredis"]
redislite = ["redislite"]
Expand Down
4 changes: 2 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def cache_alias(request):

def _validate_backend_installed(cache_alias):
# Import at root level trigger https://github.com/jazzband/django-redis/issues/638.
from django_cache_mock.backends.redis import LazyRedisCacheImportError
from django_cache_mock.exceptions import LazyLibImportError

backend_module, backend_class = CACHES[cache_alias]["BACKEND"].rsplit(".", 1)
try:
Expand All @@ -28,7 +28,7 @@ def _validate_backend_installed(cache_alias):
return False

backend = getattr(module, backend_class)
if issubclass(backend, LazyRedisCacheImportError):
if issubclass(backend, LazyLibImportError):
return False

return True
Expand Down
12 changes: 4 additions & 8 deletions tests/test_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.conf import settings
from django.core.cache import InvalidCacheBackendError, caches

from django_cache_mock.exceptions import LazyLibImportError
from tests.thread_with_exceptions import Thread


Expand Down Expand Up @@ -38,19 +39,17 @@ def test_server_name(cache_alias_installed, tmp_path):
pass
cache = caches[cache_alias]
assert cache.location == location

cache.set("FOO", "BAR")
assert cache.get("FOO") == "BAR"


def test_not_implemented_exception():
# Import at root level trigger https://github.com/jazzband/django-redis/issues/638.
from django_cache_mock.backends.redis import LazyRedisCacheImportError

try:
1 / 0
except ZeroDivisionError as _exc:

class MyError(LazyRedisCacheImportError):
class MyError(LazyLibImportError):
exception = _exc

with pytest.raises(MyError) as exception_info:
Expand All @@ -61,13 +60,10 @@ class MyError(LazyRedisCacheImportError):


def test_redis_import_error(redis_cache_alias_not_installed):
# Import at root level trigger https://github.com/jazzband/django-redis/issues/638.
from django_cache_mock.backends.redis import LazyRedisCacheImportError

cache_alias = redis_cache_alias_not_installed
try:
caches[cache_alias]
except LazyRedisCacheImportError:
except LazyLibImportError:
pass
else: # pragma: no cover
pytest.fail("Cache unexpectedly worked.")
Expand Down
13 changes: 10 additions & 3 deletions tests/test_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,26 @@ def test_custom_params():
def test_use_django_builtin_redis_based_on_backend(redis_backend):
caches = {"default": {"BACKEND": "django.core.cache.backends.redis.RedisCache"}}
patch(caches, "default", redis_backend)
assert caches["default"]["BACKEND"] == SUPPORTED_BACKENDS[redis_backend]
expected_backend = SUPPORTED_BACKENDS[redis_backend]
assert caches["default"] == {
"BACKEND": expected_backend,
}


def test_use_django_redis_based_on_backend(redis_backend):
caches = {"default": {"BACKEND": "django_redis.cache.RedisCache"}}
patch(caches, "default", redis_backend)
expected_backend = SUPPORTED_BACKENDS[f"{redis_backend}[django-redis]"]
assert caches["default"]["BACKEND"] == expected_backend
assert caches["default"] == {
"BACKEND": expected_backend,
}


def test_use_django_redis_explicit(redis_backend):
caches = {"default": {}}
explicit_django_redis_backend = f"{redis_backend}[django-redis]"
patch(caches, "default", explicit_django_redis_backend)
expected_backend = SUPPORTED_BACKENDS[explicit_django_redis_backend]
assert caches["default"]["BACKEND"] == expected_backend
assert caches["default"] == {
"BACKEND": expected_backend,
}

0 comments on commit b5bebd1

Please sign in to comment.