Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/redis/exceptions.py: 67%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

122 statements  

1from enum import Enum 

2 

3"Core exceptions raised by the Redis client" 

4 

5 

6class ExceptionType(Enum): 

7 NETWORK = "network" 

8 TLS = "tls" 

9 AUTH = "auth" 

10 SERVER = "server" 

11 

12 

13class RedisError(Exception): 

14 def __init__(self, *args, status_code: str | None = None): 

15 super().__init__(*args) 

16 self.error_type = ExceptionType.SERVER 

17 self.status_code = status_code 

18 

19 def __repr__(self): 

20 return f"{self.error_type.value}:{self.__class__.__name__}" 

21 

22 

23class ConnectionError(RedisError): 

24 def __init__(self, *args, status_code: str | None = None): 

25 super().__init__(*args, status_code=status_code) 

26 self.error_type = ExceptionType.NETWORK 

27 

28 

29class TimeoutError(RedisError): 

30 def __init__(self, *args, status_code: str | None = None): 

31 super().__init__(*args, status_code=status_code) 

32 self.error_type = ExceptionType.NETWORK 

33 

34 

35class AuthenticationError(ConnectionError): 

36 def __init__(self, *args, status_code: str | None = None): 

37 super().__init__(*args, status_code=status_code) 

38 self.error_type = ExceptionType.AUTH 

39 

40 

41class AuthorizationError(ConnectionError): 

42 def __init__(self, *args, status_code: str | None = None): 

43 super().__init__(*args, status_code=status_code) 

44 self.error_type = ExceptionType.AUTH 

45 

46 

47class BusyLoadingError(ConnectionError): 

48 def __init__(self, *args, status_code: str | None = None): 

49 super().__init__(*args, status_code=status_code) 

50 self.error_type = ExceptionType.NETWORK 

51 

52 

53class InvalidResponse(RedisError): 

54 pass 

55 

56 

57class ResponseError(RedisError): 

58 pass 

59 

60 

61class DataError(RedisError): 

62 pass 

63 

64 

65class PubSubError(RedisError): 

66 pass 

67 

68 

69class WatchError(RedisError): 

70 pass 

71 

72 

73class NoScriptError(ResponseError): 

74 pass 

75 

76 

77class OutOfMemoryError(ResponseError): 

78 """ 

79 Indicates the database is full. Can only occur when either: 

80 * Redis maxmemory-policy=noeviction 

81 * Redis maxmemory-policy=volatile* and there are no evictable keys 

82 

83 For more information see `Memory optimization in Redis <https://redis.io/docs/management/optimization/memory-optimization/#memory-allocation>`_. # noqa 

84 """ 

85 

86 pass 

87 

88 

89class ExecAbortError(ResponseError): 

90 pass 

91 

92 

93class ReadOnlyError(ResponseError): 

94 pass 

95 

96 

97class NoPermissionError(ResponseError): 

98 def __init__(self, *args, status_code: str | None = None): 

99 super().__init__(*args, status_code=status_code) 

100 self.error_type = ExceptionType.AUTH 

101 

102 

103class ModuleError(ResponseError): 

104 pass 

105 

106 

107class NoSuchFieldsetError(ResponseError): 

108 """Server reply when ``HIMPORT SET`` targets a fieldset the connection has not 

109 prepared. 

110 

111 Under lazy PREPARE bundling this is nearly unreachable, but the server can drop 

112 session state mid-connection without dropping the socket (e.g. ``RESET`` or 

113 ``maxmemory-clients`` eviction). The client catches this to re-prepare on the same 

114 socket and retry the SET once instead of failing. 

115 """ 

116 

117 pass 

118 

119 

120class LockError(RedisError, ValueError): 

121 "Errors acquiring or releasing a lock" 

122 

123 # NOTE: For backwards compatibility, this class derives from ValueError. 

124 # This was originally chosen to behave like threading.Lock. 

125 

126 def __init__( 

127 self, message: str | None = None, lock_name: str | None = None 

128 ) -> None: 

129 super().__init__(message) 

130 self.message = message 

131 self.lock_name = lock_name 

132 

133 

134class LockNotOwnedError(LockError): 

135 "Error trying to extend or release a lock that is not owned (anymore)" 

136 

137 pass 

138 

139 

140class ChildDeadlockedError(Exception): 

141 "Error indicating that a child process is deadlocked after a fork()" 

142 

143 pass 

144 

145 

146class AuthenticationWrongNumberOfArgsError(ResponseError): 

147 """ 

148 An error to indicate that the wrong number of args 

149 were sent to the AUTH command 

150 """ 

151 

152 def __init__(self, *args, status_code: str | None = None): 

153 super().__init__(*args, status_code=status_code) 

154 self.error_type = ExceptionType.AUTH 

155 

156 

157class RedisClusterException(Exception): 

158 """ 

159 Base exception for the RedisCluster client 

160 """ 

161 

162 def __init__(self, *args: object) -> None: 

163 super().__init__(*args) 

164 self.error_type = ExceptionType.SERVER 

