Skip to content

Commit 6f25c5d

Browse files
authored
V2.6.0 release (#58)
* Custom serialization (#56) * Changed house keeping * Added pylint to test-requirements * Changed packages python versions * Changed refactored transform branch tables to private * Changed Refactor transform into encoding/decoding * Changed pep8 unto thyself * Changed pylama bug, NANI * Changed attribute to indicate it's private * Added initial happy path test * Changed type hinting * Added test check we can store the result from initial to a second * Added test that assert result from second store and encode is still expected value * Added encryption example test * Added tests for encrypted values * Changed improved message during unit test failure * Changed consistent naming * Changed typing, type hints * Changed both new test files are now part of coverage test run * Added readme section for extended types * Changed readme example to use repl * Added defaults for custom types * Changed updated testing and added additional example * Changed linting change * Added readme datetime example * Changed, QOL * Added allow for extending types based on method name * Changed update docstring to latest change
1 parent 0b7b2e8 commit 6f25c5d

9 files changed

+1200
-69
lines changed

.github/workflows/ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ jobs:
4444
4545
- name: Run Pylama
4646
run: |
47-
pylama * -i E501
47+
pylama redis_dict.py -i E501,E231
4848
4949
- name: Run Unit Tests
5050
run: |
51-
coverage run -m unittest discover
51+
coverage run -m unittest discover -p "*tests.py"
5252
5353
- name: Upload coverage reports to Codecov, send only once
5454
if: matrix.python-version == '3.12'

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ __pycache__
66
build
77
dist
88
venv
9+
.venv
910

1011
.hypothesis/
1112

README.md

+80-19
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
[![codecov](https://codecov.io/gh/Attumm/redis-dict/graph/badge.svg?token=Lqs7McQGEs)](https://codecov.io/gh/Attumm/redis-dict)
44
[![Downloads](https://static.pepy.tech/badge/redis-dict/month)](https://pepy.tech/project/redis-dict)
55

6-
RedisDict is a Python library that provides a convenient and familiar interface for interacting with Redis as if it were a Python dictionary. This simple yet powerful library enables you to manage key-value pairs in Redis using native Python syntax. It supports various data types, including strings, integers, floats, booleans, lists, and dictionaries, and includes additional utility functions for more complex use cases.
7-
8-
By leveraging Redis for efficient key-value storage, RedisDict allows for high-performance data management and is particularly useful for handling large datasets that may exceed local memory capacity.
6+
RedisDict is a Python library that offers a convenient and familiar interface for interacting with Redis, treating it as if it were a Python dictionary. Its goal is to help developers write clean, Pythonic code while using Redis as a storage solution for seamless distributed computing. This simple yet powerful library utilizes Redis as a key-value store and supports various data types, including strings, integers, floats, booleans, lists, and dictionaries. Additionally, developers can extend RedisDict to work with custom objects.
97

8+
The library includes utility functions for more complex use cases such as caching, batching, and more. By leveraging Redis for efficient key-value storage, RedisDict enables high-performance data management, maintaining efficiency even with large datasets and Redis instances.
109

1110
## Features
1211

@@ -17,20 +16,27 @@ By leveraging Redis for efficient key-value storage, RedisDict allows for high-p
1716
* Efficiency and Scalability: RedisDict is designed for use with large datasets and is optimized for efficiency. It retrieves only the data needed for a particular operation, ensuring efficient memory usage and fast performance.
1817
* Namespace Management: Provides simple and efficient namespace handling to help organize and manage data in Redis, streamlining data access and manipulation.
1918
* Distributed Computing: With its ability to seamlessly connect to other instances or servers with access to the same Redis instance, RedisDict enables easy distributed computing.
20-
* Custom data types: Add custom types and transformations to suit your specific needs.
19+
* Custom data: types: Add custom types encoding/decoding to store your data types.
20+
* Encryption: allows for storing data encrypted, while retaining the simple dictionary interface.
2121

2222
## Example
2323
Redis is an exceptionally fast database when used appropriately. RedisDict leverages Redis for efficient key-value storage, enabling high-performance data management.
2424

25-
```python
26-
from redis_dict import RedisDict
25+
```bash
26+
pip install redis-dict
27+
```
2728

28-
dic = RedisDict()
29-
dic['foo'] = 42
30-
print(dic['foo']) # Output: 42
31-
print('foo' in dic) # Output: True
32-
dic["baz"] = "hello world"
33-
print(dic) # Output: {'foo': 42, 'baz': 'hello world'}
29+
```python
30+
>>> from redis_dict import RedisDict
31+
>>> dic = RedisDict()
32+
>>> dic['foo'] = 42
33+
>>> dic['foo']
34+
42
35+
>>> 'foo' in dic
36+
True
37+
>>> dic["baz"] = "hello world"
38+
>>> dic
39+
{'foo': 42, 'baz': 'hello world'}
3440
```
3541
In Redis our example looks like this.
3642
```
@@ -43,12 +49,12 @@ In Redis our example looks like this.
4349
"str:hello world"
4450
```
4551

52+
4653
### Namespaces
47-
Acting as an identifier for your dictionary across different systems, RedisDict employs namespaces for organized data management. When a namespace isn't specified, "main" becomes the default. Thus allowing for data organization accross systems and projects with the same redis instance.
54+
Acting as an identifier for your dictionary across different systems, RedisDict employs namespaces for organized data management. When a namespace isn't specified, "main" becomes the default. Thus allowing for data organization across systems and projects with the same redis instance.
4855

4956
This approach also minimizes the risk of key collisions between different applications, preventing hard-to-debug issues. By leveraging namespaces, RedisDict ensures a cleaner and more maintainable data management experience for developers working on multiple projects.
5057

51-
5258
## Advanced Features
5359

5460
### Expiration
@@ -81,6 +87,8 @@ with dic.expire_at(seconds):
8187
3. Updating keys while preserving the initial timeout In certain situations, there is a need to update the value while keeping the expiration intact. This is achievable by setting the 'preserve_expiration' to true.
8288

8389
```python
90+
import time
91+
8492
dic = RedisDict(expire=10, preserve_expiration=True)
8593
dic['gone'] = 'in ten seconds'
8694

@@ -93,6 +101,7 @@ dic['gone'] = 'gone in 5 seconds'
93101
Efficiently batch your requests using the Pipeline feature, which can be easily utilized with a context manager.
94102

95103
```python
104+
from redis_dict import RedisDict
96105
dic = RedisDict(namespace="example")
97106

98107
# one round trip to redis
@@ -122,21 +131,22 @@ print(dic["foo"]) # outputs "bar"
122131
### Caching made simple
123132
```python
124133
import time
134+
from datetime import timedelta
125135
from redis_dict import RedisDict
126136

127137
def expensive_function(x):
128-
time.sleep(2)
138+
time.sleep(x)
129139
return x * 2
130140

131-
cache = RedisDict(namespace="cache", expire=10)
141+
cache = RedisDict(namespace="cache", expire=timedelta(minutes=60))
132142

133143
def cached_expensive_function(x):
134144
if x not in cache:
135145
cache[x] = expensive_function(x)
136146
return cache[x]
137147

138148
start_time = time.time()
139-
print(cached_expensive_function(5)) # Takes around 2 seconds to compute and caches the result.
149+
print(cached_expensive_function(5)) # Takes around 5 seconds to compute and caches the result.
140150
print(f"Time taken: {time.time() - start_time:.2f} seconds")
141151

142152
start_time = time.time()
@@ -156,7 +166,7 @@ dic["name"] = "John Doe"
156166
dic["age"] = 32
157167
dic["city"] = "Amsterdam"
158168

159-
# Get value by key
169+
# Get value by key, from any instance connected to the same redis/namespace
160170
print(dic["name"]) # Output: John Doe
161171

162172
# Update value by key, got a year older
@@ -209,10 +219,61 @@ print(dic["d"]) # Output: 4
209219
For more advanced examples of RedisDict, please refer to the unit-test files in the repository. All features and functionalities are thoroughly tested in [unit tests (here)](https://github.com/Attumm/redis-dict/blob/main/tests.py#L1) Or take a look at load test for batching [load test](https://github.com/Attumm/redis-dict/blob/main/load_test.py#L1).
210220
The unit-tests can be as used as a starting point.
211221

222+
### Extending Types
223+
224+
## Extending RedisDict with Custom Types
225+
226+
RedisDict supports custom type serialization. Here's how to add a new type:
227+
228+
229+
```python
230+
import json
231+
from redis_dict import RedisDict
232+
233+
class Person:
234+
def __init__(self, name, age):
235+
self.name = name
236+
self.age = age
237+
238+
def encode(self) -> str:
239+
return json.dumps(self.__dict__)
240+
241+
@classmethod
242+
def decode(cls, encoded_str: str) -> 'Person':
243+
return cls(**json.loads(encoded_str))
244+
245+
redis_dict = RedisDict()
246+
247+
# Extend redis dict with the new type
248+
redis_dict.extends_type(Person)
249+
250+
# RedisDict can now seamlessly handle Person instances.
251+
person = Person(name="John", age=32)
252+
redis_dict["person1"] = person
253+
254+
result = redis_dict["person1"]
255+
256+
assert result.name == person.name
257+
assert result.age == person.age
258+
```
259+
260+
```python
261+
>>> from datetime import datetime
262+
>>> redis_dict.extends_type(datetime, datetime.isoformat, datetime.fromisoformat)
263+
>>> redis_dict["now"] = datetime.now()
264+
>>> redis_dict
265+
{'now': datetime.datetime(2024, 10, 14, 18, 41, 53, 493775)}
266+
>>> redis_dict["now"]
267+
datetime.datetime(2024, 10, 14, 18, 41, 53, 493775)
268+
```
269+
270+
For more information on [extending types](https://github.com/Attumm/redis-dict/blob/main/extend_types_tests.py).
212271
### Redis Encryption
213-
Setup guide for configuring and utilizing encrypted Redis for redis-dict.
272+
Setup guide for configuring and utilizing encrypted Redis TLS for redis-dict.
214273
[Setup guide](https://github.com/Attumm/redis-dict/blob/main/encrypted_redis.MD)
215274

275+
### Redis Storage Encryption
276+
For storing encrypted data values, it's possible to use extended types. Take a look at this [encrypted test](https://github.com/Attumm/redis-dict/blob/main/encrypt_tests.py).
216277

217278
### Tests
218279
The RedisDict library includes a comprehensive suite of tests that ensure its correctness and resilience. The test suite covers various data types, edge cases, and error handling scenarios. It also employs the Hypothesis library for property-based testing, which provides fuzz testing to evaluate the implementation

0 commit comments

Comments
 (0)