Skip to content

Commit

Permalink
Merge pull request #24 from Attumm/expire_key_on_feature_#23
Browse files Browse the repository at this point in the history
 v=2.1.0
  • Loading branch information
Attumm authored Jun 23, 2023
2 parents 1bb19f1 + c48397d commit 3f91ecd
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 58 deletions.
4 changes: 2 additions & 2 deletions assert_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
assert sorted(dd.multi_get('keys')) == sorted(list(items.values()))
assert dd.multi_dict('keys') == items

long_key ='thekeyislongbutstill'
long_key = 'thekeyislongbutstill'
items = {'K1': 'V1', 'KK22': 'VV22', 'KKK333': 'VVV333'}
for key, val in items.items():
dd.chain_set([long_key, key], val)
Expand All @@ -87,7 +87,7 @@

assert len(dd) == 1

del(dd['one_item'])
del dd['one_item']
assert len(dd) == 0

print('all is well')
10 changes: 5 additions & 5 deletions load_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

data_types = ["str", "int", "float", "bool", "list", "dict"]


def generate_random_data(data_type):
if data_type == "str":
return ''.join(random.choice(string.ascii_letters) for _ in range(10))
Expand All @@ -27,20 +28,20 @@ def generate_random_data(data_type):
else:
return {f'key{i}': random.randint(1, 100) for i in range(5)}


def main():
start_total = time.time()
r = RedisDict(namespace="load_test")
operation_times = []
batched = BATCHING
batched = BATCHING

if batched:
data = []
for i in range(OPERATIONS):
key = f"key{i}"
data_type = random.choice(data_types)
value = generate_random_data(data_type)
data.append((key, value))

data.append((key, value))

if i % BATCH_SIZE == 0:
with r.pipeline():
Expand Down Expand Up @@ -71,7 +72,7 @@ def main():

start_time = time.time()
r[key] = value
retrieved_value = r[key]
_ = r[key]
end_time = time.time()

operation_times.append(end_time - start_time)
Expand Down Expand Up @@ -100,4 +101,3 @@ def main():

if __name__ == "__main__":
main()

36 changes: 34 additions & 2 deletions redis_dict.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import json
from typing import Any, Callable, Dict, Iterator, Set, List, Tuple, Union, Optional

from redis import StrictRedis

from contextlib import contextmanager
Expand Down Expand Up @@ -99,6 +98,8 @@ class RedisDict:
namespace (str): A string used as a prefix for Redis keys to separate data in different namespaces.
expire (Union[int, None]): An optional expiration time for keys, in seconds.
TODO:
Move init to work with types
"""

transform: transform_type = {
Expand Down Expand Up @@ -134,6 +135,7 @@ def __init__(self, **kwargs: Any):

self.namespace: str = kwargs.pop('namespace', '')
self.expire: Union[int, None] = kwargs.pop('expire', None)
self.preserve_expiration: bool = kwargs.pop('preserve_expiration', False)

self.redis: StrictRedis[Any] = StrictRedis(decode_responses=True, **kwargs)
self.get_redis: StrictRedis[Any] = self.redis
Expand Down Expand Up @@ -185,7 +187,12 @@ def _store(self, key: str, value: Any) -> None:
value = self.pre_transform.get(store_type, lambda x: x)(value) # type: ignore

store_value = '{}:{}'.format(store_type, value)
self.redis.set(self._format_key(key), store_value, ex=self.expire)
formatted_key = self._format_key(key)

if self.preserve_expiration and self.redis.exists(formatted_key):
self.redis.set(formatted_key, store_value, keepttl=True)
else:
self.redis.set(formatted_key, store_value, ex=self.expire)

def _load(self, key: str) -> Tuple[bool, Any]:
"""
Expand Down Expand Up @@ -720,3 +727,28 @@ def multi_del(self, key: str) -> int:
if len(keys) == 0:
return 0
return self.redis.delete(*keys)

def get_redis_info(self) -> Dict[str, Any]:
"""
Retrieve information and statistics about the Redis server.
Returns:
dict: The information and statistics from the Redis server in a dictionary.
"""
return dict(self.redis.info())

def get_ttl(self, key: str) -> Optional[int]:
"""
Get the Time To Live (TTL) in seconds for a given key. If the key does not exist or does not have an
associated expire, return None.
Args:
key (str): The key for which to get the TTL.
Returns:
Optional[int]: The TTL in seconds if the key exists and has an expire set; otherwise, None.
"""
val = self.redis.ttl(self._format_key(key))
if val < 0:
return None
return val
6 changes: 2 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
long_description=long_description,
long_description_content_type='text/markdown',

version='2.0.3',
version='2.1.0',
py_modules=['redis_dict'],
install_requires=['redis',],
license='MIT',
Expand All @@ -35,14 +35,12 @@
'License :: OSI Approved :: MIT License',

'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
],
)

2 changes: 1 addition & 1 deletion test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
attrs==22.2.0
cffi==1.15.1
coverage==5.5
cryptography==40.0.1
cryptography==41.0.0
exceptiongroup==1.1.1
future==0.18.3
hypothesis==6.70.1
Expand Down
Loading

0 comments on commit 3f91ecd

Please sign in to comment.