redis-dict 2.6.0__tar.gz → 2.7.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: redis dict
3
- Version: 2.6.0
3
+ Version: 2.7.0
4
4
  Summary: Dictionary with Redis as storage backend
5
5
  Home-page: https://github.com/Attumm/redisdict
6
6
  Author: Melvin Bijman
@@ -44,7 +44,7 @@ The library includes utility functions for more complex use cases such as cachin
44
44
  ## Features
45
45
 
46
46
  * Dictionary-like interface: Use familiar Python dictionary syntax to interact with Redis.
47
- * Data Type Support: Comprehensive support for various data types, including strings, integers, floats, booleans, lists, dictionaries, sets, and tuples.
47
+ * Data Type Support: Comprehensive support for various data types.
48
48
  * Pipelining support: Use pipelines for batch operations to improve performance.
49
49
  * Expiration Support: Enables the setting of expiration times either globally or individually per key, through the use of context managers.
50
50
  * 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.
@@ -253,9 +253,53 @@ print(dic["d"]) # Output: 4
253
253
  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).
254
254
  The unit-tests can be as used as a starting point.
255
255
 
256
- ### Extending Types
256
+ ## Types
257
257
 
258
- ## Extending RedisDict with Custom Types
258
+ ### standard types
259
+ RedisDict supports a range of Python data types, from basic types to nested structures.
260
+ Basic types are handled natively, while complex data types like lists and dictionaries, RedisDict uses JSON serialization, specifically avoiding `pickle` due to its [security vulnerabilities](https://docs.python.org/3/library/pickle.html) in distributed computing contexts.
261
+ Although the library supports nested structures, the recommended best practice is to use RedisDict as a shallow dictionary.
262
+ This approach optimizes Redis database performance and efficiency by ensuring that each set and get operation efficiently maps to Redis's key-value storage capabilities, while still preserving the library's Pythonic interface.
263
+ Following types are supported:
264
+ `str, int, float, bool, NoneType, list, dict, tuple, set, datetime, date, time, timedelta, Decimal, complex, bytes, UUID, OrderedDict, defaultdict, frozenset`
265
+ ```python
266
+ from redis_dict import RedisDict
267
+
268
+ from uuid import UUID
269
+ from decimal import Decimal
270
+ from collections import OrderedDict, defaultdict
271
+ from datetime import datetime, date, time, timedelta
272
+
273
+
274
+ dic = RedisDict()
275
+
276
+ dic["string"] = "Hello World"
277
+ dic["number"] = 42
278
+ dic["float"] = 3.14
279
+ dic["bool"] = True
280
+ dic["None"] = None
281
+
282
+ dic["list"] = [1, 2, 3]
283
+ dic["dict"] = {"a": 1, "b": 2}
284
+ dic["tuple"] = (1, 2, 3)
285
+ dic["set"] = {1, 2, 3}
286
+
287
+ dic["datetime"] = datetime.date(2024, 1, 1, 12, 30, 45)
288
+ dic["date"] = date(2024, 1, 1)
289
+ dic["time"] = time(12, 30, 45)
290
+ dic["delta"] = timedelta(days=1, hours=2)
291
+
292
+ dic["decimal"] = Decimal("3.14159")
293
+ dic["complex"] = complex(1, 2)
294
+ dic["bytes"] = bytes([72, 101, 108, 108, 111])
295
+ dic["uuid"] = UUID('12345678-1234-5678-1234-567812345678')
296
+
297
+ dic["ordered"] = OrderedDict([('a', 1), ('b', 2)])
298
+ dic["default"] = defaultdict(int, {'a': 1, 'b': 2})
299
+ dic["frozen"] = frozenset([1, 2, 3])
300
+ ```
301
+
302
+ ### Extending RedisDict with Custom Types
259
303
 
260
304
  RedisDict supports custom type serialization. Here's how to add a new type:
261
305
 
@@ -10,7 +10,7 @@ The library includes utility functions for more complex use cases such as cachin
10
10
  ## Features
11
11
 
12
12
  * Dictionary-like interface: Use familiar Python dictionary syntax to interact with Redis.
13
- * Data Type Support: Comprehensive support for various data types, including strings, integers, floats, booleans, lists, dictionaries, sets, and tuples.
13
+ * Data Type Support: Comprehensive support for various data types.
14
14
  * Pipelining support: Use pipelines for batch operations to improve performance.
15
15
  * Expiration Support: Enables the setting of expiration times either globally or individually per key, through the use of context managers.
16
16
  * 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.
@@ -219,9 +219,53 @@ print(dic["d"]) # Output: 4
219
219
  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).
220
220
  The unit-tests can be as used as a starting point.
221
221
 
222
- ### Extending Types
222
+ ## Types
223
223
 
224
- ## Extending RedisDict with Custom Types
224
+ ### standard types
225
+ RedisDict supports a range of Python data types, from basic types to nested structures.
226
+ Basic types are handled natively, while complex data types like lists and dictionaries, RedisDict uses JSON serialization, specifically avoiding `pickle` due to its [security vulnerabilities](https://docs.python.org/3/library/pickle.html) in distributed computing contexts.
227
+ Although the library supports nested structures, the recommended best practice is to use RedisDict as a shallow dictionary.
228
+ This approach optimizes Redis database performance and efficiency by ensuring that each set and get operation efficiently maps to Redis's key-value storage capabilities, while still preserving the library's Pythonic interface.
229
+ Following types are supported:
230
+ `str, int, float, bool, NoneType, list, dict, tuple, set, datetime, date, time, timedelta, Decimal, complex, bytes, UUID, OrderedDict, defaultdict, frozenset`
231
+ ```python
232
+ from redis_dict import RedisDict
233
+
234
+ from uuid import UUID
235
+ from decimal import Decimal
236
+ from collections import OrderedDict, defaultdict
237
+ from datetime import datetime, date, time, timedelta
238
+
239
+
240
+ dic = RedisDict()
241
+
242
+ dic["string"] = "Hello World"
243
+ dic["number"] = 42
244
+ dic["float"] = 3.14
245
+ dic["bool"] = True
246
+ dic["None"] = None
247
+
248
+ dic["list"] = [1, 2, 3]
249
+ dic["dict"] = {"a": 1, "b": 2}
250
+ dic["tuple"] = (1, 2, 3)
251
+ dic["set"] = {1, 2, 3}
252
+
253
+ dic["datetime"] = datetime.date(2024, 1, 1, 12, 30, 45)
254
+ dic["date"] = date(2024, 1, 1)
255
+ dic["time"] = time(12, 30, 45)
256
+ dic["delta"] = timedelta(days=1, hours=2)
257
+
258
+ dic["decimal"] = Decimal("3.14159")
259
+ dic["complex"] = complex(1, 2)
260
+ dic["bytes"] = bytes([72, 101, 108, 108, 111])
261
+ dic["uuid"] = UUID('12345678-1234-5678-1234-567812345678')
262
+
263
+ dic["ordered"] = OrderedDict([('a', 1), ('b', 2)])
264
+ dic["default"] = defaultdict(int, {'a': 1, 'b': 2})
265
+ dic["frozen"] = frozenset([1, 2, 3])
266
+ ```
267
+
268
+ ### Extending RedisDict with Custom Types
225
269
 
226
270
  RedisDict supports custom type serialization. Here's how to add a new type:
227
271
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: redis-dict
3
- Version: 2.6.0
3
+ Version: 2.7.0
4
4
  Summary: Dictionary with Redis as storage backend
5
5
  Home-page: https://github.com/Attumm/redisdict
6
6
  Author: Melvin Bijman
@@ -44,7 +44,7 @@ The library includes utility functions for more complex use cases such as cachin
44
44
  ## Features
45
45
 
46
46
  * Dictionary-like interface: Use familiar Python dictionary syntax to interact with Redis.
47
- * Data Type Support: Comprehensive support for various data types, including strings, integers, floats, booleans, lists, dictionaries, sets, and tuples.
47
+ * Data Type Support: Comprehensive support for various data types.
48
48
  * Pipelining support: Use pipelines for batch operations to improve performance.
49
49
  * Expiration Support: Enables the setting of expiration times either globally or individually per key, through the use of context managers.
50
50
  * 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.
@@ -253,9 +253,53 @@ print(dic["d"]) # Output: 4
253
253
  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).
254
254
  The unit-tests can be as used as a starting point.
255
255
 
256
- ### Extending Types
256
+ ## Types
257
257
 
258
- ## Extending RedisDict with Custom Types
258
+ ### standard types
259
+ RedisDict supports a range of Python data types, from basic types to nested structures.
260
+ Basic types are handled natively, while complex data types like lists and dictionaries, RedisDict uses JSON serialization, specifically avoiding `pickle` due to its [security vulnerabilities](https://docs.python.org/3/library/pickle.html) in distributed computing contexts.
261
+ Although the library supports nested structures, the recommended best practice is to use RedisDict as a shallow dictionary.
262
+ This approach optimizes Redis database performance and efficiency by ensuring that each set and get operation efficiently maps to Redis's key-value storage capabilities, while still preserving the library's Pythonic interface.
263
+ Following types are supported:
264
+ `str, int, float, bool, NoneType, list, dict, tuple, set, datetime, date, time, timedelta, Decimal, complex, bytes, UUID, OrderedDict, defaultdict, frozenset`
265
+ ```python
266
+ from redis_dict import RedisDict
267
+
268
+ from uuid import UUID
269
+ from decimal import Decimal
270
+ from collections import OrderedDict, defaultdict
271
+ from datetime import datetime, date, time, timedelta
272
+
273
+
274
+ dic = RedisDict()
275
+
276
+ dic["string"] = "Hello World"
277
+ dic["number"] = 42
278
+ dic["float"] = 3.14
279
+ dic["bool"] = True
280
+ dic["None"] = None
281
+
282
+ dic["list"] = [1, 2, 3]
283
+ dic["dict"] = {"a": 1, "b": 2}
284
+ dic["tuple"] = (1, 2, 3)
285
+ dic["set"] = {1, 2, 3}
286
+
287
+ dic["datetime"] = datetime.date(2024, 1, 1, 12, 30, 45)
288
+ dic["date"] = date(2024, 1, 1)
289
+ dic["time"] = time(12, 30, 45)
290
+ dic["delta"] = timedelta(days=1, hours=2)
291
+
292
+ dic["decimal"] = Decimal("3.14159")
293
+ dic["complex"] = complex(1, 2)
294
+ dic["bytes"] = bytes([72, 101, 108, 108, 111])
295
+ dic["uuid"] = UUID('12345678-1234-5678-1234-567812345678')
296
+
297
+ dic["ordered"] = OrderedDict([('a', 1), ('b', 2)])
298
+ dic["default"] = defaultdict(int, {'a': 1, 'b': 2})
299
+ dic["frozen"] = frozenset([1, 2, 3])
300
+ ```
301
+
302
+ ### Extending RedisDict with Custom Types
259
303
 
260
304
  RedisDict supports custom type serialization. Here's how to add a new type:
261
305
 
@@ -66,9 +66,14 @@ otherwise, they will be dropped.
66
66
  >>> cache.get("1234") is None
67
67
  >>> True
68
68
  """
69
+ # Types imports
69
70
  import json
71
+ from datetime import datetime, time, timedelta, date
72
+ from decimal import Decimal
73
+ from uuid import UUID
74
+ from collections import OrderedDict, defaultdict
75
+ import base64
70
76
 
71
- from datetime import timedelta
72
77
  from typing import Any, Callable, Dict, Iterator, Set, List, Tuple, Union, Optional
73
78
  from contextlib import contextmanager
74
79
 
@@ -189,7 +194,6 @@ class RedisDict:
189
194
  expire (Union[int, None]): An optional expiration time for keys, in seconds.
190
195
 
191
196
  """
192
-
193
197
  decoding_registry: DecodeType = {
194
198
  type('').__name__: str,
195
199
  type(1).__name__: int,
@@ -201,6 +205,20 @@ class RedisDict:
201
205
  "dict": json.loads,
202
206
  "tuple": _decode_tuple,
203
207
  type(set()).__name__: _decode_set,
208
+
209
+ datetime.__name__: datetime.fromisoformat,
210
+ date.__name__: date.fromisoformat,
211
+ time.__name__: time.fromisoformat,
212
+ timedelta.__name__: lambda x: timedelta(seconds=float(x)),
213
+
214
+ Decimal.__name__: Decimal,
215
+ complex.__name__: lambda x: complex(*map(float, x.split(','))),
216
+ bytes.__name__: base64.b64decode,
217
+
218
+ UUID.__name__: UUID,
219
+ OrderedDict.__name__: lambda x: OrderedDict(json.loads(x)),
220
+ defaultdict.__name__: lambda x: defaultdict(type(None), json.loads(x)),
221
+ frozenset.__name__: lambda x: frozenset(json.loads(x)),
204
222
  }
205
223
 
206
224
  encoding_registry: EncodeType = {
@@ -208,6 +226,17 @@ class RedisDict:
208
226
  "dict": json.dumps,
209
227
  "tuple": _encode_tuple,
210
228
  type(set()).__name__: _encode_set,
229
+
230
+ datetime.__name__: datetime.isoformat,
231
+ date.__name__: date.isoformat,
232
+ time.__name__: time.isoformat,
233
+ timedelta.__name__: lambda x: str(x.total_seconds()),
234
+
235
+ complex.__name__: lambda x: f"{x.real},{x.imag}",
236
+ bytes.__name__: lambda x: base64.b64encode(x).decode('ascii'),
237
+ OrderedDict.__name__: lambda x: json.dumps(list(x.items())),
238
+ defaultdict.__name__: lambda x: json.dumps(dict(x)),
239
+ frozenset.__name__: lambda x: json.dumps(list(x)),
211
240
  }
212
241
 
213
242
  def __init__(self,
@@ -269,6 +298,14 @@ class RedisDict:
269
298
  return len(val) < self._max_string_size
270
299
  return True
271
300
 
301
+ def _format_value(self, key: str, value: Any) -> str:
302
+ store_type, key = type(value).__name__, str(key)
303
+ if not self._valid_input(value, store_type) or not self._valid_input(key, "str"):
304
+ raise ValueError("Invalid input value or key size exceeded the maximum limit.")
305
+ encoded_value = self.encoding_registry.get(store_type, lambda x: x)(value) # type: ignore
306
+
307
+ return f'{store_type}:{encoded_value}'
308
+
272
309
  def _store(self, key: str, value: Any) -> None:
273
310
  """
274
311
  Store a value in Redis with the given key.
@@ -285,18 +322,12 @@ class RedisDict:
285
322
  Allowing for simple dict set operation, but only cache data that makes sense.
286
323
 
287
324
  """
288
- store_type, key = type(value).__name__, str(key)
289
- if not self._valid_input(value, store_type) or not self._valid_input(key, "str"):
290
- raise ValueError("Invalid input value or key size exceeded the maximum limit.")
291
- value = self.encoding_registry.get(store_type, lambda x: x)(value) # type: ignore
292
-
293
- store_value = f'{store_type}:{value}'
294
325
  formatted_key = self._format_key(key)
295
-
326
+ formatted_value = self._format_value(key, value)
296
327
  if self.preserve_expiration and self.redis.exists(formatted_key):
297
- self.redis.set(formatted_key, store_value, keepttl=True)
328
+ self.redis.set(formatted_key, formatted_value, keepttl=True)
298
329
  else:
299
- self.redis.set(formatted_key, store_value, ex=self.expire)
330
+ self.redis.set(formatted_key, formatted_value, ex=self.expire)
300
331
 
301
332
  def _load(self, key: str) -> Tuple[bool, Any]:
302
333
  """
@@ -311,8 +342,7 @@ class RedisDict:
311
342
  result = self.get_redis.get(self._format_key(key))
312
343
  if result is None:
313
344
  return False, None
314
- type_, value = result.split(':', 1)
315
- return True, self.decoding_registry.get(type_, lambda x: x)(value)
345
+ return True, self._transform(result)
316
346
 
317
347
  def _transform(self, result: str) -> Any:
318
348
  """
@@ -17,7 +17,7 @@ setup(
17
17
  long_description=long_description,
18
18
  long_description_content_type='text/markdown',
19
19
 
20
- version='2.6.0',
20
+ version='2.7.0',
21
21
  py_modules=['redis_dict'],
22
22
  install_requires=['redis',],
23
23
  license='MIT',
File without changes
File without changes