canonicalwebteam.store-api 7.1.0__tar.gz → 7.3.0__tar.gz

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.

Files changed (14) hide show
  1. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/PKG-INFO +1 -1
  2. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/canonicalwebteam/stores_web_redis/utility.py +44 -14
  3. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/pyproject.toml +1 -1
  4. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/LICENSE +0 -0
  5. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/README.md +0 -0
  6. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/canonicalwebteam/__init__.py +0 -0
  7. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/canonicalwebteam/exceptions.py +0 -0
  8. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/canonicalwebteam/retry_utils.py +0 -0
  9. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/canonicalwebteam/store_api/__init__.py +0 -0
  10. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/canonicalwebteam/store_api/base.py +0 -0
  11. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/canonicalwebteam/store_api/dashboard.py +0 -0
  12. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/canonicalwebteam/store_api/devicegw.py +0 -0
  13. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/canonicalwebteam/store_api/publishergw.py +0 -0
  14. {canonicalwebteam_store_api-7.1.0 → canonicalwebteam_store_api-7.3.0}/canonicalwebteam/stores_web_redis/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: canonicalwebteam.store-api
3
- Version: 7.1.0
3
+ Version: 7.3.0
4
4
  Summary:
5
5
  License: LGPL-3.0
6
6
  Author: Canonical Web Team
@@ -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,24 @@ 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, bytearray)):
18
+ try:
19
+ return bytes(obj).decode("utf-8")
20
+ except UnicodeDecodeError:
21
+ return f"non-decodable-bytes ({len(obj)} bytes)"
22
+
23
+ if isinstance(obj, set):
24
+ try:
25
+ return sorted(obj)
26
+ except Exception:
27
+ return list(obj)
28
+ if isinstance(obj, tuple):
29
+ return list(obj)
30
+ return super().default(obj)
31
+
32
+
15
33
  class RedisCache:
16
34
  def __init__(self, namespace: str, maxsize: int, ttl: int = 300):
17
35
  self.namespace = namespace
@@ -29,20 +47,23 @@ class RedisCache:
29
47
  logger.warning("Redis unavailable: %s", e)
30
48
  self.redis_available = False
31
49
 
32
- def _build_key(self, base_key: str, **parts) -> str:
50
+ def _build_key(
51
+ self, key: Union[str, tuple[str, Optional[dict[str, Any]]]]
52
+ ) -> str:
53
+ base_key, parts = key if isinstance(key, tuple) else (key, {})
33
54
  key_parts = ":".join(f"{k}-{v}" for k, v in parts.items() if v)
34
- key = (
55
+ full_key = (
35
56
  f"{self.namespace}:{base_key}:{key_parts}"
36
57
  if key_parts
37
58
  else f"{self.namespace}:{base_key}"
38
59
  )
39
- return key
60
+ return full_key
40
61
 
41
62
  def _serialize(self, value: Any) -> str:
42
63
  if isinstance(value, str):
43
64
  return value
44
65
  try:
45
- return json.dumps(value)
66
+ return json.dumps(value, cls=SafeJSONEncoder)
46
67
  except (TypeError, ValueError) as e:
47
68
  logger.error("Serialization error: %s", e)
48
69
  raise
@@ -60,34 +81,43 @@ class RedisCache:
60
81
  logger.error("Deserialization error: %s", e)
61
82
  raise
62
83
 
63
- def get(self, key: str, expected_type: type = str) -> Any:
84
+ def get(
85
+ self,
86
+ key: Union[str, tuple[str, Optional[dict[str, Any]]]],
87
+ expected_type: type = str,
88
+ ) -> Any:
89
+ full_key = self._build_key(key)
64
90
  if self.redis_available:
65
- full_key = self._build_key(key)
66
91
  try:
67
92
  value = self.client.get(full_key)
68
93
  return self._deserialize(value, expected_type)
69
94
  except redis.RedisError as e:
70
95
  logger.error("Redis get error: %s", e)
71
- value = self.fallback.get(key)
96
+ value = self.fallback.get(full_key)
72
97
  return value
73
98
 
74
- def set(self, key: str, value: Any, ttl=300):
99
+ def set(
100
+ self,
101
+ key: Union[str, tuple[str, Optional[dict[str, Any]]]],
102
+ value: Any,
103
+ ttl=300,
104
+ ):
105
+ full_key = self._build_key(key)
75
106
  if self.redis_available:
76
- full_key = self._build_key(key)
77
107
  try:
78
108
  serialized = self._serialize(value)
79
109
  self.client.setex(full_key, ttl, serialized)
80
110
  return
81
111
  except redis.RedisError as e:
82
112
  logger.error("Redis set error: %s", e)
83
- self.fallback[key] = value
113
+ self.fallback[full_key] = value
84
114
 
85
- def delete(self, key: str):
115
+ def delete(self, key: Union[str, tuple[str, Optional[dict[str, Any]]]]):
116
+ full_key = self._build_key(key)
86
117
  if self.redis_available:
87
- full_key = self._build_key(key)
88
118
  try:
89
119
  self.client.delete(full_key)
90
120
  except redis.RedisError as e:
91
121
  logger.error("Redis delete error: %s", e)
92
122
  else:
93
- self.fallback.pop(key, None)
123
+ self.fallback.pop(full_key, None)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = 'canonicalwebteam.store-api'
3
- version = '7.1.0'
3
+ version = '7.3.0'
4
4
  description = ''
5
5
  authors = ['Canonical Web Team <webteam@canonical.com>']
6
6
  license = 'LGPL-3.0'