165 

166 def __repr__(self): 

167 return f"{self.error_type.value}:{self.__class__.__name__}" 

168 

169 

170class ClusterError(RedisError): 

171 """ 

172 Cluster errors occurred multiple times, resulting in an exhaustion of the 

173 command execution TTL 

174 """ 

175 

176 def __init__(self, *args, status_code: str | None = None): 

177 super().__init__(*args, status_code=status_code) 

178 self.error_type = ExceptionType.SERVER 

179 

180 

181class ClusterDownError(ClusterError, ResponseError): 

182 """ 

183 Error indicated CLUSTERDOWN error received from cluster. 

184 By default Redis Cluster nodes stop accepting queries if they detect there 

185 is at least a hash slot uncovered (no available node is serving it). 

186 This way if the cluster is partially down (for example a range of hash 

187 slots are no longer covered) the entire cluster eventually becomes 

188 unavailable. It automatically returns available as soon as all the slots 

189 are covered again. 

190 """ 

191 

192 def __init__(self, resp, status_code: str | None = None): 

193 self.args = (resp,) 

194 self.message = resp 

195 self.error_type = ExceptionType.SERVER 

196 self.status_code = status_code 

197 

198 

199class AskError(ResponseError): 

200 """ 

201 Error indicated ASK error received from cluster. 

202 When a slot is set as MIGRATING, the node will accept all queries that 

203 pertain to this hash slot, but only if the key in question exists, 

204 otherwise the query is forwarded using a -ASK redirection to the node that 

205 is target of the migration. 

206 

207 src node: MIGRATING to dst node 

208 get > ASK error 

209 ask dst node > ASKING command 

210 dst node: IMPORTING from src node 

211 asking command only affects next command 

212 any op will be allowed after asking command 

213 """ 

214 

215 def __init__(self, resp, status_code: str | None = None): 

216 """should only redirect to master node""" 

217 super().__init__(resp, status_code=status_code) 

218 self.args = (resp,) 

219 self.message = resp 

220 slot_id, new_node = resp.split(" ") 

221 host, port = new_node.rsplit(":", 1) 

222 self.slot_id = int(slot_id) 

223 self.node_addr = self.host, self.port = host, int(port) 

224 

225 

226class TryAgainError(ResponseError): 

227 """ 

228 Error indicated TRYAGAIN error received from cluster. 

229 Operations on keys that don't exist or are - during resharding - split 

230 between the source and destination nodes, will generate a -TRYAGAIN error. 

231 """ 

232 

233 def __init__(self, *args, status_code: str | None = None, **kwargs): 

234 super().__init__(*args, status_code=status_code) 

235 

236 

237class ClusterCrossSlotError(ResponseError): 

238 """ 

239 Error indicated CROSSSLOT error received from cluster. 

240 A CROSSSLOT error is generated when keys in a request don't hash to the 

241 same slot. 

242 """ 

243 

244 message = "Keys in request don't hash to the same slot" 

245 

246 def __init__(self, *args, status_code: str | None = None): 

247 super().__init__(*args, status_code=status_code) 

248 self.error_type = ExceptionType.SERVER 

249 

250 

251class MovedError(AskError): 

252 """ 

253 Error indicated MOVED error received from cluster. 

254 A request sent to a node that doesn't serve this key will be replayed with 

255 a MOVED error that points to the correct node. 

256 """ 

257 

258 pass 

259 

260 

261class MasterDownError(ClusterDownError): 

262 """ 

263 Error indicated MASTERDOWN error received from cluster. 

264 Link with MASTER is down and replica-serve-stale-data is set to 'no'. 

265 """ 

266 

267 pass 

268 

269 

270class SlotNotCoveredError(RedisClusterException): 

271 """ 

272 This error only happens in the case where the connection pool will try to 

273 fetch what node that is covered by a given slot. 

274 

275 If this error is raised the client should drop the current node layout and 

276 attempt to reconnect and refresh the node layout again 

277 """ 

278 

279 pass 

280 

281 

282class MaxConnectionsError(ConnectionError): 

283 """ 

284 Raised when a connection pool has reached its max_connections limit. 

285 This indicates pool exhaustion rather than an actual connection failure. 

286 """ 

287 

288 pass 

289 

290 

291class CrossSlotTransactionError(RedisClusterException): 

292 """ 

293 Raised when a transaction or watch is triggered in a pipeline 

294 and not all keys or all commands belong to the same slot. 

295 """ 

296 

297 pass 

298 

299 

300class InvalidPipelineStack(RedisClusterException): 

301 """ 

302 Raised on unexpected response length on pipelines. This is 

303 most likely a handling error on the stack. 

304 """ 

305 

306 pass 

307 

308 

309class ExternalAuthProviderError(ConnectionError): 

310 """ 

311 Raised when an external authentication provider returns an error. 

312 """ 

313 

314 pass 

315 

316 

317class IncorrectPolicyType(Exception): 

318 """ 

319 Raised when a policy type isn't matching to any known policy types. 

320 """ 

321 

322 pass