Skip to content

Commit

Permalink
complete dt test
Browse files Browse the repository at this point in the history
  • Loading branch information
Ed-XCF committed Nov 29, 2022
1 parent 55b4bde commit 4805b24
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 27 deletions.
58 changes: 36 additions & 22 deletions redis_property.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
import json
from threading import RLock
from contextvars import ContextVar
from datetime import datetime

import orjson
from redis import Redis, RedisError

__all__ = ["redis_property"]
__all__ = ["redis_property", "cache_ttl", "cache_disable"]

_redis_cli = None
_default_ttl = 24 * 60 * 60
_disable = False
_default_cache_ttl = 24 * 60 * 60
_default_cache_disable = False

cache_ttl: ContextVar[int] = ContextVar('cache_ttl', default=_default_cache_ttl)
cache_disable: ContextVar[bool] = ContextVar('cache_disable', default=_default_cache_disable)

def _default_key(obj, func):

def _key_maker(obj, func):
return type(obj).__name__ + func.__name__


def configure(url, default_key=None, default_ttl=_default_ttl, disable=_disable):
def configure(url, *, key_maker=None, ttl=None, disable=None):
global _redis_cli
_redis_cli = Redis.from_url(url)

global _default_ttl
_default_ttl = default_ttl
if key_maker is not None:
global _key_maker # noqa
_key_maker = key_maker

if ttl is not None:
cache_ttl.set(ttl)

if default_key is not None:
global _default_key # noqa
_default_key = default_key

global _disable
_disable = disable
if disable is not None:
cache_disable.set(disable)


def assert_redis_cli_exists():
Expand All @@ -42,7 +47,7 @@ def safe_read(key):
if value is None:
return

return value.decode("utf-8")
return value.decode()


def safe_write(key, value, ttl):
Expand All @@ -64,17 +69,17 @@ def __init__(self, seconds, key=None):
assert_redis_cli_exists()

if callable(seconds):
self.func, self.ttl = seconds, _default_ttl
self.func, self.ttl = seconds, cache_ttl.get()
else:
self.func, self.ttl = None, seconds

self._key = key or _default_key
self._key = key or _key_maker
self._copy_func_info()
self.lock = RLock()

def __call__(self, func):
if self.func is not None:
if _disable:
if cache_disable.get():
return self.func(func)

return self.__get__(func, None)
Expand All @@ -96,7 +101,7 @@ def _copy_func_info(self):
setattr(self, member_name, value)

def __get__(self, instance, _):
if _disable:
if cache_disable.get():
return self.func(instance)

if instance is None:
Expand All @@ -119,9 +124,18 @@ def __get__(self, instance, _):
def __delete__(self, instance):
key = self._make_key(instance)
safe_remove(key)

_dumps = staticmethod(json.dumps)
_loads = staticmethod(json.loads)

@staticmethod
def _dumps(value):
return orjson.dumps(value).decode()

@staticmethod
def _loads(value):
data = orjson.loads(value)
try:
return datetime.fromisoformat(data)
except (TypeError, ValueError):
return data

def _make_key(self, obj):
return str(self._key(obj, self.func) if callable(self._key) else self._key)
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
redis
orjson
94 changes: 89 additions & 5 deletions test_redis_property.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import random
from datetime import datetime, timedelta
from copy import deepcopy

from cached_property import cached_property

import redis_property as redis_property_lib
from redis_property import redis_property
from redis_property import redis_property, cache_disable


class TestRedisProperty:
def setup_class(self):
redis_property_lib.configure(
"redis://:@127.0.0.1:6379/0",
lambda o, f: f"{type(o).__name__}:{o.id}:{f.__name__}"
key_maker=lambda o, f: f"{type(o).__name__}:{o.id}:{f.__name__}",
disable=False,
)

def test_work_alone(self):
Expand All @@ -30,7 +33,7 @@ def number(self):
del adder.number
assert adder.number == 3
del adder.number

def test_work_alone_with_ttl(self):
class Adder:
id = random.randint(1, 1000)
Expand Down Expand Up @@ -66,11 +69,50 @@ def number(self):
assert adder.number == adder.number


class TestRedisPropertyWithContextVar:
def setup_class(self):
redis_property_lib.configure(
"redis://:@127.0.0.1:6379/0",
key_maker=lambda o, f: f"{type(o).__name__}:{o.id}:{f.__name__}",
disable=False,
)

def test_work_with_cache_disable(self):
class Adder:
id = random.randint(1, 1000)

def __init__(self):
self.times = 1

@redis_property
def number(self):
self.times += 1
return self.times

adder = Adder()
assert adder.number == adder.number
del adder.number
assert adder.number == 3
del adder.number

cache_disable.set(True)
assert adder.number != adder.number
del adder.number
assert adder.number == 6
del adder.number

cache_disable.set(False)
assert adder.number == adder.number
del adder.number
assert adder.number == 8
del adder.number


class TestDisabledRedisProperty:
def setup_class(self):
redis_property_lib.configure(
"redis://:@127.0.0.1:6379/0",
lambda o, f: f"{type(o).__name__}:{o.id}:{f.__name__}",
key_maker=lambda o, f: f"{type(o).__name__}:{o.id}:{f.__name__}",
disable=True,
)

Expand All @@ -91,7 +133,7 @@ def number(self):
del adder.number
assert adder.number == 4
del adder.number

def test_work_alone_with_ttl(self):
class Adder:
id = random.randint(1, 1000)
Expand Down Expand Up @@ -125,3 +167,45 @@ def number(self):

adder = Adder()
assert adder.number == adder.number


class TestRedisPropertyDatetime:
def setup_class(self):
redis_property_lib.configure(
"redis://:@127.0.0.1:6379/0",
key_maker=lambda o, f: f"{type(o).__name__}:{o.id}:{f.__name__}",
disable=False,
)
print(cache_disable.get())

def test_work_for_datetime(self):
now = datetime.now()

class Adder:
id = random.randint(1, 1000)

def __init__(self):
self.now = deepcopy(now)

@redis_property
def current(self):
self.now += timedelta(seconds=1)
return self.now

adder = Adder()
assert adder.current == adder.current
del adder.current
assert adder.current == now + timedelta(seconds=2)
del adder.current

cache_disable.set(True)
assert adder.current != adder.current
del adder.current
assert adder.current == now + timedelta(seconds=5)
del adder.current

cache_disable.set(False)
assert adder.current == adder.current
del adder.current
assert adder.current == now + timedelta(seconds=7)
del adder.current

0 comments on commit 4805b24

Please sign in to comment.