aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Leon Sandøy <[email protected]>2020-05-28 01:29:34 +0200
committerGravatar Leon Sandøy <[email protected]>2020-05-28 01:29:34 +0200
commitf66a63501fe1ef8fb5390dfbe42ae9f95ea2bc28 (patch)
tree0e462b216dd21d9434bfcb9ef0c2206aed7fc4be
parentMake prefix consts private and more precise. (diff)
Add custom exceptions for each error state.
The bot can get into trouble in three distinct ways: - It has no Bot instance - It has no namespace - It has no parent instance. These happen only if you're using it wrong. To make the test more precise, and to add a little bit more readability (RuntimeError could be anything!), we'll introduce some custom exceptions for these three states. This addresses a review comment by @aeros.
-rw-r--r--bot/utils/redis_cache.py22
-rw-r--r--tests/bot/utils/test_redis_cache.py7
2 files changed, 21 insertions, 8 deletions
diff --git a/bot/utils/redis_cache.py b/bot/utils/redis_cache.py
index 979ea5d47..6b3c68979 100644
--- a/bot/utils/redis_cache.py
+++ b/bot/utils/redis_cache.py
@@ -27,6 +27,18 @@ _KEY_PREFIXES = (
)
+class NoBotInstanceError(RuntimeError):
+ """Raised when RedisCache is created without an available bot instance on the owner class."""
+
+
+class NoNamespaceError(RuntimeError):
+ """Raised when RedisCache has no namespace, for example if it is not assigned to a class attribute."""
+
+
+class NoParentInstanceError(RuntimeError):
+ """Raised when the parent instance is available, for example if called by accessing the parent class directly."""
+
+
class RedisCache:
"""
A simplified interface for a Redis connection.
@@ -149,7 +161,7 @@ class RedisCache:
"This object must be initialized as a class attribute."
)
log.error(error_message)
- raise RuntimeError(error_message)
+ raise NoNamespaceError(error_message)
if self.bot is None:
error_message = (
@@ -159,7 +171,7 @@ class RedisCache:
"the RedisCache inside a class that has a Bot instance attribute."
)
log.error(error_message)
- raise RuntimeError(error_message)
+ raise NoBotInstanceError(error_message)
await self.bot.redis_ready.wait()
@@ -194,7 +206,7 @@ class RedisCache:
if self._namespace is None:
error_message = "RedisCache must be a class attribute."
log.error(error_message)
- raise RuntimeError(error_message)
+ raise NoNamespaceError(error_message)
if instance is None:
error_message = (
@@ -202,7 +214,7 @@ class RedisCache:
"before accessing it using the cog's class object."
)
log.error(error_message)
- raise RuntimeError(error_message)
+ raise NoParentInstanceError(error_message)
for attribute in vars(instance).values():
if isinstance(attribute, Bot):
@@ -217,7 +229,7 @@ class RedisCache:
"the RedisCache inside a class that has a Bot instance attribute."
)
log.error(error_message)
- raise RuntimeError(error_message)
+ raise NoBotInstanceError(error_message)
def __repr__(self) -> str:
"""Return a beautiful representation of this object instance."""
diff --git a/tests/bot/utils/test_redis_cache.py b/tests/bot/utils/test_redis_cache.py
index 4f95dff03..8c1a40640 100644
--- a/tests/bot/utils/test_redis_cache.py
+++ b/tests/bot/utils/test_redis_cache.py
@@ -4,6 +4,7 @@ import unittest
import fakeredis.aioredis
from bot.utils import RedisCache
+from bot.utils.redis_cache import NoBotInstanceError, NoNamespaceError, NoParentInstanceError
from tests import helpers
@@ -260,13 +261,13 @@ class RedisCacheTests(unittest.IsolatedAsyncioTestCase):
cog = MyCog()
# Raises "No Bot instance"
- with self.assertRaises(RuntimeError):
+ with self.assertRaises(NoBotInstanceError):
await cog.cache.get("john")
# Raises "RedisCache has no namespace"
- with self.assertRaises(RuntimeError):
+ with self.assertRaises(NoNamespaceError):
await cog.other_cache.get("was")
# Raises "You must access the RedisCache instance through the cog instance"
- with self.assertRaises(RuntimeError):
+ with self.assertRaises(NoParentInstanceError):
await MyCog.cache.get("afraid")