aboutsummaryrefslogtreecommitdiffstats
path: root/tests/bot
diff options
context:
space:
mode:
authorGravatar ChrisJL <[email protected]>2023-04-11 22:22:47 +0100
committerGravatar GitHub <[email protected]>2023-04-11 22:22:47 +0100
commitf94505ac975888b259ea2d07b4442d6d908352f8 (patch)
treed156f9d7c8dbdc89642e161105766cd3644b931f /tests/bot
parentBump httpx from 0.23.3 to 0.24.0 (#2529) (diff)
parentUse commands.Converter subclass for d.py converters (diff)
Merge pull request #2523 from python-discord/flake8-to-ruff
Migration codestyle from Flake8 to ruff
Diffstat (limited to 'tests/bot')
-rw-r--r--tests/bot/exts/filtering/test_discord_token_filter.py4
-rw-r--r--tests/bot/exts/filtering/test_extension_filter.py2
-rw-r--r--tests/bot/exts/info/test_information.py44
-rw-r--r--tests/bot/exts/moderation/infraction/test_infractions.py5
-rw-r--r--tests/bot/exts/moderation/infraction/test_utils.py14
-rw-r--r--tests/bot/exts/moderation/test_incidents.py4
-rw-r--r--tests/bot/exts/moderation/test_silence.py83
-rw-r--r--tests/bot/exts/moderation/test_slowmode.py20
-rw-r--r--tests/bot/exts/recruitment/talentpool/test_review.py10
-rw-r--r--tests/bot/exts/test_cogs.py2
-rw-r--r--tests/bot/exts/utils/snekbox/test_io.py2
-rw-r--r--tests/bot/exts/utils/snekbox/test_snekbox.py170
-rw-r--r--tests/bot/resources/test_resources.py2
-rw-r--r--tests/bot/test_constants.py8
-rw-r--r--tests/bot/test_converters.py162
-rw-r--r--tests/bot/test_decorators.py8
-rw-r--r--tests/bot/test_pagination.py18
-rw-r--r--tests/bot/utils/test_message_cache.py5
-rw-r--r--tests/bot/utils/test_time.py81
19 files changed, 325 insertions, 319 deletions
diff --git a/tests/bot/exts/filtering/test_discord_token_filter.py b/tests/bot/exts/filtering/test_discord_token_filter.py
index a5cddf8d9..1cb9e16fa 100644
--- a/tests/bot/exts/filtering/test_discord_token_filter.py
+++ b/tests/bot/exts/filtering/test_discord_token_filter.py
@@ -222,8 +222,8 @@ class DiscordTokenFilterTests(unittest.IsolatedAsyncioTestCase):
def test_regex_matches_multiple_valid(self):
"""Should support multiple matches in the middle of a string."""
- token_1 = "NDY3MjIzMjMwNjUwNzc3NjQx.XsyWGg.uFNEQPCc4ePwGh7egG8UicQssz8"
- token_2 = "NDcyMjY1OTQzMDYyNDEzMzMy.XsyWMw.l8XPnDqb0lp-EiQ2g_0xVFT1pyc"
+ token_1 = "NDY3MjIzMjMwNjUwNzc3NjQx.XsyWGg.uFNEQPCc4ePwGh7egG8UicQssz8" # noqa: S105
+ token_2 = "NDcyMjY1OTQzMDYyNDEzMzMy.XsyWMw.l8XPnDqb0lp-EiQ2g_0xVFT1pyc" # noqa: S105
message = f"garbage {token_1} hello {token_2} world"
results = discord_token.TOKEN_RE.finditer(message)
diff --git a/tests/bot/exts/filtering/test_extension_filter.py b/tests/bot/exts/filtering/test_extension_filter.py
index 827d267d2..f71de1e1b 100644
--- a/tests/bot/exts/filtering/test_extension_filter.py
+++ b/tests/bot/exts/filtering/test_extension_filter.py
@@ -25,7 +25,7 @@ class ExtensionsListTests(unittest.IsolatedAsyncioTestCase):
for i, filter_content in enumerate(self.whitelist, start=1):
filters.append({
"id": i, "content": filter_content, "description": None, "settings": {},
- "additional_settings": {}, "created_at": now, "updated_at": now # noqa: P103
+ "additional_settings": {}, "created_at": now, "updated_at": now
})
self.filter_list.add_list({
"id": 1,
diff --git a/tests/bot/exts/info/test_information.py b/tests/bot/exts/info/test_information.py
index 65595e959..e90291f62 100644
--- a/tests/bot/exts/info/test_information.py
+++ b/tests/bot/exts/info/test_information.py
@@ -1,7 +1,7 @@
import textwrap
import unittest
import unittest.mock
-from datetime import datetime
+from datetime import UTC, datetime
from textwrap import shorten
import discord
@@ -41,7 +41,7 @@ class InformationCogTests(unittest.IsolatedAsyncioTestCase):
self.ctx.send.assert_called_once()
_, kwargs = self.ctx.send.call_args
- embed = kwargs.pop('embed')
+ embed = kwargs.pop("embed")
self.assertEqual(embed.title, "Role information (Total 1 role)")
self.assertEqual(embed.colour, discord.Colour.og_blurple())
@@ -110,15 +110,15 @@ class UserInfractionHelperMethodTests(unittest.IsolatedAsyncioTestCase):
test_values = (
{
"helper_method": self.cog.basic_user_infraction_counts,
- "expected_args": ("bot/infractions", {'hidden': 'False', 'user__id': str(self.member.id)}),
+ "expected_args": ("bot/infractions", {"hidden": "False", "user__id": str(self.member.id)}),
},
{
"helper_method": self.cog.expanded_user_infraction_counts,
- "expected_args": ("bot/infractions", {'user__id': str(self.member.id)}),
+ "expected_args": ("bot/infractions", {"user__id": str(self.member.id)}),
},
{
"helper_method": self.cog.user_nomination_counts,
- "expected_args": ("bot/nominations", {'user__id': str(self.member.id)}),
+ "expected_args": ("bot/nominations", {"user__id": str(self.member.id)}),
},
)
@@ -241,19 +241,19 @@ class UserInfractionHelperMethodTests(unittest.IsolatedAsyncioTestCase):
"expected_lines": ["No nominations"],
},
{
- "api response": [{'active': True}],
+ "api response": [{"active": True}],
"expected_lines": ["This user is **currently** nominated", "(1 nomination in total)"],
},
{
- "api response": [{'active': True}, {'active': False}],
+ "api response": [{"active": True}, {"active": False}],
"expected_lines": ["This user is **currently** nominated", "(2 nominations in total)"],
},
{
- "api response": [{'active': False}],
+ "api response": [{"active": False}],
"expected_lines": ["This user has 1 historical nomination, but is currently not nominated."],
},
{
- "api response": [{'active': False}, {'active': False}],
+ "api response": [{"active": False}, {"active": False}],
"expected_lines": ["This user has 2 historical nominations, but is currently not nominated."],
},
@@ -290,7 +290,7 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):
user.nick = None
user.__str__ = unittest.mock.Mock(return_value="Mr. Hemlock")
user.colour = 0
- user.created_at = user.joined_at = datetime.utcnow()
+ user.created_at = user.joined_at = datetime.now(UTC)
embed = await self.cog.create_user_embed(ctx, user, False)
@@ -312,7 +312,7 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):
user.nick = "Cat lover"
user.__str__ = unittest.mock.Mock(return_value="Mr. Hemlock")
user.colour = 0
- user.created_at = user.joined_at = datetime.utcnow()
+ user.created_at = user.joined_at = datetime.now(UTC)
embed = await self.cog.create_user_embed(ctx, user, False)
@@ -329,11 +329,11 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):
async def test_create_user_embed_ignores_everyone_role(self):
"""Created `!user` embeds should not contain mention of the @everyone-role."""
ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=1))
- admins_role = helpers.MockRole(name='Admins')
+ admins_role = helpers.MockRole(name="Admins")
# A `MockMember` has the @Everyone role by default; we add the Admins to that.
user = helpers.MockMember(roles=[admins_role], colour=100)
- user.created_at = user.joined_at = datetime.utcnow()
+ user.created_at = user.joined_at = datetime.now(UTC)
embed = await self.cog.create_user_embed(ctx, user, False)
@@ -354,13 +354,13 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):
"""The embed should contain expanded infractions and nomination info in mod channels."""
ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=50))
- moderators_role = helpers.MockRole(name='Moderators')
+ moderators_role = helpers.MockRole(name="Moderators")
infraction_counts.return_value = ("Infractions", "expanded infractions info")
nomination_counts.return_value = ("Nominations", "nomination info")
user = helpers.MockMember(id=314, roles=[moderators_role], colour=100)
- user.created_at = user.joined_at = datetime.utcfromtimestamp(1)
+ user.created_at = user.joined_at = datetime.fromtimestamp(1, tz=UTC)
embed = await self.cog.create_user_embed(ctx, user, False)
infraction_counts.assert_called_once_with(user)
@@ -394,13 +394,13 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):
"""The embed should contain only basic infraction data outside of mod channels."""
ctx = helpers.MockContext(channel=helpers.MockTextChannel(id=100))
- moderators_role = helpers.MockRole(name='Moderators')
+ moderators_role = helpers.MockRole(name="Moderators")
infraction_counts.return_value = ("Infractions", "basic infractions info")
user_messages.return_value = ("Messages", "user message counts")
user = helpers.MockMember(id=314, roles=[moderators_role], colour=100)
- user.created_at = user.joined_at = datetime.utcfromtimestamp(1)
+ user.created_at = user.joined_at = datetime.fromtimestamp(1, tz=UTC)
embed = await self.cog.create_user_embed(ctx, user, False)
infraction_counts.assert_called_once_with(user)
@@ -444,10 +444,10 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):
"""The embed should be created with the colour of the top role, if a top role is available."""
ctx = helpers.MockContext()
- moderators_role = helpers.MockRole(name='Moderators')
+ moderators_role = helpers.MockRole(name="Moderators")
user = helpers.MockMember(id=314, roles=[moderators_role], colour=100)
- user.created_at = user.joined_at = datetime.utcnow()
+ user.created_at = user.joined_at = datetime.now(UTC)
embed = await self.cog.create_user_embed(ctx, user, False)
self.assertEqual(embed.colour, discord.Colour(100))
@@ -465,7 +465,7 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):
ctx = helpers.MockContext()
user = helpers.MockMember(id=217, colour=discord.Colour.default())
- user.created_at = user.joined_at = datetime.utcnow()
+ user.created_at = user.joined_at = datetime.now(UTC)
embed = await self.cog.create_user_embed(ctx, user, False)
self.assertEqual(embed.colour, discord.Colour.og_blurple())
@@ -483,7 +483,7 @@ class UserEmbedTests(unittest.IsolatedAsyncioTestCase):
ctx = helpers.MockContext()
user = helpers.MockMember(id=217, colour=0)
- user.created_at = user.joined_at = datetime.utcnow()
+ user.created_at = user.joined_at = datetime.now(UTC)
user.display_avatar.url = "avatar url"
embed = await self.cog.create_user_embed(ctx, user, False)
@@ -644,6 +644,6 @@ class RuleCommandTests(unittest.IsolatedAsyncioTestCase):
for raw_user_input, expected_matched_rule_numbers in test_cases:
with self.subTest(identifier=raw_user_input):
final_rule_numbers = await self.cog.rules(self.cog, self.ctx, args=raw_user_input)
- embed = self.ctx.send.call_args.kwargs['embed']
+ embed = self.ctx.send.call_args.kwargs["embed"]
self.assertEqual(information.DEFAULT_RULES_DESCRIPTION, embed.description)
self.assertEqual(expected_matched_rule_numbers, final_rule_numbers)
diff --git a/tests/bot/exts/moderation/infraction/test_infractions.py b/tests/bot/exts/moderation/infraction/test_infractions.py
index b78328137..26ba770dc 100644
--- a/tests/bot/exts/moderation/infraction/test_infractions.py
+++ b/tests/bot/exts/moderation/infraction/test_infractions.py
@@ -270,10 +270,9 @@ class CleanBanTests(unittest.IsolatedAsyncioTestCase):
def inner(name):
if name == "ModManagement":
return self.management_cog if enable_manage else None
- elif name == "Clean":
+ if name == "Clean":
return self.clean_cog if enable_clean else None
- else:
- return DEFAULT
+ return DEFAULT
return inner
async def test_cleanban_falls_back_to_native_purge_without_clean_cog(self):
diff --git a/tests/bot/exts/moderation/infraction/test_utils.py b/tests/bot/exts/moderation/infraction/test_utils.py
index 122935e37..25337673e 100644
--- a/tests/bot/exts/moderation/infraction/test_utils.py
+++ b/tests/bot/exts/moderation/infraction/test_utils.py
@@ -1,6 +1,6 @@
import unittest
from collections import namedtuple
-from datetime import datetime
+from datetime import UTC, datetime
from unittest.mock import AsyncMock, MagicMock, patch
from discord import Embed, Forbidden, HTTPException, NotFound
@@ -136,7 +136,10 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
"""
test_cases = [
{
- "args": (dict(id=0, type="ban", reason=None, expires_at=datetime(2020, 2, 26, 9, 20)), self.user),
+ "args": (
+ dict(id=0, type="ban", reason=None, expires_at=datetime(2020, 2, 26, 9, 20, tzinfo=UTC)),
+ self.user,
+ ),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
@@ -192,7 +195,10 @@ class ModerationUtilsTests(unittest.IsolatedAsyncioTestCase):
"send_result": False
},
{
- "args": (dict(id=0, type="mute", reason="Test", expires_at=datetime(2020, 2, 26, 9, 20)), self.user),
+ "args": (
+ dict(id=0, type="mute", reason="Test", expires_at=datetime(2020, 2, 26, 9, 20, tzinfo=UTC)),
+ self.user,
+ ),
"expected_output": Embed(
title=utils.INFRACTION_TITLE,
description=utils.INFRACTION_DESCRIPTION_TEMPLATE.format(
@@ -309,7 +315,7 @@ class TestPostInfraction(unittest.IsolatedAsyncioTestCase):
async def test_normal_post_infraction(self):
"""Should return response from POST request if there are no errors."""
- now = datetime.utcnow()
+ now = datetime.now(UTC)
expected = {
"actor": self.ctx.author.id,
"hidden": True,
diff --git a/tests/bot/exts/moderation/test_incidents.py b/tests/bot/exts/moderation/test_incidents.py
index 53d98360c..1a02339d4 100644
--- a/tests/bot/exts/moderation/test_incidents.py
+++ b/tests/bot/exts/moderation/test_incidents.py
@@ -20,7 +20,7 @@ from tests.helpers import (
MockUser
)
-CURRENT_TIME = datetime.datetime(2022, 1, 1, tzinfo=datetime.timezone.utc)
+CURRENT_TIME = datetime.datetime(2022, 1, 1, tzinfo=datetime.UTC)
class MockAsyncIterable:
@@ -799,7 +799,7 @@ class TestMessageLinkEmbeds(TestIncidents):
"\n".join("Lets make a new line test".split()): "Lets\nmake\na...",
- 'Hello, World!' * 300: (
+ "Hello, World!" * 300: (
"Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!"
"Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!"
"Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!"
diff --git a/tests/bot/exts/moderation/test_silence.py b/tests/bot/exts/moderation/test_silence.py
index 2622f46a7..ec0b3bf43 100644
--- a/tests/bot/exts/moderation/test_silence.py
+++ b/tests/bot/exts/moderation/test_silence.py
@@ -1,7 +1,6 @@
import itertools
import unittest
-from datetime import datetime, timezone
-from typing import List, Tuple
+from datetime import UTC, datetime
from unittest import mock
from unittest.mock import AsyncMock, Mock
@@ -97,10 +96,12 @@ class SilenceNotifierTests(SilenceTest):
"""Alert is skipped on first loop or not an increment of 900."""
test_cases = (0, 15, 5000)
for current_loop in test_cases:
- with self.subTest(current_loop=current_loop):
- with mock.patch.object(self.notifier, "_current_loop", new=current_loop):
- await self.notifier._notifier()
- self.alert_channel.send.assert_not_called()
+ with (
+ self.subTest(current_loop=current_loop),
+ mock.patch.object(self.notifier, "_current_loop", new=current_loop),
+ ):
+ await self.notifier._notifier()
+ self.alert_channel.send.assert_not_called()
@autospec(silence.Silence, "previous_overwrites", "unsilence_timestamps", pass_mocks=False)
@@ -203,7 +204,7 @@ class SilenceCogTests(SilenceTest):
self.assertEqual((None,), member.move_to.call_args_list[0].args)
@staticmethod
- def create_erroneous_members() -> Tuple[List[MockMember], List[MockMember]]:
+ def create_erroneous_members() -> tuple[list[MockMember], list[MockMember]]:
"""
Helper method to generate a list of members that error out on move_to call.
@@ -363,7 +364,7 @@ class RescheduleTests(RedisTestCase):
channels = [MockTextChannel(id=123), MockTextChannel(id=456)]
self.bot.get_channel.side_effect = channels
self.cog.unsilence_timestamps.items.return_value = [(123, 2000), (456, 3000)]
- silence.datetime.now.return_value = datetime.fromtimestamp(1000, tz=timezone.utc)
+ silence.datetime.now.return_value = datetime.fromtimestamp(1000, tz=UTC)
self.cog._unsilence_wrapper = mock.MagicMock()
unsilence_return = self.cog._unsilence_wrapper.return_value
@@ -426,17 +427,19 @@ class SilenceTests(SilenceTest):
targets = (MockTextChannel(), MockVoiceChannel(), None)
for (duration, message, was_silenced), target in itertools.product(test_cases, targets):
- with mock.patch.object(self.cog, "_set_silence_overwrites", return_value=was_silenced):
- with self.subTest(was_silenced=was_silenced, target=target, message=message):
- with mock.patch.object(self.cog, "send_message") as send_message:
- ctx = MockContext()
- await self.cog.silence.callback(self.cog, ctx, target, duration)
- send_message.assert_called_once_with(
- message,
- ctx.channel,
- target or ctx.channel,
- alert_target=was_silenced
- )
+ with (
+ mock.patch.object(self.cog, "_set_silence_overwrites", return_value=was_silenced),
+ self.subTest(was_silenced=was_silenced, target=target, message=message),
+ mock.patch.object(self.cog, "send_message") as send_message
+ ):
+ ctx = MockContext()
+ await self.cog.silence.callback(self.cog, ctx, target, duration)
+ send_message.assert_called_once_with(
+ message,
+ ctx.channel,
+ target or ctx.channel,
+ alert_target=was_silenced
+ )
@voice_sync_helper
async def test_sync_called(self, ctx, sync, kick):
@@ -577,10 +580,10 @@ class SilenceTests(SilenceTest):
new_overwrite_dict = dict(self.voice_overwrite)
# Remove 'connect' & 'speak' keys because they were changed by the method.
- del prev_overwrite_dict['connect']
- del prev_overwrite_dict['speak']
- del new_overwrite_dict['connect']
- del new_overwrite_dict['speak']
+ del prev_overwrite_dict["connect"]
+ del prev_overwrite_dict["speak"]
+ del new_overwrite_dict["connect"]
+ del new_overwrite_dict["speak"]
self.assertDictEqual(prev_overwrite_dict, new_overwrite_dict)
@@ -617,13 +620,13 @@ class SilenceTests(SilenceTest):
now_timestamp = 100
duration = 15
timestamp = now_timestamp + duration * 60
- datetime_mock.now.return_value = datetime.fromtimestamp(now_timestamp, tz=timezone.utc)
+ datetime_mock.now.return_value = datetime.fromtimestamp(now_timestamp, tz=UTC)
ctx = MockContext(channel=self.text_channel)
await self.cog.silence.callback(self.cog, ctx, duration)
self.cog.unsilence_timestamps.set.assert_awaited_once_with(ctx.channel.id, timestamp)
- datetime_mock.now.assert_called_once_with(tz=timezone.utc) # Ensure it's using an aware dt.
+ datetime_mock.now.assert_called_once_with(tz=UTC) # Ensure it's using an aware dt.
async def test_cached_indefinite_time(self):
"""A value of -1 was cached for a permanent silence."""
@@ -697,13 +700,15 @@ class UnsilenceTests(SilenceTest):
if target:
target.overwrites_for.return_value = overwrite
- with mock.patch.object(self.cog, "_unsilence", return_value=was_unsilenced):
- with mock.patch.object(self.cog, "send_message") as send_message:
- with self.subTest(was_unsilenced=was_unsilenced, overwrite=overwrite, target=target):
- await self.cog.unsilence.callback(self.cog, ctx, channel=target)
+ with (
+ mock.patch.object(self.cog, "_unsilence", return_value=was_unsilenced),
+ mock.patch.object(self.cog, "send_message") as send_message,
+ self.subTest(was_unsilenced=was_unsilenced, overwrite=overwrite, target=target),
+ ):
+ await self.cog.unsilence.callback(self.cog, ctx, channel=target)
- call_args = (message, ctx.channel, target or ctx.channel)
- send_message.assert_awaited_once_with(*call_args, alert_target=was_unsilenced)
+ call_args = (message, ctx.channel, target or ctx.channel)
+ send_message.assert_awaited_once_with(*call_args, alert_target=was_unsilenced)
async def test_skipped_already_unsilenced(self):
"""Permissions were not set and `False` was returned for an already unsilenced channel."""
@@ -808,10 +813,10 @@ class UnsilenceTests(SilenceTest):
new_overwrite_dict = dict(self.text_overwrite)
# Remove these keys because they were modified by the unsilence.
- del prev_overwrite_dict['send_messages']
- del prev_overwrite_dict['add_reactions']
- del new_overwrite_dict['send_messages']
- del new_overwrite_dict['add_reactions']
+ del prev_overwrite_dict["send_messages"]
+ del prev_overwrite_dict["add_reactions"]
+ del new_overwrite_dict["send_messages"]
+ del new_overwrite_dict["add_reactions"]
self.assertDictEqual(prev_overwrite_dict, new_overwrite_dict)
@@ -826,10 +831,10 @@ class UnsilenceTests(SilenceTest):
new_overwrite_dict = dict(self.voice_overwrite)
# Remove these keys because they were modified by the unsilence.
- del prev_overwrite_dict['connect']
- del prev_overwrite_dict['speak']
- del new_overwrite_dict['connect']
- del new_overwrite_dict['speak']
+ del prev_overwrite_dict["connect"]
+ del prev_overwrite_dict["speak"]
+ del new_overwrite_dict["connect"]
+ del new_overwrite_dict["speak"]
self.assertDictEqual(prev_overwrite_dict, new_overwrite_dict)
diff --git a/tests/bot/exts/moderation/test_slowmode.py b/tests/bot/exts/moderation/test_slowmode.py
index 5483b7a64..cf5101e16 100644
--- a/tests/bot/exts/moderation/test_slowmode.py
+++ b/tests/bot/exts/moderation/test_slowmode.py
@@ -17,24 +17,24 @@ class SlowmodeTests(unittest.IsolatedAsyncioTestCase):
async def test_get_slowmode_no_channel(self) -> None:
"""Get slowmode without a given channel."""
- self.ctx.channel = MockTextChannel(name='python-general', slowmode_delay=5)
+ self.ctx.channel = MockTextChannel(name="python-general", slowmode_delay=5)
await self.cog.get_slowmode(self.cog, self.ctx, None)
self.ctx.send.assert_called_once_with("The slowmode delay for #python-general is 5 seconds.")
async def test_get_slowmode_with_channel(self) -> None:
"""Get slowmode with a given channel."""
- text_channel = MockTextChannel(name='python-language', slowmode_delay=2)
+ text_channel = MockTextChannel(name="python-language", slowmode_delay=2)
await self.cog.get_slowmode(self.cog, self.ctx, text_channel)
- self.ctx.send.assert_called_once_with('The slowmode delay for #python-language is 2 seconds.')
+ self.ctx.send.assert_called_once_with("The slowmode delay for #python-language is 2 seconds.")
async def test_set_slowmode_no_channel(self) -> None:
"""Set slowmode without a given channel."""
test_cases = (
- ('helpers', 23, True, f'{Emojis.check_mark} The slowmode delay for #helpers is now 23 seconds.'),
- ('mods', 76526, False, f'{Emojis.cross_mark} The slowmode delay must be between 0 and 6 hours.'),
- ('admins', 97, True, f'{Emojis.check_mark} The slowmode delay for #admins is now 1 minute and 37 seconds.')
+ ("helpers", 23, True, f"{Emojis.check_mark} The slowmode delay for #helpers is now 23 seconds."),
+ ("mods", 76526, False, f"{Emojis.cross_mark} The slowmode delay must be between 0 and 6 hours."),
+ ("admins", 97, True, f"{Emojis.check_mark} The slowmode delay for #admins is now 1 minute and 37 seconds.")
)
for channel_name, seconds, edited, result_msg in test_cases:
@@ -60,9 +60,9 @@ class SlowmodeTests(unittest.IsolatedAsyncioTestCase):
async def test_set_slowmode_with_channel(self) -> None:
"""Set slowmode with a given channel."""
test_cases = (
- ('bot-commands', 12, True, f'{Emojis.check_mark} The slowmode delay for #bot-commands is now 12 seconds.'),
- ('mod-spam', 21, True, f'{Emojis.check_mark} The slowmode delay for #mod-spam is now 21 seconds.'),
- ('admin-spam', 4323598, False, f'{Emojis.cross_mark} The slowmode delay must be between 0 and 6 hours.')
+ ("bot-commands", 12, True, f"{Emojis.check_mark} The slowmode delay for #bot-commands is now 12 seconds."),
+ ("mod-spam", 21, True, f"{Emojis.check_mark} The slowmode delay for #mod-spam is now 21 seconds."),
+ ("admin-spam", 4323598, False, f"{Emojis.cross_mark} The slowmode delay must be between 0 and 6 hours.")
)
for channel_name, seconds, edited, result_msg in test_cases:
@@ -87,7 +87,7 @@ class SlowmodeTests(unittest.IsolatedAsyncioTestCase):
async def test_reset_slowmode_sets_delay_to_zero(self) -> None:
"""Reset slowmode with a given channel."""
- text_channel = MockTextChannel(name='meta', slowmode_delay=1)
+ text_channel = MockTextChannel(name="meta", slowmode_delay=1)
self.cog.set_slowmode = mock.AsyncMock()
await self.cog.reset_slowmode(self.cog, self.ctx, text_channel)
diff --git a/tests/bot/exts/recruitment/talentpool/test_review.py b/tests/bot/exts/recruitment/talentpool/test_review.py
index f726fccc7..25622e91f 100644
--- a/tests/bot/exts/recruitment/talentpool/test_review.py
+++ b/tests/bot/exts/recruitment/talentpool/test_review.py
@@ -1,5 +1,5 @@
import unittest
-from datetime import datetime, timedelta, timezone
+from datetime import UTC, datetime, timedelta
from unittest.mock import AsyncMock, Mock, patch
from bot.exts.recruitment.talentpool import _review
@@ -61,8 +61,8 @@ class ReviewerTests(unittest.IsolatedAsyncioTestCase):
@patch("bot.exts.recruitment.talentpool._review.MIN_REVIEW_INTERVAL", timedelta(days=1))
async def test_is_ready_for_review(self):
"""Tests for the `is_ready_for_review` function."""
- too_recent = datetime.now(timezone.utc) - timedelta(hours=1)
- not_too_recent = datetime.now(timezone.utc) - timedelta(days=7)
+ too_recent = datetime.now(UTC) - timedelta(hours=1)
+ not_too_recent = datetime.now(UTC) - timedelta(days=7)
cases = (
# Only one review, and not too recent, so ready.
(
@@ -126,7 +126,7 @@ class ReviewerTests(unittest.IsolatedAsyncioTestCase):
@patch("bot.exts.recruitment.talentpool._review.MIN_NOMINATION_TIME", timedelta(days=7))
async def test_get_nomination_to_review(self):
"""Test get_nomination_to_review function."""
- now = datetime.now(timezone.utc)
+ now = datetime.now(UTC)
# Each case contains a list of nominations, followed by the index in that list
# of the one that should be selected, or None if None should be returned
@@ -184,7 +184,7 @@ class ReviewerTests(unittest.IsolatedAsyncioTestCase):
@patch("bot.exts.recruitment.talentpool._review.MIN_NOMINATION_TIME", timedelta(days=0))
async def test_get_nomination_to_review_order(self):
- now = datetime.now(timezone.utc)
+ now = datetime.now(UTC)
# Each case in cases is a list of nominations in the order they should be chosen from first to last
cases = [
diff --git a/tests/bot/exts/test_cogs.py b/tests/bot/exts/test_cogs.py
index f8e120262..99bc87120 100644
--- a/tests/bot/exts/test_cogs.py
+++ b/tests/bot/exts/test_cogs.py
@@ -50,7 +50,7 @@ class CommandNameTests(unittest.TestCase):
yield obj
@staticmethod
- def get_qualified_names(command: commands.Command) -> t.List[str]:
+ def get_qualified_names(command: commands.Command) -> list[str]:
"""Return a list of all qualified names, including aliases, for the `command`."""
names = [f"{command.full_parent_name} {alias}".strip() for alias in command.aliases]
names.append(command.qualified_name)
diff --git a/tests/bot/exts/utils/snekbox/test_io.py b/tests/bot/exts/utils/snekbox/test_io.py
index bcf1162b8..4f7f49a5e 100644
--- a/tests/bot/exts/utils/snekbox/test_io.py
+++ b/tests/bot/exts/utils/snekbox/test_io.py
@@ -19,7 +19,7 @@ class SnekboxIOTests(TestCase):
(r"A\0\tB", "A__B"),
# Any other disallowed chars -> underscore
(r"\\.txt", "_.txt"),
- (r"A!@#$%^&*B, C()[]{}+=D.txt", "A_B_C_D.txt"), # noqa: P103
+ (r"A!@#$%^&*B, C()[]{}+=D.txt", "A_B_C_D.txt"),
(" ", "_"),
# Normal file names should be unchanged
("legal_file-name.txt", "legal_file-name.txt"),
diff --git a/tests/bot/exts/utils/snekbox/test_snekbox.py b/tests/bot/exts/utils/snekbox/test_snekbox.py
index 79ac8ea2c..fa28aade8 100644
--- a/tests/bot/exts/utils/snekbox/test_snekbox.py
+++ b/tests/bot/exts/utils/snekbox/test_snekbox.py
@@ -43,7 +43,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
"files": [
{
"path": "main.py",
- "content": b64encode("import random".encode()).decode()
+ "content": b64encode(b"import random").decode()
}
]
}
@@ -72,45 +72,45 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
async def test_codeblock_converter(self):
ctx = MockContext()
cases = (
- ('print("Hello world!")', 'print("Hello world!")', 'non-formatted'),
- ('`print("Hello world!")`', 'print("Hello world!")', 'one line code block'),
- ('```\nprint("Hello world!")```', 'print("Hello world!")', 'multiline code block'),
- ('```py\nprint("Hello world!")```', 'print("Hello world!")', 'multiline python code block'),
- ('text```print("Hello world!")```text', 'print("Hello world!")', 'code block surrounded by text'),
+ ('print("Hello world!")', 'print("Hello world!")', "non-formatted"),
+ ('`print("Hello world!")`', 'print("Hello world!")', "one line code block"),
+ ('```\nprint("Hello world!")```', 'print("Hello world!")', "multiline code block"),
+ ('```py\nprint("Hello world!")```', 'print("Hello world!")', "multiline python code block"),
+ ('text```print("Hello world!")```text', 'print("Hello world!")', "code block surrounded by text"),
('```print("Hello world!")```\ntext\n```py\nprint("Hello world!")```',
- 'print("Hello world!")\nprint("Hello world!")', 'two code blocks with text in-between'),
+ 'print("Hello world!")\nprint("Hello world!")', "two code blocks with text in-between"),
('`print("Hello world!")`\ntext\n```print("How\'s it going?")```',
- 'print("How\'s it going?")', 'code block preceded by inline code'),
+ 'print("How\'s it going?")', "code block preceded by inline code"),
('`print("Hello world!")`\ntext\n`print("Hello world!")`',
- 'print("Hello world!")', 'one inline code block of two')
+ 'print("Hello world!")', "one inline code block of two")
)
for case, expected, testname in cases:
- with self.subTest(msg=f'Extract code from {testname}.'):
+ with self.subTest(msg=f"Extract code from {testname}."):
self.assertEqual(
- '\n'.join(await snekbox.CodeblockConverter.convert(ctx, case)), expected
+ "\n".join(await snekbox.CodeblockConverter.convert(ctx, case)), expected
)
def test_prepare_timeit_input(self):
"""Test the prepare_timeit_input codeblock detection."""
- base_args = ('-m', 'timeit', '-s')
+ base_args = ("-m", "timeit", "-s")
cases = (
- (['print("Hello World")'], '', 'single block of code'),
- (['x = 1', 'print(x)'], 'x = 1', 'two blocks of code'),
- (['x = 1', 'print(x)', 'print("Some other code.")'], 'x = 1', 'three blocks of code')
+ (['print("Hello World")'], "", "single block of code"),
+ (["x = 1", "print(x)"], "x = 1", "two blocks of code"),
+ (["x = 1", "print(x)", 'print("Some other code.")'], "x = 1", "three blocks of code")
)
for case, setup_code, test_name in cases:
setup = snekbox._cog.TIMEIT_SETUP_WRAPPER.format(setup=setup_code)
- expected = [*base_args, setup, '\n'.join(case[1:] if setup_code else case)]
- with self.subTest(msg=f'Test with {test_name} and expected return {expected}'):
+ expected = [*base_args, setup, "\n".join(case[1:] if setup_code else case)]
+ with self.subTest(msg=f"Test with {test_name} and expected return {expected}"):
self.assertEqual(self.cog.prepare_timeit_input(case), expected)
def test_eval_result_message(self):
"""EvalResult.get_message(), should return message."""
cases = (
- ('ERROR', None, ('Your 3.11 eval job has failed', 'ERROR', '')),
- ('', 128 + snekbox._eval.SIGKILL, ('Your 3.11 eval job timed out or ran out of memory', '', '')),
- ('', 255, ('Your 3.11 eval job has failed', 'A fatal NsJail error occurred', ''))
+ ("ERROR", None, ("Your 3.11 eval job has failed", "ERROR", "")),
+ ("", 128 + snekbox._eval.SIGKILL, ("Your 3.11 eval job timed out or ran out of memory", "", "")),
+ ("", 255, ("Your 3.11 eval job has failed", "A fatal NsJail error occurred", ""))
)
for stdout, returncode, expected in cases:
exp_msg, exp_err, exp_files_err = expected
@@ -167,7 +167,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
msg = result.get_failed_files_str(char_max=10)
self.assertEqual(msg, expected)
- @patch('bot.exts.utils.snekbox._eval.Signals', side_effect=ValueError)
+ @patch("bot.exts.utils.snekbox._eval.Signals", side_effect=ValueError)
def test_eval_result_message_invalid_signal(self, _mock_signals: Mock):
result = EvalResult(stdout="", returncode=127)
self.assertEqual(
@@ -177,7 +177,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
self.assertEqual(result.error_message, "")
self.assertEqual(result.files_error_message, "")
- @patch('bot.exts.utils.snekbox._eval.Signals')
+ @patch("bot.exts.utils.snekbox._eval.Signals")
def test_eval_result_message_valid_signal(self, mock_signals: Mock):
mock_signals.return_value.name = "SIGTEST"
result = EvalResult(stdout="", returncode=127)
@@ -189,9 +189,9 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
def test_eval_result_status_emoji(self):
"""Return emoji according to the eval result."""
cases = (
- (' ', -1, ':warning:'),
- ('Hello world!', 0, ':white_check_mark:'),
- ('Invalid beard size', -1, ':x:')
+ (" ", -1, ":warning:"),
+ ("Hello world!", 0, ":white_check_mark:"),
+ ("Invalid beard size", -1, ":x:")
)
for stdout, returncode, expected in cases:
with self.subTest(stdout=stdout, returncode=returncode, expected=expected):
@@ -200,48 +200,48 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
async def test_format_output(self):
"""Test output formatting."""
- self.cog.upload_output = AsyncMock(return_value='https://testificate.com/')
+ self.cog.upload_output = AsyncMock(return_value="https://testificate.com/")
too_many_lines = (
- '001 | v\n002 | e\n003 | r\n004 | y\n005 | l\n006 | o\n'
- '007 | n\n008 | g\n009 | b\n010 | e\n011 | a\n... (truncated - too many lines)'
+ "001 | v\n002 | e\n003 | r\n004 | y\n005 | l\n006 | o\n"
+ "007 | n\n008 | g\n009 | b\n010 | e\n011 | a\n... (truncated - too many lines)"
)
too_long_too_many_lines = (
"\n".join(
- f"{i:03d} | {line}" for i, line in enumerate(['verylongbeard' * 10] * 15, 1)
+ f"{i:03d} | {line}" for i, line in enumerate(["verylongbeard" * 10] * 15, 1)
)[:1000] + "\n... (truncated - too long, too many lines)"
)
cases = (
- ('', ('[No output]', None), 'No output'),
- ('My awesome output', ('My awesome output', None), 'One line output'),
- ('<@', ("<@\u200B", None), r'Convert <@ to <@\u200B'),
- ('<!@', ("<!@\u200B", None), r'Convert <!@ to <!@\u200B'),
+ ("", ("[No output]", None), "No output"),
+ ("My awesome output", ("My awesome output", None), "One line output"),
+ ("<@", ("<@\u200B", None), r"Convert <@ to <@\u200B"),
+ ("<!@", ("<!@\u200B", None), r"Convert <!@ to <!@\u200B"),
(
- '\u202E\u202E\u202E',
- ('Code block escape attempt detected; will not output result', 'https://testificate.com/'),
- 'Detect RIGHT-TO-LEFT OVERRIDE'
+ "\u202E\u202E\u202E",
+ ("Code block escape attempt detected; will not output result", "https://testificate.com/"),
+ "Detect RIGHT-TO-LEFT OVERRIDE"
),
(
- '\u200B\u200B\u200B',
- ('Code block escape attempt detected; will not output result', 'https://testificate.com/'),
- 'Detect ZERO WIDTH SPACE'
+ "\u200B\u200B\u200B",
+ ("Code block escape attempt detected; will not output result", "https://testificate.com/"),
+ "Detect ZERO WIDTH SPACE"
),
- ('long\nbeard', ('001 | long\n002 | beard', None), 'Two line output'),
+ ("long\nbeard", ("001 | long\n002 | beard", None), "Two line output"),
(
- 'v\ne\nr\ny\nl\no\nn\ng\nb\ne\na\nr\nd',
- (too_many_lines, 'https://testificate.com/'),
- '12 lines output'
+ "v\ne\nr\ny\nl\no\nn\ng\nb\ne\na\nr\nd",
+ (too_many_lines, "https://testificate.com/"),
+ "12 lines output"
),
(
- 'verylongbeard' * 100,
- ('verylongbeard' * 76 + 'verylongbear\n... (truncated - too long)', 'https://testificate.com/'),
- '1300 characters output'
+ "verylongbeard" * 100,
+ ("verylongbeard" * 76 + "verylongbear\n... (truncated - too long)", "https://testificate.com/"),
+ "1300 characters output"
),
(
- ('verylongbeard' * 10 + '\n') * 15,
- (too_long_too_many_lines, 'https://testificate.com/'),
- '15 lines, 1965 characters output'
+ ("verylongbeard" * 10 + "\n") * 15,
+ (too_long_too_many_lines, "https://testificate.com/"),
+ "15 lines, 1965 characters output"
),
)
for case, expected, testname in cases:
@@ -257,10 +257,10 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
self.cog.send_job = AsyncMock(return_value=response)
self.cog.continue_job = AsyncMock(return_value=None)
- await self.cog.eval_command(self.cog, ctx=ctx, python_version='3.11', code=['MyAwesomeCode'])
+ await self.cog.eval_command(self.cog, ctx=ctx, python_version="3.11", code=["MyAwesomeCode"])
job = EvalJob.from_code("MyAwesomeCode")
self.cog.send_job.assert_called_once_with(ctx, job)
- self.cog.continue_job.assert_called_once_with(ctx, response, 'eval')
+ self.cog.continue_job.assert_called_once_with(ctx, response, "eval")
async def test_eval_command_evaluate_twice(self):
"""Test the eval and re-eval command procedure."""
@@ -269,9 +269,9 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
ctx.command = MagicMock()
self.cog.send_job = AsyncMock(return_value=response)
self.cog.continue_job = AsyncMock()
- self.cog.continue_job.side_effect = (EvalJob.from_code('MyAwesomeFormattedCode'), None)
+ self.cog.continue_job.side_effect = (EvalJob.from_code("MyAwesomeFormattedCode"), None)
- await self.cog.eval_command(self.cog, ctx=ctx, python_version='3.11', code=['MyAwesomeCode'])
+ await self.cog.eval_command(self.cog, ctx=ctx, python_version="3.11", code=["MyAwesomeCode"])
expected_job = EvalJob.from_code("MyAwesomeFormattedCode")
self.cog.send_job.assert_called_with(ctx, expected_job)
@@ -285,7 +285,7 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
async def delay_with_side_effect(*args, **kwargs) -> dict:
"""Delay the post_job call to ensure the job runs long enough to conflict."""
await asyncio.sleep(1)
- return {'stdout': '', 'returncode': 0}
+ return {"stdout": "", "returncode": 0}
self.cog.post_job = AsyncMock(side_effect=delay_with_side_effect)
with self.assertRaises(LockedResourceError):
@@ -299,32 +299,32 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
ctx = MockContext()
ctx.message = MockMessage()
ctx.send = AsyncMock()
- ctx.author = MockUser(mention='@LemonLemonishBeard#0042')
+ ctx.author = MockUser(mention="@LemonLemonishBeard#0042")
eval_result = EvalResult("", 0)
self.cog.post_job = AsyncMock(return_value=eval_result)
- self.cog.format_output = AsyncMock(return_value=('[No output]', None))
+ self.cog.format_output = AsyncMock(return_value=("[No output]", None))
self.cog.upload_output = AsyncMock() # Should not be called
mocked_filter_cog = MagicMock()
mocked_filter_cog.filter_snekbox_output = AsyncMock(return_value=(False, []))
self.bot.get_cog.return_value = mocked_filter_cog
- job = EvalJob.from_code('MyAwesomeCode')
+ job = EvalJob.from_code("MyAwesomeCode")
await self.cog.send_job(ctx, job),
ctx.send.assert_called_once()
self.assertEqual(
ctx.send.call_args.args[0],
- '@LemonLemonishBeard#0042 :warning: Your 3.11 eval job has completed '
- 'with return code 0.\n\n```\n[No output]\n```'
+ "@LemonLemonishBeard#0042 :warning: Your 3.11 eval job has completed "
+ "with return code 0.\n\n```\n[No output]\n```"
)
- allowed_mentions = ctx.send.call_args.kwargs['allowed_mentions']
+ allowed_mentions = ctx.send.call_args.kwargs["allowed_mentions"]
expected_allowed_mentions = AllowedMentions(everyone=False, roles=False, users=[ctx.author])
self.assertEqual(allowed_mentions.to_dict(), expected_allowed_mentions.to_dict())
self.cog.post_job.assert_called_once_with(job)
- self.cog.format_output.assert_called_once_with('')
+ self.cog.format_output.assert_called_once_with("")
self.cog.upload_output.assert_not_called()
async def test_send_job_with_paste_link(self):
@@ -332,11 +332,11 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
ctx = MockContext()
ctx.message = MockMessage()
ctx.send = AsyncMock()
- ctx.author.mention = '@LemonLemonishBeard#0042'
+ ctx.author.mention = "@LemonLemonishBeard#0042"
eval_result = EvalResult("Way too long beard", 0)
self.cog.post_job = AsyncMock(return_value=eval_result)
- self.cog.format_output = AsyncMock(return_value=('Way too long beard', 'lookatmybeard.com'))
+ self.cog.format_output = AsyncMock(return_value=("Way too long beard", "lookatmybeard.com"))
mocked_filter_cog = MagicMock()
mocked_filter_cog.filter_snekbox_output = AsyncMock(return_value=(False, []))
@@ -348,20 +348,20 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
ctx.send.assert_called_once()
self.assertEqual(
ctx.send.call_args.args[0],
- '@LemonLemonishBeard#0042 :white_check_mark: Your 3.11 eval job '
- 'has completed with return code 0.'
- '\n\n```\nWay too long beard\n```\nFull output: lookatmybeard.com'
+ "@LemonLemonishBeard#0042 :white_check_mark: Your 3.11 eval job "
+ "has completed with return code 0."
+ "\n\n```\nWay too long beard\n```\nFull output: lookatmybeard.com"
)
self.cog.post_job.assert_called_once_with(job)
- self.cog.format_output.assert_called_once_with('Way too long beard')
+ self.cog.format_output.assert_called_once_with("Way too long beard")
async def test_send_job_with_non_zero_eval(self):
"""Test the send_job function with a code returning a non-zero code."""
ctx = MockContext()
ctx.message = MockMessage()
ctx.send = AsyncMock()
- ctx.author.mention = '@LemonLemonishBeard#0042'
+ ctx.author.mention = "@LemonLemonishBeard#0042"
eval_result = EvalResult("ERROR", 127)
self.cog.post_job = AsyncMock(return_value=eval_result)
@@ -377,8 +377,8 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
ctx.send.assert_called_once()
self.assertEqual(
ctx.send.call_args.args[0],
- '@LemonLemonishBeard#0042 :x: Your 3.11 eval job has completed with return code 127.'
- '\n\n```\nERROR\n```'
+ "@LemonLemonishBeard#0042 :x: Your 3.11 eval job has completed with return code 127."
+ "\n\n```\nERROR\n```"
)
self.cog.post_job.assert_called_once_with(job)
@@ -436,11 +436,11 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
self.bot.wait_for.assert_has_awaits(
(
call(
- 'message_edit',
+ "message_edit",
check=partial_mock(snekbox._cog.predicate_message_edit, ctx),
timeout=snekbox._cog.REDO_TIMEOUT,
),
- call('reaction_add', check=partial_mock(snekbox._cog.predicate_emoji_reaction, ctx), timeout=10)
+ call("reaction_add", check=partial_mock(snekbox._cog.predicate_emoji_reaction, ctx), timeout=10)
)
)
ctx.message.add_reaction.assert_called_once_with(snekbox._cog.REDO_EMOJI)
@@ -483,17 +483,17 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
def test_predicate_message_edit(self):
"""Test the predicate_message_edit function."""
- msg0 = MockMessage(id=1, content='abc')
- msg1 = MockMessage(id=2, content='abcdef')
- msg2 = MockMessage(id=1, content='abcdef')
+ msg0 = MockMessage(id=1, content="abc")
+ msg1 = MockMessage(id=2, content="abcdef")
+ msg2 = MockMessage(id=1, content="abcdef")
cases = (
- (msg0, msg0, False, 'same ID, same content'),
- (msg0, msg1, False, 'different ID, different content'),
- (msg0, msg2, True, 'same ID, different content')
+ (msg0, msg0, False, "same ID, same content"),
+ (msg0, msg1, False, "different ID, different content"),
+ (msg0, msg2, True, "same ID, different content")
)
for ctx_msg, new_msg, expected, testname in cases:
- with self.subTest(msg=f'Messages with {testname} return {expected}'):
+ with self.subTest(msg=f"Messages with {testname} return {expected}"):
ctx = MockContext(message=ctx_msg)
actual = snekbox._cog.predicate_message_edit(ctx, ctx_msg, new_msg)
self.assertEqual(actual, expected)
@@ -509,16 +509,16 @@ class SnekboxTests(unittest.IsolatedAsyncioTestCase):
invalid_reaction_id.__str__.return_value = snekbox._cog.REDO_EMOJI
invalid_user_id = MockUser(id=42)
invalid_reaction_str = MockReaction(message=MockMessage(id=1))
- invalid_reaction_str.__str__.return_value = ':longbeard:'
+ invalid_reaction_str.__str__.return_value = ":longbeard:"
cases = (
- (invalid_reaction_id, valid_user, False, 'invalid reaction ID'),
- (valid_reaction, invalid_user_id, False, 'invalid user ID'),
- (invalid_reaction_str, valid_user, False, 'invalid reaction __str__'),
- (valid_reaction, valid_user, True, 'matching attributes')
+ (invalid_reaction_id, valid_user, False, "invalid reaction ID"),
+ (valid_reaction, invalid_user_id, False, "invalid user ID"),
+ (invalid_reaction_str, valid_user, False, "invalid reaction __str__"),
+ (valid_reaction, valid_user, True, "matching attributes")
)
for reaction, user, expected, testname in cases:
- with self.subTest(msg=f'Test with {testname} and expected return {expected}'):
+ with self.subTest(msg=f"Test with {testname} and expected return {expected}"):
actual = snekbox._cog.predicate_emoji_reaction(valid_ctx, reaction, user)
self.assertEqual(actual, expected)
diff --git a/tests/bot/resources/test_resources.py b/tests/bot/resources/test_resources.py
index 73937cfa6..77f92f100 100644
--- a/tests/bot/resources/test_resources.py
+++ b/tests/bot/resources/test_resources.py
@@ -7,7 +7,7 @@ class ResourceValidationTests(unittest.TestCase):
"""Validates resources used by the bot."""
def test_stars_valid(self):
"""The resource `bot/resources/stars.json` should contain a list of strings."""
- path = Path('bot', 'resources', 'stars.json')
+ path = Path("bot", "resources", "stars.json")
content = path.read_text()
data = json.loads(content)
diff --git a/tests/bot/test_constants.py b/tests/bot/test_constants.py
index f10d6fbe8..3492021ce 100644
--- a/tests/bot/test_constants.py
+++ b/tests/bot/test_constants.py
@@ -23,11 +23,7 @@ def is_annotation_instance(value: typing.Any, annotation: typing.Any) -> bool:
def is_any_instance(value: typing.Any, types: typing.Collection) -> bool:
"""Return True if `value` is an instance of any type in `types`."""
- for type_ in types:
- if is_annotation_instance(value, type_):
- return True
-
- return False
+ return any(is_annotation_instance(value, type_) for type_ in types)
class ConstantsTests(unittest.TestCase):
@@ -39,7 +35,7 @@ class ConstantsTests(unittest.TestCase):
sections = (
cls
for (name, cls) in inspect.getmembers(constants)
- if hasattr(cls, 'section') and isinstance(cls, type)
+ if hasattr(cls, "section") and isinstance(cls, type)
)
for section in sections:
for name, annotation in section.__annotations__.items():
diff --git a/tests/bot/test_converters.py b/tests/bot/test_converters.py
index 1bb678db2..e5ccf27f7 100644
--- a/tests/bot/test_converters.py
+++ b/tests/bot/test_converters.py
@@ -1,6 +1,6 @@
import re
import unittest
-from datetime import MAXYEAR, datetime, timezone
+from datetime import MAXYEAR, UTC, datetime
from unittest.mock import MagicMock, patch
from dateutil.relativedelta import relativedelta
@@ -15,13 +15,13 @@ class ConverterTests(unittest.IsolatedAsyncioTestCase):
@classmethod
def setUpClass(cls):
cls.context = MagicMock
- cls.context.author = 'bob'
+ cls.context.author = "bob"
- cls.fixed_utc_now = datetime.fromisoformat('2019-01-01T00:00:00+00:00')
+ cls.fixed_utc_now = datetime.fromisoformat("2019-01-01T00:00:00+00:00")
async def test_package_name_for_valid(self):
"""PackageName returns valid package names unchanged."""
- test_values = ('foo', 'le_mon', 'num83r')
+ test_values = ("foo", "le_mon", "num83r")
for name in test_values:
with self.subTest(identifier=name):
@@ -30,47 +30,46 @@ class ConverterTests(unittest.IsolatedAsyncioTestCase):
async def test_package_name_for_invalid(self):
"""PackageName raises the proper exception for invalid package names."""
- test_values = ('text_with_a_dot.', 'UpperCaseName', 'dashed-name')
+ test_values = ("text_with_a_dot.", "UpperCaseName", "dashed-name")
for name in test_values:
- with self.subTest(identifier=name):
- with self.assertRaises(BadArgument):
- await PackageName.convert(self.context, name)
+ with self.subTest(identifier=name), self.assertRaises(BadArgument):
+ await PackageName.convert(self.context, name)
async def test_duration_converter_for_valid(self):
"""Duration returns the correct `datetime` for valid duration strings."""
test_values = (
# Simple duration strings
- ('1Y', {"years": 1}),
- ('1y', {"years": 1}),
- ('1year', {"years": 1}),
- ('1years', {"years": 1}),
- ('1m', {"months": 1}),
- ('1month', {"months": 1}),
- ('1months', {"months": 1}),
- ('1w', {"weeks": 1}),
- ('1W', {"weeks": 1}),
- ('1week', {"weeks": 1}),
- ('1weeks', {"weeks": 1}),
- ('1d', {"days": 1}),
- ('1D', {"days": 1}),
- ('1day', {"days": 1}),
- ('1days', {"days": 1}),
- ('1h', {"hours": 1}),
- ('1H', {"hours": 1}),
- ('1hour', {"hours": 1}),
- ('1hours', {"hours": 1}),
- ('1M', {"minutes": 1}),
- ('1minute', {"minutes": 1}),
- ('1minutes', {"minutes": 1}),
- ('1s', {"seconds": 1}),
- ('1S', {"seconds": 1}),
- ('1second', {"seconds": 1}),
- ('1seconds', {"seconds": 1}),
+ ("1Y", {"years": 1}),
+ ("1y", {"years": 1}),
+ ("1year", {"years": 1}),
+ ("1years", {"years": 1}),
+ ("1m", {"months": 1}),
+ ("1month", {"months": 1}),
+ ("1months", {"months": 1}),
+ ("1w", {"weeks": 1}),
+ ("1W", {"weeks": 1}),
+ ("1week", {"weeks": 1}),
+ ("1weeks", {"weeks": 1}),
+ ("1d", {"days": 1}),
+ ("1D", {"days": 1}),
+ ("1day", {"days": 1}),
+ ("1days", {"days": 1}),
+ ("1h", {"hours": 1}),
+ ("1H", {"hours": 1}),
+ ("1hour", {"hours": 1}),
+ ("1hours", {"hours": 1}),
+ ("1M", {"minutes": 1}),
+ ("1minute", {"minutes": 1}),
+ ("1minutes", {"minutes": 1}),
+ ("1s", {"seconds": 1}),
+ ("1S", {"seconds": 1}),
+ ("1second", {"seconds": 1}),
+ ("1seconds", {"seconds": 1}),
# Complex duration strings
(
- '1y1m1w1d1H1M1S',
+ "1y1m1w1d1H1M1S",
{
"years": 1,
"months": 1,
@@ -81,13 +80,13 @@ class ConverterTests(unittest.IsolatedAsyncioTestCase):
"seconds": 1
}
),
- ('5y100S', {"years": 5, "seconds": 100}),
- ('2w28H', {"weeks": 2, "hours": 28}),
+ ("5y100S", {"years": 5, "seconds": 100}),
+ ("2w28H", {"weeks": 2, "hours": 28}),
# Duration strings with spaces
- ('1 year 2 months', {"years": 1, "months": 2}),
- ('1d 2H', {"days": 1, "hours": 2}),
- ('1 week2 days', {"weeks": 1, "days": 2}),
+ ("1 year 2 months", {"years": 1, "months": 2}),
+ ("1d 2H", {"days": 1, "hours": 2}),
+ ("1 week2 days", {"weeks": 1, "days": 2}),
)
converter = Duration()
@@ -95,7 +94,7 @@ class ConverterTests(unittest.IsolatedAsyncioTestCase):
for duration, duration_dict in test_values:
expected_datetime = self.fixed_utc_now + relativedelta(**duration_dict)
- with patch('bot.converters.datetime') as mock_datetime:
+ with patch("bot.converters.datetime") as mock_datetime:
mock_datetime.now.return_value = self.fixed_utc_now
with self.subTest(duration=duration, duration_dict=duration_dict):
@@ -106,19 +105,19 @@ class ConverterTests(unittest.IsolatedAsyncioTestCase):
"""Duration raises the right exception for invalid duration strings."""
test_values = (
# Units in wrong order
- '1d1w',
- '1s1y',
+ "1d1w",
+ "1s1y",
# Duplicated units
- '1 year 2 years',
- '1 M 10 minutes',
+ "1 year 2 years",
+ "1 M 10 minutes",
# Unknown substrings
- '1MVes',
- '1y3breads',
+ "1MVes",
+ "1y3breads",
# Missing amount
- 'ym',
+ "ym",
# Incorrect whitespace
" 1y",
@@ -126,15 +125,15 @@ class ConverterTests(unittest.IsolatedAsyncioTestCase):
"1y 1m",
# Garbage
- 'Guido van Rossum',
- 'lemon lemon lemon lemon lemon lemon lemon',
+ "Guido van Rossum",
+ "lemon lemon lemon lemon lemon lemon lemon",
)
converter = Duration()
for invalid_duration in test_values:
with self.subTest(invalid_duration=invalid_duration):
- exception_message = f'`{invalid_duration}` is not a valid duration string.'
+ exception_message = f"`{invalid_duration}` is not a valid duration string."
with self.assertRaisesRegex(BadArgument, re.escape(exception_message)):
await converter.convert(self.context, invalid_duration)
@@ -151,44 +150,43 @@ class ConverterTests(unittest.IsolatedAsyncioTestCase):
async def test_isodatetime_converter_for_valid(self):
"""ISODateTime converter returns correct datetime for valid datetime string."""
- utc = timezone.utc
test_values = (
# `YYYY-mm-ddTHH:MM:SSZ` | `YYYY-mm-dd HH:MM:SSZ`
- ('2019-09-02T02:03:05Z', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
- ('2019-09-02 02:03:05Z', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
+ ("2019-09-02T02:03:05Z", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
+ ("2019-09-02 02:03:05Z", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
# `YYYY-mm-ddTHH:MM:SS±HH:MM` | `YYYY-mm-dd HH:MM:SS±HH:MM`
- ('2019-09-02T03:18:05+01:15', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
- ('2019-09-02 03:18:05+01:15', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
- ('2019-09-02T00:48:05-01:15', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
- ('2019-09-02 00:48:05-01:15', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
+ ("2019-09-02T03:18:05+01:15", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
+ ("2019-09-02 03:18:05+01:15", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
+ ("2019-09-02T00:48:05-01:15", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
+ ("2019-09-02 00:48:05-01:15", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
# `YYYY-mm-ddTHH:MM:SS±HHMM` | `YYYY-mm-dd HH:MM:SS±HHMM`
- ('2019-09-02T03:18:05+0115', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
- ('2019-09-02 03:18:05+0115', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
- ('2019-09-02T00:48:05-0115', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
- ('2019-09-02 00:48:05-0115', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
+ ("2019-09-02T03:18:05+0115", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
+ ("2019-09-02 03:18:05+0115", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
+ ("2019-09-02T00:48:05-0115", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
+ ("2019-09-02 00:48:05-0115", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
# `YYYY-mm-ddTHH:MM:SS±HH` | `YYYY-mm-dd HH:MM:SS±HH`
- ('2019-09-02 03:03:05+01', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
- ('2019-09-02T01:03:05-01', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
+ ("2019-09-02 03:03:05+01", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
+ ("2019-09-02T01:03:05-01", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
# `YYYY-mm-ddTHH:MM:SS` | `YYYY-mm-dd HH:MM:SS`
- ('2019-09-02T02:03:05', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
- ('2019-09-02 02:03:05', datetime(2019, 9, 2, 2, 3, 5, tzinfo=utc)),
+ ("2019-09-02T02:03:05", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
+ ("2019-09-02 02:03:05", datetime(2019, 9, 2, 2, 3, 5, tzinfo=UTC)),
# `YYYY-mm-ddTHH:MM` | `YYYY-mm-dd HH:MM`
- ('2019-11-12T09:15', datetime(2019, 11, 12, 9, 15, tzinfo=utc)),
- ('2019-11-12 09:15', datetime(2019, 11, 12, 9, 15, tzinfo=utc)),
+ ("2019-11-12T09:15", datetime(2019, 11, 12, 9, 15, tzinfo=UTC)),
+ ("2019-11-12 09:15", datetime(2019, 11, 12, 9, 15, tzinfo=UTC)),
# `YYYY-mm-dd`
- ('2019-04-01', datetime(2019, 4, 1, tzinfo=utc)),
+ ("2019-04-01", datetime(2019, 4, 1, tzinfo=UTC)),
# `YYYY-mm`
- ('2019-02-01', datetime(2019, 2, 1, tzinfo=utc)),
+ ("2019-02-01", datetime(2019, 2, 1, tzinfo=UTC)),
# `YYYY`
- ('2025', datetime(2025, 1, 1, tzinfo=utc)),
+ ("2025", datetime(2025, 1, 1, tzinfo=UTC)),
)
converter = ISODateTime()
@@ -202,19 +200,19 @@ class ConverterTests(unittest.IsolatedAsyncioTestCase):
"""ISODateTime converter raises the correct exception for invalid datetime strings."""
test_values = (
# Make sure it doesn't interfere with the Duration converter
- '1Y',
- '1d',
- '1H',
+ "1Y",
+ "1d",
+ "1H",
# Check if it fails when only providing the optional time part
- '10:10:10',
- '10:00',
+ "10:10:10",
+ "10:00",
# Invalid date format
- '19-01-01',
+ "19-01-01",
# Other non-valid strings
- 'fisk the tag master',
+ "fisk the tag master",
)
converter = ISODateTime()
@@ -249,6 +247,8 @@ class ConverterTests(unittest.IsolatedAsyncioTestCase):
)
converter = HushDurationConverter()
for invalid_minutes_string, exception_message in test_values:
- with self.subTest(invalid_minutes_string=invalid_minutes_string, exception_message=exception_message):
- with self.assertRaisesRegex(BadArgument, re.escape(exception_message)):
- await converter.convert(self.context, invalid_minutes_string)
+ with (
+ self.subTest(invalid_minutes_string=invalid_minutes_string, exception_message=exception_message),
+ self.assertRaisesRegex(BadArgument, re.escape(exception_message)),
+ ):
+ await converter.convert(self.context, invalid_minutes_string)
diff --git a/tests/bot/test_decorators.py b/tests/bot/test_decorators.py
index 3d450caa0..6a04123a7 100644
--- a/tests/bot/test_decorators.py
+++ b/tests/bot/test_decorators.py
@@ -142,6 +142,8 @@ class InWhitelistTests(unittest.TestCase):
with unittest.mock.patch("bot.decorators.commands.check", new=lambda predicate: predicate):
predicate = in_whitelist(**test_case.kwargs)
- with self.subTest(test_description=test_case.description):
- with self.assertRaisesRegex(InWhitelistCheckFailure, exception_message):
- predicate(test_case.ctx)
+ with (
+ self.subTest(test_description=test_case.description),
+ self.assertRaisesRegex(InWhitelistCheckFailure, exception_message),
+ ):
+ predicate(test_case.ctx)
diff --git a/tests/bot/test_pagination.py b/tests/bot/test_pagination.py
index 630f2516d..cf23f1948 100644
--- a/tests/bot/test_pagination.py
+++ b/tests/bot/test_pagination.py
@@ -8,39 +8,39 @@ class LinePaginatorTests(TestCase):
def setUp(self):
"""Create a paginator for the test method."""
- self.paginator = pagination.LinePaginator(prefix='', suffix='', max_size=30,
+ self.paginator = pagination.LinePaginator(prefix="", suffix="", max_size=30,
scale_to_size=50)
def test_add_line_works_on_small_lines(self):
"""`add_line` should allow small lines to be added."""
- self.paginator.add_line('x' * (self.paginator.max_size - 3))
+ self.paginator.add_line("x" * (self.paginator.max_size - 3))
# Note that the page isn't added to _pages until it's full.
self.assertEqual(len(self.paginator._pages), 0)
def test_add_line_works_on_long_lines(self):
"""After additional lines after `max_size` is exceeded should go on the next page."""
- self.paginator.add_line('x' * self.paginator.max_size)
+ self.paginator.add_line("x" * self.paginator.max_size)
self.assertEqual(len(self.paginator._pages), 0)
# Any additional lines should start a new page after `max_size` is exceeded.
- self.paginator.add_line('x')
+ self.paginator.add_line("x")
self.assertEqual(len(self.paginator._pages), 1)
def test_add_line_continuation(self):
"""When `scale_to_size` is exceeded, remaining words should be split onto the next page."""
- self.paginator.add_line('zyz ' * (self.paginator.scale_to_size//4 + 1))
+ self.paginator.add_line("zyz " * (self.paginator.scale_to_size//4 + 1))
self.assertEqual(len(self.paginator._pages), 1)
def test_add_line_no_continuation(self):
"""If adding a new line to an existing page would exceed `max_size`, it should start a new
page rather than using continuation.
"""
- self.paginator.add_line('z' * (self.paginator.max_size - 3))
- self.paginator.add_line('z')
+ self.paginator.add_line("z" * (self.paginator.max_size - 3))
+ self.paginator.add_line("z")
self.assertEqual(len(self.paginator._pages), 1)
def test_add_line_truncates_very_long_words(self):
"""`add_line` should truncate if a single long word exceeds `scale_to_size`."""
- self.paginator.add_line('x' * (self.paginator.scale_to_size + 1))
+ self.paginator.add_line("x" * (self.paginator.scale_to_size + 1))
# Note: item at index 1 is the truncated line, index 0 is prefix
- self.assertEqual(self.paginator._current_page[1], 'x' * self.paginator.scale_to_size)
+ self.assertEqual(self.paginator._current_page[1], "x" * self.paginator.scale_to_size)
diff --git a/tests/bot/utils/test_message_cache.py b/tests/bot/utils/test_message_cache.py
index 04bfd28d1..ad3f4e8b6 100644
--- a/tests/bot/utils/test_message_cache.py
+++ b/tests/bot/utils/test_message_cache.py
@@ -157,9 +157,8 @@ class TestMessageCache(unittest.TestCase):
cache.append(msg)
for current_loop in test_cases:
- with self.subTest(current_loop=current_loop):
- with self.assertRaises(IndexError):
- cache[current_loop]
+ with self.subTest(current_loop=current_loop), self.assertRaises(IndexError):
+ cache[current_loop]
def test_slicing_with_unfilled_cache(self):
"""Test if slicing returns the correct messages if the cache is not yet fully filled."""
diff --git a/tests/bot/utils/test_time.py b/tests/bot/utils/test_time.py
index 120d65176..6244a3548 100644
--- a/tests/bot/utils/test_time.py
+++ b/tests/bot/utils/test_time.py
@@ -1,5 +1,5 @@
import unittest
-from datetime import datetime, timezone
+from datetime import UTC, datetime
from dateutil.relativedelta import relativedelta
@@ -13,23 +13,23 @@ class TimeTests(unittest.TestCase):
"""humanize_delta should be able to handle unknown units, and will not abort."""
# Does not abort for unknown units, as the unit name is checked
# against the attribute of the relativedelta instance.
- actual = time.humanize_delta(relativedelta(days=2, hours=2), precision='elephants', max_units=2)
- self.assertEqual(actual, '2 days and 2 hours')
+ actual = time.humanize_delta(relativedelta(days=2, hours=2), precision="elephants", max_units=2)
+ self.assertEqual(actual, "2 days and 2 hours")
def test_humanize_delta_handle_high_units(self):
"""humanize_delta should be able to handle very high units."""
# Very high maximum units, but it only ever iterates over
# each value the relativedelta might have.
- actual = time.humanize_delta(relativedelta(days=2, hours=2), precision='hours', max_units=20)
- self.assertEqual(actual, '2 days and 2 hours')
+ actual = time.humanize_delta(relativedelta(days=2, hours=2), precision="hours", max_units=20)
+ self.assertEqual(actual, "2 days and 2 hours")
def test_humanize_delta_should_normal_usage(self):
"""Testing humanize delta."""
test_cases = (
- (relativedelta(days=2), 'seconds', 1, '2 days'),
- (relativedelta(days=2, hours=2), 'seconds', 2, '2 days and 2 hours'),
- (relativedelta(days=2, hours=2), 'seconds', 1, '2 days'),
- (relativedelta(days=2, hours=2), 'days', 2, '2 days'),
+ (relativedelta(days=2), "seconds", 1, "2 days"),
+ (relativedelta(days=2, hours=2), "seconds", 2, "2 days and 2 hours"),
+ (relativedelta(days=2, hours=2), "seconds", 1, "2 days"),
+ (relativedelta(days=2, hours=2), "days", 2, "2 days"),
)
for delta, precision, max_units, expected in test_cases:
@@ -43,8 +43,8 @@ class TimeTests(unittest.TestCase):
for max_units in test_cases:
with self.subTest(max_units=max_units), self.assertRaises(ValueError) as error:
- time.humanize_delta(relativedelta(days=2, hours=2), precision='hours', max_units=max_units)
- self.assertEqual(str(error.exception), 'max_units must be positive.')
+ time.humanize_delta(relativedelta(days=2, hours=2), precision="hours", max_units=max_units)
+ self.assertEqual(str(error.exception), "max_units must be positive.")
def test_format_with_duration_none_expiry(self):
"""format_with_duration should work for None expiry."""
@@ -52,9 +52,9 @@ class TimeTests(unittest.TestCase):
(None, None, None, None),
# To make sure that date_from and max_units are not touched
- (None, 'Why hello there!', None, None),
- (None, None, float('inf'), None),
- (None, 'Why hello there!', float('inf'), None),
+ (None, "Why hello there!", None, None),
+ (None, None, float("inf"), None),
+ (None, "Why hello there!", float("inf"), None),
)
for expiry, date_from, max_units, expected in test_cases:
@@ -64,10 +64,10 @@ class TimeTests(unittest.TestCase):
def test_format_with_duration_custom_units(self):
"""format_with_duration should work for custom max_units."""
test_cases = (
- ('3000-12-12T00:01:00Z', datetime(3000, 12, 11, 12, 5, 5, tzinfo=timezone.utc), 6,
- '<t:32533488060:f> (11 hours, 55 minutes and 55 seconds)'),
- ('3000-11-23T20:09:00Z', datetime(3000, 4, 25, 20, 15, tzinfo=timezone.utc), 20,
- '<t:32531918940:f> (6 months, 28 days, 23 hours and 54 minutes)')
+ ("3000-12-12T00:01:00Z", datetime(3000, 12, 11, 12, 5, 5, tzinfo=UTC), 6,
+ "<t:32533488060:f> (11 hours, 55 minutes and 55 seconds)"),
+ ("3000-11-23T20:09:00Z", datetime(3000, 4, 25, 20, 15, tzinfo=UTC), 20,
+ "<t:32531918940:f> (6 months, 28 days, 23 hours and 54 minutes)")
)
for expiry, date_from, max_units, expected in test_cases:
@@ -76,23 +76,22 @@ class TimeTests(unittest.TestCase):
def test_format_with_duration_normal_usage(self):
"""format_with_duration should work for normal usage, across various durations."""
- utc = timezone.utc
test_cases = (
- ('2019-12-12T00:01:00Z', datetime(2019, 12, 11, 12, 0, 5, tzinfo=utc), 2,
- '<t:1576108860:f> (12 hours and 55 seconds)'),
- ('2019-12-12T00:01:00Z', datetime(2019, 12, 11, 12, 0, 5, tzinfo=utc), 1, '<t:1576108860:f> (12 hours)'),
- ('2019-12-12T00:00:00Z', datetime(2019, 12, 11, 23, 59, tzinfo=utc), 2, '<t:1576108800:f> (1 minute)'),
- ('2019-11-23T20:09:00Z', datetime(2019, 11, 15, 20, 15, tzinfo=utc), 2,
- '<t:1574539740:f> (7 days and 23 hours)'),
- ('2019-11-23T20:09:00Z', datetime(2019, 4, 25, 20, 15, tzinfo=utc), 2,
- '<t:1574539740:f> (6 months and 28 days)'),
- ('2019-11-23T20:58:00Z', datetime(2019, 11, 23, 20, 53, tzinfo=utc), 2, '<t:1574542680:f> (5 minutes)'),
- ('2019-11-24T00:00:00Z', datetime(2019, 11, 23, 23, 59, 0, tzinfo=utc), 2, '<t:1574553600:f> (1 minute)'),
- ('2019-11-23T23:59:00Z', datetime(2017, 7, 21, 23, 0, tzinfo=utc), 2,
- '<t:1574553540:f> (2 years and 4 months)'),
- ('2019-11-23T23:59:00Z', datetime(2019, 11, 23, 23, 49, 5, tzinfo=utc), 2,
- '<t:1574553540:f> (9 minutes and 55 seconds)'),
- (None, datetime(2019, 11, 23, 23, 49, 5), 2, None),
+ ("2019-12-12T00:01:00Z", datetime(2019, 12, 11, 12, 0, 5, tzinfo=UTC), 2,
+ "<t:1576108860:f> (12 hours and 55 seconds)"),
+ ("2019-12-12T00:01:00Z", datetime(2019, 12, 11, 12, 0, 5, tzinfo=UTC), 1, "<t:1576108860:f> (12 hours)"),
+ ("2019-12-12T00:00:00Z", datetime(2019, 12, 11, 23, 59, tzinfo=UTC), 2, "<t:1576108800:f> (1 minute)"),
+ ("2019-11-23T20:09:00Z", datetime(2019, 11, 15, 20, 15, tzinfo=UTC), 2,
+ "<t:1574539740:f> (7 days and 23 hours)"),
+ ("2019-11-23T20:09:00Z", datetime(2019, 4, 25, 20, 15, tzinfo=UTC), 2,
+ "<t:1574539740:f> (6 months and 28 days)"),
+ ("2019-11-23T20:58:00Z", datetime(2019, 11, 23, 20, 53, tzinfo=UTC), 2, "<t:1574542680:f> (5 minutes)"),
+ ("2019-11-24T00:00:00Z", datetime(2019, 11, 23, 23, 59, 0, tzinfo=UTC), 2, "<t:1574553600:f> (1 minute)"),
+ ("2019-11-23T23:59:00Z", datetime(2017, 7, 21, 23, 0, tzinfo=UTC), 2,
+ "<t:1574553540:f> (2 years and 4 months)"),
+ ("2019-11-23T23:59:00Z", datetime(2019, 11, 23, 23, 49, 5, tzinfo=UTC), 2,
+ "<t:1574553540:f> (9 minutes and 55 seconds)"),
+ (None, datetime(2019, 11, 23, 23, 49, 5, tzinfo=UTC), 2, None),
)
for expiry, date_from, max_units, expected in test_cases:
@@ -106,8 +105,8 @@ class TimeTests(unittest.TestCase):
def test_until_expiration_with_duration_custom_units(self):
"""until_expiration should work for custom max_units."""
test_cases = (
- ('3000-12-12T00:01:00Z', '<t:32533488060:R>'),
- ('3000-11-23T20:09:00Z', '<t:32531918940:R>')
+ ("3000-12-12T00:01:00Z", "<t:32533488060:R>"),
+ ("3000-11-23T20:09:00Z", "<t:32531918940:R>")
)
for expiry, expected in test_cases:
@@ -117,11 +116,11 @@ class TimeTests(unittest.TestCase):
def test_until_expiration_normal_usage(self):
"""until_expiration should work for normal usage, across various durations."""
test_cases = (
- ('3000-12-12T00:01:00Z', '<t:32533488060:R>'),
- ('3000-12-12T00:01:00Z', '<t:32533488060:R>'),
- ('3000-12-12T00:00:00Z', '<t:32533488000:R>'),
- ('3000-11-23T20:09:00Z', '<t:32531918940:R>'),
- ('3000-11-23T20:09:00Z', '<t:32531918940:R>'),
+ ("3000-12-12T00:01:00Z", "<t:32533488060:R>"),
+ ("3000-12-12T00:01:00Z", "<t:32533488060:R>"),
+ ("3000-12-12T00:00:00Z", "<t:32533488000:R>"),
+ ("3000-11-23T20:09:00Z", "<t:32531918940:R>"),
+ ("3000-11-23T20:09:00Z", "<t:32531918940:R>"),
)
for expiry, expected in test_cases: