canonicalwebteam.store-api 7.0.0__py3-none-any.whl → 7.2.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of canonicalwebteam.store-api might be problematic. Click here for more details.

@@ -3,7 +3,7 @@ from cachetools import TTLCache
3
3
  import redis
4
4
  import json
5
5
  import logging
6
- from typing import Optional, Any
6
+ from typing import Optional, Any, Union
7
7
 
8
8
  logger = logging.getLogger(__name__)
9
9
 
@@ -12,6 +12,16 @@ port = os.getenv("REDIS_DB_PORT", "6379")
12
12
  password = os.getenv("REDIS_DB_PASSWORD", None)
13
13
 
14
14
 
15
+ class SafeJSONEncoder(json.JSONEncoder):
16
+ def default(self, obj):
17
+ if isinstance(obj, bytes):
18
+ try:
19
+ return obj.decode("utf-8")
20
+ except UnicodeDecodeError:
21
+ return f"<<non-decodable-bytes ({len(obj)} bytes)>>"
22
+ return super().default(obj)
23
+
24
+
15
25
  class RedisCache:
16
26
  def __init__(self, namespace: str, maxsize: int, ttl: int = 300):
17
27
  self.namespace = namespace
@@ -29,14 +39,23 @@ class RedisCache:
29
39
  logger.warning("Redis unavailable: %s", e)
30
40
  self.redis_available = False
31
41
 
32
- def _build_key(self, key: str) -> str:
33
- return f"{self.namespace}:{key}"
42
+ def _build_key(
43
+ self, key: Union[str, tuple[str, Optional[dict[str, Any]]]]
44
+ ) -> str:
45
+ base_key, parts = key if isinstance(key, tuple) else (key, {})
46
+ key_parts = ":".join(f"{k}-{v}" for k, v in parts.items() if v)
47
+ full_key = (
48
+ f"{self.namespace}:{base_key}:{key_parts}"
49
+ if key_parts
50
+ else f"{self.namespace}:{base_key}"
51
+ )
52
+ return full_key
34
53
 
35
54
  def _serialize(self, value: Any) -> str:
36
55
  if isinstance(value, str):
37
56
  return value
38
57
  try:
39
- return json.dumps(value)
58
+ return json.dumps(value, cls=SafeJSONEncoder)
40
59
  except (TypeError, ValueError) as e:
41
60
  logger.error("Serialization error: %s", e)
42
61
  raise
@@ -54,34 +73,43 @@ class RedisCache:
54
73
  logger.error("Deserialization error: %s", e)
55
74
  raise
56
75
 
57
- def get(self, key: str, expected_type: type = str) -> Any:
76
+ def get(
77
+ self,
78
+ key: Union[str, tuple[str, Optional[dict[str, Any]]]],
79
+ expected_type: type = str,
80
+ ) -> Any:
81
+ full_key = self._build_key(key)
58
82
  if self.redis_available:
59
- full_key = self._build_key(key)
60
83
  try:
61
84
  value = self.client.get(full_key)
62
85
  return self._deserialize(value, expected_type)
63
86
  except redis.RedisError as e:
64
87
  logger.error("Redis get error: %s", e)
65
- value = self.fallback.get(key)
88
+ value = self.fallback.get(full_key)
66
89
  return value
67
90
 
68
- def set(self, key: str, value: Any, ttl=300):
91
+ def set(
92
+ self,
93
+ key: Union[str, tuple[str, Optional[dict[str, Any]]]],
94
+ value: Any,
95
+ ttl=300,
96
+ ):
97
+ full_key = self._build_key(key)
69
98
  if self.redis_available:
70
- full_key = self._build_key(key)
71
99
  try:
72
100
  serialized = self._serialize(value)
73
101
  self.client.setex(full_key, ttl, serialized)
74
102
  return
75
103
  except redis.RedisError as e:
76
104
  logger.error("Redis set error: %s", e)
77
- self.fallback[key] = value
105
+ self.fallback[full_key] = value
78
106
 
79
- def delete(self, key: str):
107
+ def delete(self, key: Union[str, tuple[str, Optional[dict[str, Any]]]]):
108
+ full_key = self._build_key(key)
80
109
  if self.redis_available:
81
- full_key = self._build_key(key)
82
110
  try:
83
111
  self.client.delete(full_key)
84
112
  except redis.RedisError as e:
85
113
  logger.error("Redis delete error: %s", e)
86
114
  else:
87
- self.fallback.pop(key, None)
115
+ self.fallback.pop(full_key, None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: canonicalwebteam.store-api
3
- Version: 7.0.0
3
+ Version: 7.2.0
4
4
  Summary:
5
5
  License: LGPL-3.0
6
6
  Author: Canonical Web Team
@@ -7,8 +7,8 @@ canonicalwebteam/store_api/dashboard.py,sha256=M5JLjTTahN-bfiVz9SuP6ahLjqEvOalwm
7
7
  canonicalwebteam/store_api/devicegw.py,sha256=i42fnc29-CF3vM_tm7mwoOjQraDhu41EDkxILle1pQ4,10627
8
8
  canonicalwebteam/store_api/publishergw.py,sha256=u2D2Y76xC8ms16XTZcUe_KmRdcyzqOV2g0aN9HYZBrQ,29702
9
9
  canonicalwebteam/stores_web_redis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- canonicalwebteam/stores_web_redis/utility.py,sha256=h-4AxoMM0TBYjgWgq6dlN1-c0VKzaB9ZDzSPe75CVdY,2787
11
- canonicalwebteam_store_api-7.0.0.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
12
- canonicalwebteam_store_api-7.0.0.dist-info/METADATA,sha256=-iatcvbkeNQnpOgKOaPyTkdfl4LM1ckmUk05XMa1svI,2284
13
- canonicalwebteam_store_api-7.0.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
14
- canonicalwebteam_store_api-7.0.0.dist-info/RECORD,,
10
+ canonicalwebteam/stores_web_redis/utility.py,sha256=dsHn8Zasn3Wsq4M29igv2gLA1vmXMDo8PQduf5cF_ns,3677
11
+ canonicalwebteam_store_api-7.2.0.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
12
+ canonicalwebteam_store_api-7.2.0.dist-info/METADATA,sha256=50eC9ov7cIBDajLYmhtdPDgj_Q8LlWp4qPCFtOgD9SI,2284
13
+ canonicalwebteam_store_api-7.2.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
14
+ canonicalwebteam_store_api-7.2.0.dist-info/RECORD,,