Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: do not check if tag registered just because it leads to difficulties #226

Merged
merged 1 commit into from
May 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ scalable and reliable applications. This library intends to make it easy to impl
- Client-side cache (10x faster than simple cache with redis)
- Bloom filters
- Different cache invalidation techniques (time-based or tags)
- Cache any objects securely with pickle (use [hash key](#redis))
- Cache any objects securely with pickle (use [secret](#redis))
- 2x faster than `aiocache` (with client side caching)

## Usage Example
Expand Down Expand Up @@ -84,9 +84,9 @@ More examples [here](https://github.com/Krukov/cashews/tree/master/examples)
from cashews import cache

# via url
cache.setup("redis://0.0.0.0/?db=1&socket_connect_timeout=0.5&suppress=0&hash_key=my_secret&enable=1")
cache.setup("redis://0.0.0.0/?db=1&socket_connect_timeout=0.5&suppress=0&secret=my_secret&enable=1")
# or via kwargs
cache.setup("redis://0.0.0.0/", db=1, wait_for_connection_timeout=0.5, suppress=False, hash_key=b"my_key", enable=True)
cache.setup("redis://0.0.0.0/", db=1, wait_for_connection_timeout=0.5, suppress=False, secret=b"my_key", enable=True)
```

Alternatively, you can create a cache instance yourself:
Expand Down Expand Up @@ -156,8 +156,8 @@ If you would like to use [client-side cache](https://redis.io/topics/client-side
Client side cache will add `cashews:` prefix for each key, to customize it use `client_side_prefix` option.

```python
cache.setup("redis://0.0.0.0/?db=1&minsize=10&suppress=false&hash_key=my_secret", prefix="func")
cache.setup("redis://0.0.0.0/2", password="my_pass", socket_connect_timeout=0.1, retry_on_timeout=True, hash_key="my_secret")
cache.setup("redis://0.0.0.0/?db=1&minsize=10&suppress=false&secret=my_secret", prefix="func")
cache.setup("redis://0.0.0.0/2", password="my_pass", socket_connect_timeout=0.1, retry_on_timeout=True, secret="my_secret")
cache.setup("redis://0.0.0.0", client_side=True, client_side_prefix="my_prefix:", pickle_type="dill")
```

Expand Down
5 changes: 3 additions & 2 deletions cashews/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from ._typing import KeyOrTemplate, KeyTemplate

TemplateValue = str
_re_special_chars_map = {i: "\\" + chr(i) for i in b"()[]?*+-|^$\\.&~# \t\n\r\v\f"}
_re_special_chars_map = {i: "\\" + chr(i) for i in b"()[]?*+-|^$\\&~# \t\n\r\v\f"}


def _decode_bytes(value: bytes):
Expand Down Expand Up @@ -164,7 +164,8 @@ def default_format(template: KeyTemplate, **values) -> KeyOrTemplate:


def _re_default(field_name):
return f"(?P<{field_name.replace('.', '_')}>.+)?"
field_name = field_name.split(".")[0]
return f"(?P<{field_name}>.+)?"


_re_formatter = _ReplaceFormatter(default=_re_default)
Expand Down
11 changes: 0 additions & 11 deletions cashews/wrapper/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from cashews._typing import TTL, Key, KeyOrTemplate, OnRemoveCallback, Tag, Tags, Value
from cashews.backends.interface import Backend
from cashews.exceptions import TagNotRegisteredError
from cashews.formatter import default_format, template_to_re_pattern

from .commands import CommandWrapper
Expand Down Expand Up @@ -36,14 +35,6 @@ def _match_patterns(key: Key, patterns: List[Pattern]) -> Optional[Match]:
return match
return None

def check_tags_registered(self, key: Key, tags: Tags):
tags = set(tags)
key_tags = set(self.get_key_tags(key))
difference = tags.difference(key_tags)

if difference:
raise TagNotRegisteredError(f"tag: {difference} not registered: call cache.register_tag before using tags")


class CommandsTagsWrapper(CommandWrapper):
def __init__(self, name: str = ""):
Expand Down Expand Up @@ -116,15 +107,13 @@ async def set(
) -> bool:
_set = await super().set(key=key, value=value, expire=expire, exist=exist)
if _set and tags:
self._tags_registry.check_tags_registered(key, tags)
for tag in tags:
await self.set_add(self._tags_key_prefix + tag, key, expire=expire)
return _set

async def incr(self, key: Key, value: int = 1, expire: Optional[float] = None, tags: Tags = ()) -> int:
_set = await super().incr(key=key, value=value, expire=expire)
if _set and tags:
self._tags_registry.check_tags_registered(key, tags)
for tag in tags:
await self.set_add(self._tags_key_prefix + tag, key, expire=expire)
return _set
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ async def _backend(request, redis_dsn, backend_factory):
backend = backend_factory(
Redis,
redis_dsn,
hash_key=None,
secret=None,
max_connections=20,
suppress=False,
socket_timeout=1,
Expand All @@ -80,7 +80,7 @@ async def _backend(request, redis_dsn, backend_factory):
backend = backend_factory(
Redis,
redis_dsn,
hash_key=uuid4().hex,
secret=uuid4().hex,
max_connections=20,
suppress=False,
socket_timeout=10,
Expand All @@ -92,7 +92,7 @@ async def _backend(request, redis_dsn, backend_factory):
backend = backend_factory(
BcastClientSide,
redis_dsn,
hash_key=None,
secret=None,
max_connections=5,
suppress=False,
socket_timeout=0.1,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_client_side_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def _create_cache(redis_dsn, backend_factory):
from cashews.backends.redis.client_side import BcastClientSide

async def call(local_cache=None):
backend = backend_factory(BcastClientSide, redis_dsn, hash_key=None, local_cache=local_cache)
backend = backend_factory(BcastClientSide, redis_dsn, secret=None, local_cache=local_cache)
await backend.init()
await backend.clear()
return backend
Expand Down
8 changes: 4 additions & 4 deletions tests/test_pickle_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ async def _cache(request, redis_dsn):
if pickle_type == "redis":
from cashews.backends.redis import Redis

redis = Redis(redis_dsn, hash_key="test", safe=False, digestmod=digestmod)
redis = Redis(redis_dsn, secret="test", safe=False, digestmod=digestmod)
await redis.init()
await redis.clear()
yield redis
await redis.close()
else:
yield Memory(hash_key=b"test", digestmod=digestmod, pickle_type=pickle_type)
yield Memory(secret=b"test", digestmod=digestmod, pickle_type=pickle_type)


@pytest.mark.parametrize(
Expand Down Expand Up @@ -271,7 +271,7 @@ async def test_no_hash(key, value):

async def test_cache_from_hash_to_no_hash():
val = Decimal("10.2")
cache = Memory(hash_key="test")
cache = Memory(secret="test")
await cache.set("key", val)

assert await cache.get("key") == val
Expand All @@ -286,7 +286,7 @@ async def test_cache_from_no_hash_to_hash():
await cache.set("key", val)

assert await cache.get("key") == val
cache_hash = Memory(hash_key="test")
cache_hash = Memory(secret="test")
cache_hash.store = cache.store

assert await cache_hash.get("key") == val
6 changes: 3 additions & 3 deletions tests/test_redis_down.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def redis_backend():


async def test_safe_redis(redis_backend):
redis = redis_backend(safe=True, address="redis://localhost:9223", hash_key=None)
redis = redis_backend(safe=True, address="redis://localhost:9223", secret=None)
await redis.init()

assert await redis.set("test", "test") is False
Expand Down Expand Up @@ -52,7 +52,7 @@ async def test_safe_redis(redis_backend):


async def test_unsafe_redis_down(redis_backend):
redis = redis_backend(safe=False, address="redis://localhost:9223", hash_key=None)
redis = redis_backend(safe=False, address="redis://localhost:9223", secret=None)
await redis.init()
with pytest.raises(CacheBackendInteractionError):
await redis.ping()
Expand All @@ -63,7 +63,7 @@ async def test_unsafe_redis_down(redis_backend):
async def test_cache_decorators_on_redis_down(redis_backend):
mock = Mock(return_value="val")
cache = Cache()
cache._add_backend(redis_backend(safe=True, address="redis://localhost:9223", hash_key=None))
cache._add_backend(redis_backend(safe=True, address="redis://localhost:9223", secret=None))

@cache(ttl=1)
@cache.failover(1)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_settings_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ def test_url_but_backend_dependency_is_not_installed(url, error):
},
),
(
"redis://localhost/0/?hash_key=secret&password=test&safe=1&minsize=3&create_connection_timeout=0.1", # noqa: E501
"redis://localhost/0/?secret=secret&password=test&safe=1&minsize=3&create_connection_timeout=0.1", # noqa: E501
{
"address": "redis://localhost/0/",
"hash_key": "secret",
"secret": "secret",
"password": "test",
"safe": True,
"minsize": 3,
Expand Down
16 changes: 16 additions & 0 deletions tests/test_tags_feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,19 @@ async def cached(
return f"{a}{b}"

assert await cached(1) == "1None"


async def test_template_tag_function(cache: Cache):
@cache(ttl="1m", key="{user.name:hash}:func", tags=["tag:{user.name}", "tag:{user.name:hash}"])
async def func(user):
return random()

class User:
def __init__(self, name):
self.name = name

def __hash__(self):
return hash(self.name)

await func(User("test"))
await cache.delete_tags("tag:test")
Loading