From 3b33188fd180bcd892f5e6102d9848e78e0cddcf Mon Sep 17 00:00:00 2001 From: Eyad Jawad Date: Tue, 7 Jul 2026 00:07:59 +0300 Subject: [PATCH 1/4] Add translate_from feature to translator_cog and its tests --- bot/extensions/translator_cog.py | 15 ++- errors.txt | 150 ++++++++++++++++++++++++ tests/extensions/conftest.py | 12 ++ tests/extensions/test_reminder_cog.py | 13 +- tests/extensions/test_threads_cog.py | 11 -- tests/extensions/test_time_cog.py | 7 -- tests/extensions/test_translator_cog.py | 73 ++++++++++++ 7 files changed, 245 insertions(+), 36 deletions(-) create mode 100644 errors.txt create mode 100644 tests/extensions/conftest.py create mode 100644 tests/extensions/test_translator_cog.py diff --git a/bot/extensions/translator_cog.py b/bot/extensions/translator_cog.py index c807299b..98869912 100644 --- a/bot/extensions/translator_cog.py +++ b/bot/extensions/translator_cog.py @@ -20,9 +20,9 @@ async def language_autocomplete(_: Interaction, current: str) -> list[Choice[str return [ Choice(name=language.capitalize(), value=language) - for language in languages[:25] + for language in languages if current.lower() in language.lower() - ] + ][:25] class TranslatorCog( @@ -36,13 +36,16 @@ class TranslatorCog( usage="sentence={sentence}", ) @autocomplete(translate_into=language_autocomplete) - async def translator(self, ctx: Context, *, sentence: str, translate_into: str): + @autocomplete(translate_from=language_autocomplete) + async def translator(self, ctx: Context, *, sentence: str, translate_from: str | None = "auto", translate_into: str): """Translate a sentence or word from any language into any languages. :param ctx: The context object. :type ctx: Context :param sentence: The sentence or word to be translated. :type sentence: str + :param translate_from: The language code for the source language. + :type translate_from: str | None :param translate_into: The language code for the target language. :type translate_into: str :return: Embed with original input and its translation @@ -50,7 +53,7 @@ async def translator(self, ctx: Context, *, sentence: str, translate_into: str): await ctx.defer() text_translator = Translator() - translated_text = text_translator.translate(sentence, dest=translate_into) + translated_text = text_translator.translate(sentence, src=translate_from, dest=translate_into) embed = Embed(color=self.bot.default_color) @@ -60,8 +63,8 @@ async def translator(self, ctx: Context, *, sentence: str, translate_into: str): inline=False, ) embed.add_field( - name=f"{translate_into} Translation", - value=translated_text.text, + name=f"{translate_into.capitalize()} Translation", + value=translated_text.text.capitalize(), inline=False, ) diff --git a/errors.txt b/errors.txt new file mode 100644 index 00000000..b1cfb290 --- /dev/null +++ b/errors.txt @@ -0,0 +1,150 @@ +============================= test session starts ============================== +platform linux -- Python 3.12.13, pytest-9.1.1, pluggy-1.6.0 +rootdir: /home/eyad/Programming/Python newbie second/grace +configfile: pyproject.toml +plugins: typeguard-4.5.2, asyncio-1.4.0 +asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function +collected 50 items + +tests/extensions/test_reminder_cog.py .......................... +tests/extensions/test_threads_cog.py ....... +tests/extensions/test_time_cog.py ......... +tests/extensions/test_translator_cog.py + + + + + + + + + +type = rich +title = None +url = None +description = None +colour = #ffffff +fields = [EmbedProxy(inline=False, name='English Original', value='Funny'), +EmbedProxy(inline=False, name='Arabic Translation', value='مضحك')] +timestamp = None +author = EmbedProxy() +thumbnail = EmbedProxy(flags=) +footer = EmbedProxy() +image = EmbedProxy(flags=) +provider = EmbedProxy() +video = EmbedProxy(flags=) +_flags = 0 + + + + + + + + +F. +tests/models/test_extension.py ...... + +=================================== FAILURES =================================== +_______________________________ test_translator ________________________________ + +translator_cog = +mock_bot = + + @pytest.mark.asyncio + async def test_translator(translator_cog, mock_bot): + ctx = MagicMock() + ctx.defer = AsyncMock() + ctx.send = AsyncMock() + + translate_from = "English" + translate_into = "Arabic" + sentence = "Funny" + translated_text = "مضحك" + + await translator_cog.translator( + translator_cog, + ctx, + sentence="Funny", + translate_from="English", + translate_into="Arabic" + ) + + embed = Embed(color=mock_bot.default_color) + + embed.add_field( + name=f"{translate_from} Original", + value=sentence, + inline=False, + ) + embed.add_field( + name=f"{translate_into} Translation", + value=translated_text, + inline=False, + ) + + print(f"\n\n\n\n\n\n\n\n \ntype = {embed.type}\ntitle = {embed.title}\nurl = {embed.url}\ndescription = {embed.description}\ncolour = {embed.colour}\nfields = {embed.fields}\ntimestamp = {embed.timestamp}\nauthor = {embed.author}\nthumbnail = {embed.thumbnail}\nfooter = {embed.footer}\nimage = {embed.image}\nprovider = {embed.provider}\nvideo = {embed.video}\n_flags = {embed._flags} \n\n\n\n\n\n\n\n") +> ctx.send.assert_awaited_once_with(embed) + +tests/extensions/test_translator_cog.py:49: +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ +../../../.pyenv/versions/3.12.13/lib/python3.12/unittest/mock.py:2363: in assert_awaited_once_with + return self.assert_awaited_with(*args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + +self = +args = (,), kwargs = {} + + def assert_awaited_with(self, /, *args, **kwargs): + """ + Assert that the last await was with the specified arguments. + """ + if self.await_args is None: + expected = self._format_mock_call_signature(args, kwargs) + raise AssertionError(f'Expected await: {expected}\nNot awaited') + + def _error_message(): + msg = self._format_mock_failure_message(args, kwargs, action='await') + return msg + + expected = self._call_matcher(_Call((args, kwargs), two=True)) + actual = self._call_matcher(self.await_args) + if actual != expected: + cause = expected if isinstance(expected, Exception) else None +> raise AssertionError(_error_message()) from cause +E AssertionError: expected await not found. +E Expected: send() +E Actual: send(embed=) + +../../../.pyenv/versions/3.12.13/lib/python3.12/unittest/mock.py:2352: AssertionError +=============================== warnings summary =============================== +venv/lib/python3.12/site-packages/discord/player.py:30 + /home/eyad/Programming/Python newbie second/grace/venv/lib/python3.12/site-packages/discord/player.py:30: DeprecationWarning: 'audioop' is deprecated and slated for removal in Python 3.13 + import audioop + +db/alembic/versions/614bb9e370d8_add_settings_for_puns_cooldown.py:33 +db/alembic/versions/614bb9e370d8_add_settings_for_puns_cooldown.py:33 + /home/eyad/Programming/Python newbie second/grace/db/alembic/versions/614bb9e370d8_add_settings_for_puns_cooldown.py:33: SADeprecationWarning: The from_engine() method on Inspector is deprecated and will be removed in a future release. Please use the sqlalchemy.inspect() function on an Engine or Connection in order to acquire an Inspector. (deprecated since: 1.4) + inspector = Inspector.from_engine(bind) + +venv/lib/python3.12/site-packages/httpx/_models.py:1 + /home/eyad/Programming/Python newbie second/grace/venv/lib/python3.12/site-packages/httpx/_models.py:1: DeprecationWarning: 'cgi' is deprecated and slated for removal in Python 3.13 + import cgi + +tests/extensions/test_translator_cog.py::test_translator + /home/eyad/Programming/Python newbie second/grace/venv/lib/python3.12/site-packages/httpx/_config.py:156: DeprecationWarning: ssl.PROTOCOL_TLS is deprecated + context = ssl.SSLContext(ssl.PROTOCOL_TLS) + +tests/extensions/test_translator_cog.py::test_translator + /home/eyad/Programming/Python newbie second/grace/venv/lib/python3.12/site-packages/httpx/_config.py:159: DeprecationWarning: ssl.OP_NO_SSL*/ssl.OP_NO_TLS* options are deprecated + context.options |= ssl.OP_NO_TLSv1 + +tests/extensions/test_translator_cog.py::test_translator + /home/eyad/Programming/Python newbie second/grace/venv/lib/python3.12/site-packages/httpx/_config.py:160: DeprecationWarning: ssl.OP_NO_SSL*/ssl.OP_NO_TLS* options are deprecated + context.options |= ssl.OP_NO_TLSv1_1 + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html +=========================== short test summary info ============================ +FAILED tests/extensions/test_translator_cog.py::test_translator - AssertionEr... +=================== 1 failed, 49 passed, 7 warnings in 8.01s =================== diff --git a/tests/extensions/conftest.py b/tests/extensions/conftest.py new file mode 100644 index 00000000..b4279a1a --- /dev/null +++ b/tests/extensions/conftest.py @@ -0,0 +1,12 @@ +from unittest.mock import MagicMock + +import pytest + +@pytest.fixture +def mock_bot(): + """Create a mock Discord bot instance.""" + bot = MagicMock() + bot.default_color = 0xFFFFFF + bot.app.config.get = MagicMock(return_value=None) + bot.scheduler = MagicMock() + return bot diff --git a/tests/extensions/test_reminder_cog.py b/tests/extensions/test_reminder_cog.py index bb57999a..c65efc73 100644 --- a/tests/extensions/test_reminder_cog.py +++ b/tests/extensions/test_reminder_cog.py @@ -1,6 +1,6 @@ import re from datetime import UTC, datetime, timedelta -from unittest.mock import AsyncMock, MagicMock +from unittest.mock import AsyncMock import pytest from dateutil.tz import tzlocal @@ -9,17 +9,6 @@ from bot.extensions.reminder_cog import ReminderCog - -@pytest.fixture -def mock_bot(): - """Create a mock Discord bot instance.""" - bot = MagicMock() - bot.default_color = 0xFFFFFF - bot.app.config.get = MagicMock(return_value=None) - bot.scheduler = MagicMock() - return bot - - @pytest.fixture def reminder_cog(mock_bot): """Instantiate the ReminderCog with a mock bot.""" diff --git a/tests/extensions/test_threads_cog.py b/tests/extensions/test_threads_cog.py index 8fddf69e..402fbe63 100644 --- a/tests/extensions/test_threads_cog.py +++ b/tests/extensions/test_threads_cog.py @@ -5,17 +5,6 @@ from bot.extensions.threads_cog import ThreadsCog from bot.models.extensions.thread import Thread - -@pytest.fixture -def mock_bot(): - """Create a mock Discord bot instance.""" - bot = MagicMock() - bot.default_color = 0xFFFFFF - bot.app.config.get = MagicMock(return_value=None) - bot.scheduler = MagicMock() - return bot - - @pytest.fixture def threads_cog(mock_bot): """Instantiate the ThreadsCog with a mock bot.""" diff --git a/tests/extensions/test_time_cog.py b/tests/extensions/test_time_cog.py index ea06e3a1..2760234b 100644 --- a/tests/extensions/test_time_cog.py +++ b/tests/extensions/test_time_cog.py @@ -6,13 +6,6 @@ from bot.extensions.time_cog import TimeCog - -@pytest.fixture -def mock_bot(): - """Create a mock Discord bot instance.""" - return MagicMock() - - @pytest.fixture def time_cog(mock_bot): """Instantiate the TimeCog with a mock bot.""" diff --git a/tests/extensions/test_translator_cog.py b/tests/extensions/test_translator_cog.py new file mode 100644 index 00000000..770372f4 --- /dev/null +++ b/tests/extensions/test_translator_cog.py @@ -0,0 +1,73 @@ +from discord import Embed +from discord.app_commands import Choice +from unittest.mock import AsyncMock, MagicMock + +import pytest + +from bot.extensions.translator_cog import language_autocomplete, TranslatorCog + + +@pytest.fixture +def translator_cog(mock_bot): + """Instantiate the TranslatorCog with a mock bot.""" + + return TranslatorCog(mock_bot) + +@pytest.mark.asyncio +async def test_translator(translator_cog, mock_bot): + ctx = MagicMock() + ctx.defer = AsyncMock() + ctx.send = AsyncMock() + + translate_from = "English" + translate_into = "Arabic" + sentence = "Funny" + translated_text = "مضحك" + + await translator_cog.translator( + translator_cog, + ctx, + sentence="Funny", + translate_from="English", + translate_into="Arabic" + ) + + result = Embed(color=mock_bot.default_color) + + result.add_field( + name=f"{translate_from} Original", + value=sentence, + inline=False, + ) + result.add_field( + name=f"{translate_into} Translation", + value=translated_text, + inline=False, + ) + + ctx.send.assert_awaited_once_with(embed=result) + + +@pytest.mark.asyncio +async def test_language_autocomplete_empty_input(): + empty = await language_autocomplete(None, "") + assert len(empty) == 25 + +@pytest.mark.asyncio +async def test_language_autocomplete_invalid_input(): + invalid = await language_autocomplete(None, "1232") + assert invalid == [] + +@pytest.mark.asyncio +async def test_language_autocomplete_ara_input(): + ara = await language_autocomplete(None, "ara") + assert ara == [ + Choice(name='Arabic', value='arabic'), + Choice(name='Gujarati', value='gujarati'), + Choice(name='Marathi', value='marathi') + ] + +@pytest.mark.asyncio +async def test_language_autocomplete_zu_input(): + zu = await language_autocomplete(None, "zu") + assert zu == [Choice(name='Zulu', value='zulu')] From d59b6ae9a1c34b61f83d56199a95a3671f919dce Mon Sep 17 00:00:00 2001 From: Eyad Jawad Date: Tue, 7 Jul 2026 00:32:13 +0300 Subject: [PATCH 2/4] Format using ruff --- ruffOutput.txt | 119 ++++++++++++++++++++++++ tests/extensions/conftest.py | 1 + tests/extensions/test_reminder_cog.py | 1 + tests/extensions/test_threads_cog.py | 1 + tests/extensions/test_time_cog.py | 1 + tests/extensions/test_translator_cog.py | 6 +- 6 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 ruffOutput.txt diff --git a/ruffOutput.txt b/ruffOutput.txt new file mode 100644 index 00000000..aa46e33b --- /dev/null +++ b/ruffOutput.txt @@ -0,0 +1,119 @@ +error[I001][*]: Import block is un-sorted or un-formatted + --> tests/extensions/conftest.py:1:1 + | +1 | / from unittest.mock import MagicMock +2 | | +3 | | import pytest + | |_____________^ +4 | +5 | @pytest.fixture + | +help: Organize imports +2 | +3 | import pytest +4 | +5 + +6 | @pytest.fixture +7 | def mock_bot(): +8 | """Create a mock Discord bot instance.""" + +error[I001][*]: Import block is un-sorted or un-formatted + --> tests/extensions/test_reminder_cog.py:1:1 + | + 1 | / import re + 2 | | from datetime import UTC, datetime, timedelta + 3 | | from unittest.mock import AsyncMock + 4 | | + 5 | | import pytest + 6 | | from dateutil.tz import tzlocal + 7 | | from discord import Embed + 8 | | from freezegun import freeze_time + 9 | | +10 | | from bot.extensions.reminder_cog import ReminderCog + | |___________________________________________________^ +11 | +12 | @pytest.fixture + | +help: Organize imports +9 | +10 | from bot.extensions.reminder_cog import ReminderCog +11 | +12 + +13 | @pytest.fixture +14 | def reminder_cog(mock_bot): +15 | """Instantiate the ReminderCog with a mock bot.""" + +error[I001][*]: Import block is un-sorted or un-formatted + --> tests/extensions/test_threads_cog.py:1:1 + | +1 | / from unittest.mock import AsyncMock, MagicMock +2 | | +3 | | import pytest +4 | | +5 | | from bot.extensions.threads_cog import ThreadsCog +6 | | from bot.models.extensions.thread import Thread + | |_______________________________________________^ +7 | +8 | @pytest.fixture + | +help: Organize imports +5 | from bot.extensions.threads_cog import ThreadsCog +6 | from bot.models.extensions.thread import Thread +7 | +8 + +9 | @pytest.fixture +10 | def threads_cog(mock_bot): +11 | """Instantiate the ThreadsCog with a mock bot.""" + +error[I001][*]: Import block is un-sorted or un-formatted + --> tests/extensions/test_time_cog.py:1:1 + | +1 | / from datetime import datetime +2 | | from unittest.mock import AsyncMock, MagicMock +3 | | +4 | | import pytest +5 | | import pytz +6 | | +7 | | from bot.extensions.time_cog import TimeCog + | |___________________________________________^ +8 | +9 | @pytest.fixture + | +help: Organize imports +6 | +7 | from bot.extensions.time_cog import TimeCog +8 | +9 + +10 | @pytest.fixture +11 | def time_cog(mock_bot): +12 | """Instantiate the TimeCog with a mock bot.""" + +error[I001][*]: Import block is un-sorted or un-formatted + --> tests/extensions/test_translator_cog.py:1:1 + | +1 | / from discord import Embed +2 | | from discord.app_commands import Choice +3 | | from unittest.mock import AsyncMock, MagicMock +4 | | +5 | | import pytest +6 | | +7 | | from bot.extensions.translator_cog import language_autocomplete, TranslatorCog + | |______________________________________________________________________________^ + | +help: Organize imports + - from discord import Embed + - from discord.app_commands import Choice +1 | from unittest.mock import AsyncMock, MagicMock +2 | +3 | import pytest +4 + from discord import Embed +5 + from discord.app_commands import Choice +6 | + - from bot.extensions.translator_cog import language_autocomplete, TranslatorCog +7 + from bot.extensions.translator_cog import TranslatorCog, language_autocomplete +8 | +9 | +10 | @pytest.fixture + +Found 5 errors. +[*] 5 fixable with the `--fix` option. diff --git a/tests/extensions/conftest.py b/tests/extensions/conftest.py index b4279a1a..46ac2315 100644 --- a/tests/extensions/conftest.py +++ b/tests/extensions/conftest.py @@ -2,6 +2,7 @@ import pytest + @pytest.fixture def mock_bot(): """Create a mock Discord bot instance.""" diff --git a/tests/extensions/test_reminder_cog.py b/tests/extensions/test_reminder_cog.py index c65efc73..eb44dc60 100644 --- a/tests/extensions/test_reminder_cog.py +++ b/tests/extensions/test_reminder_cog.py @@ -9,6 +9,7 @@ from bot.extensions.reminder_cog import ReminderCog + @pytest.fixture def reminder_cog(mock_bot): """Instantiate the ReminderCog with a mock bot.""" diff --git a/tests/extensions/test_threads_cog.py b/tests/extensions/test_threads_cog.py index 402fbe63..c71f67ee 100644 --- a/tests/extensions/test_threads_cog.py +++ b/tests/extensions/test_threads_cog.py @@ -5,6 +5,7 @@ from bot.extensions.threads_cog import ThreadsCog from bot.models.extensions.thread import Thread + @pytest.fixture def threads_cog(mock_bot): """Instantiate the ThreadsCog with a mock bot.""" diff --git a/tests/extensions/test_time_cog.py b/tests/extensions/test_time_cog.py index 2760234b..e1e5f5e9 100644 --- a/tests/extensions/test_time_cog.py +++ b/tests/extensions/test_time_cog.py @@ -6,6 +6,7 @@ from bot.extensions.time_cog import TimeCog + @pytest.fixture def time_cog(mock_bot): """Instantiate the TimeCog with a mock bot.""" diff --git a/tests/extensions/test_translator_cog.py b/tests/extensions/test_translator_cog.py index 770372f4..7be93f58 100644 --- a/tests/extensions/test_translator_cog.py +++ b/tests/extensions/test_translator_cog.py @@ -1,10 +1,10 @@ -from discord import Embed -from discord.app_commands import Choice from unittest.mock import AsyncMock, MagicMock import pytest +from discord import Embed +from discord.app_commands import Choice -from bot.extensions.translator_cog import language_autocomplete, TranslatorCog +from bot.extensions.translator_cog import TranslatorCog, language_autocomplete @pytest.fixture From 642404d447889cb35a068f87296ca1523346a1d8 Mon Sep 17 00:00:00 2001 From: Eyad Jawad Date: Tue, 7 Jul 2026 00:37:58 +0300 Subject: [PATCH 3/4] Remove temporary files --- errors.txt | 150 ------------------------------------------------- ruffOutput.txt | 119 --------------------------------------- 2 files changed, 269 deletions(-) delete mode 100644 errors.txt delete mode 100644 ruffOutput.txt diff --git a/errors.txt b/errors.txt deleted file mode 100644 index b1cfb290..00000000 --- a/errors.txt +++ /dev/null @@ -1,150 +0,0 @@ -============================= test session starts ============================== -platform linux -- Python 3.12.13, pytest-9.1.1, pluggy-1.6.0 -rootdir: /home/eyad/Programming/Python newbie second/grace -configfile: pyproject.toml -plugins: typeguard-4.5.2, asyncio-1.4.0 -asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function -collected 50 items - -tests/extensions/test_reminder_cog.py .......................... -tests/extensions/test_threads_cog.py ....... -tests/extensions/test_time_cog.py ......... -tests/extensions/test_translator_cog.py - - - - - - - - - -type = rich -title = None -url = None -description = None -colour = #ffffff -fields = [EmbedProxy(inline=False, name='English Original', value='Funny'), -EmbedProxy(inline=False, name='Arabic Translation', value='مضحك')] -timestamp = None -author = EmbedProxy() -thumbnail = EmbedProxy(flags=) -footer = EmbedProxy() -image = EmbedProxy(flags=) -provider = EmbedProxy() -video = EmbedProxy(flags=) -_flags = 0 - - - - - - - - -F. -tests/models/test_extension.py ...... - -=================================== FAILURES =================================== -_______________________________ test_translator ________________________________ - -translator_cog = -mock_bot = - - @pytest.mark.asyncio - async def test_translator(translator_cog, mock_bot): - ctx = MagicMock() - ctx.defer = AsyncMock() - ctx.send = AsyncMock() - - translate_from = "English" - translate_into = "Arabic" - sentence = "Funny" - translated_text = "مضحك" - - await translator_cog.translator( - translator_cog, - ctx, - sentence="Funny", - translate_from="English", - translate_into="Arabic" - ) - - embed = Embed(color=mock_bot.default_color) - - embed.add_field( - name=f"{translate_from} Original", - value=sentence, - inline=False, - ) - embed.add_field( - name=f"{translate_into} Translation", - value=translated_text, - inline=False, - ) - - print(f"\n\n\n\n\n\n\n\n \ntype = {embed.type}\ntitle = {embed.title}\nurl = {embed.url}\ndescription = {embed.description}\ncolour = {embed.colour}\nfields = {embed.fields}\ntimestamp = {embed.timestamp}\nauthor = {embed.author}\nthumbnail = {embed.thumbnail}\nfooter = {embed.footer}\nimage = {embed.image}\nprovider = {embed.provider}\nvideo = {embed.video}\n_flags = {embed._flags} \n\n\n\n\n\n\n\n") -> ctx.send.assert_awaited_once_with(embed) - -tests/extensions/test_translator_cog.py:49: -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ -../../../.pyenv/versions/3.12.13/lib/python3.12/unittest/mock.py:2363: in assert_awaited_once_with - return self.assert_awaited_with(*args, **kwargs) - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - -self = -args = (,), kwargs = {} - - def assert_awaited_with(self, /, *args, **kwargs): - """ - Assert that the last await was with the specified arguments. - """ - if self.await_args is None: - expected = self._format_mock_call_signature(args, kwargs) - raise AssertionError(f'Expected await: {expected}\nNot awaited') - - def _error_message(): - msg = self._format_mock_failure_message(args, kwargs, action='await') - return msg - - expected = self._call_matcher(_Call((args, kwargs), two=True)) - actual = self._call_matcher(self.await_args) - if actual != expected: - cause = expected if isinstance(expected, Exception) else None -> raise AssertionError(_error_message()) from cause -E AssertionError: expected await not found. -E Expected: send() -E Actual: send(embed=) - -../../../.pyenv/versions/3.12.13/lib/python3.12/unittest/mock.py:2352: AssertionError -=============================== warnings summary =============================== -venv/lib/python3.12/site-packages/discord/player.py:30 - /home/eyad/Programming/Python newbie second/grace/venv/lib/python3.12/site-packages/discord/player.py:30: DeprecationWarning: 'audioop' is deprecated and slated for removal in Python 3.13 - import audioop - -db/alembic/versions/614bb9e370d8_add_settings_for_puns_cooldown.py:33 -db/alembic/versions/614bb9e370d8_add_settings_for_puns_cooldown.py:33 - /home/eyad/Programming/Python newbie second/grace/db/alembic/versions/614bb9e370d8_add_settings_for_puns_cooldown.py:33: SADeprecationWarning: The from_engine() method on Inspector is deprecated and will be removed in a future release. Please use the sqlalchemy.inspect() function on an Engine or Connection in order to acquire an Inspector. (deprecated since: 1.4) - inspector = Inspector.from_engine(bind) - -venv/lib/python3.12/site-packages/httpx/_models.py:1 - /home/eyad/Programming/Python newbie second/grace/venv/lib/python3.12/site-packages/httpx/_models.py:1: DeprecationWarning: 'cgi' is deprecated and slated for removal in Python 3.13 - import cgi - -tests/extensions/test_translator_cog.py::test_translator - /home/eyad/Programming/Python newbie second/grace/venv/lib/python3.12/site-packages/httpx/_config.py:156: DeprecationWarning: ssl.PROTOCOL_TLS is deprecated - context = ssl.SSLContext(ssl.PROTOCOL_TLS) - -tests/extensions/test_translator_cog.py::test_translator - /home/eyad/Programming/Python newbie second/grace/venv/lib/python3.12/site-packages/httpx/_config.py:159: DeprecationWarning: ssl.OP_NO_SSL*/ssl.OP_NO_TLS* options are deprecated - context.options |= ssl.OP_NO_TLSv1 - -tests/extensions/test_translator_cog.py::test_translator - /home/eyad/Programming/Python newbie second/grace/venv/lib/python3.12/site-packages/httpx/_config.py:160: DeprecationWarning: ssl.OP_NO_SSL*/ssl.OP_NO_TLS* options are deprecated - context.options |= ssl.OP_NO_TLSv1_1 - --- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html -=========================== short test summary info ============================ -FAILED tests/extensions/test_translator_cog.py::test_translator - AssertionEr... -=================== 1 failed, 49 passed, 7 warnings in 8.01s =================== diff --git a/ruffOutput.txt b/ruffOutput.txt deleted file mode 100644 index aa46e33b..00000000 --- a/ruffOutput.txt +++ /dev/null @@ -1,119 +0,0 @@ -error[I001][*]: Import block is un-sorted or un-formatted - --> tests/extensions/conftest.py:1:1 - | -1 | / from unittest.mock import MagicMock -2 | | -3 | | import pytest - | |_____________^ -4 | -5 | @pytest.fixture - | -help: Organize imports -2 | -3 | import pytest -4 | -5 + -6 | @pytest.fixture -7 | def mock_bot(): -8 | """Create a mock Discord bot instance.""" - -error[I001][*]: Import block is un-sorted or un-formatted - --> tests/extensions/test_reminder_cog.py:1:1 - | - 1 | / import re - 2 | | from datetime import UTC, datetime, timedelta - 3 | | from unittest.mock import AsyncMock - 4 | | - 5 | | import pytest - 6 | | from dateutil.tz import tzlocal - 7 | | from discord import Embed - 8 | | from freezegun import freeze_time - 9 | | -10 | | from bot.extensions.reminder_cog import ReminderCog - | |___________________________________________________^ -11 | -12 | @pytest.fixture - | -help: Organize imports -9 | -10 | from bot.extensions.reminder_cog import ReminderCog -11 | -12 + -13 | @pytest.fixture -14 | def reminder_cog(mock_bot): -15 | """Instantiate the ReminderCog with a mock bot.""" - -error[I001][*]: Import block is un-sorted or un-formatted - --> tests/extensions/test_threads_cog.py:1:1 - | -1 | / from unittest.mock import AsyncMock, MagicMock -2 | | -3 | | import pytest -4 | | -5 | | from bot.extensions.threads_cog import ThreadsCog -6 | | from bot.models.extensions.thread import Thread - | |_______________________________________________^ -7 | -8 | @pytest.fixture - | -help: Organize imports -5 | from bot.extensions.threads_cog import ThreadsCog -6 | from bot.models.extensions.thread import Thread -7 | -8 + -9 | @pytest.fixture -10 | def threads_cog(mock_bot): -11 | """Instantiate the ThreadsCog with a mock bot.""" - -error[I001][*]: Import block is un-sorted or un-formatted - --> tests/extensions/test_time_cog.py:1:1 - | -1 | / from datetime import datetime -2 | | from unittest.mock import AsyncMock, MagicMock -3 | | -4 | | import pytest -5 | | import pytz -6 | | -7 | | from bot.extensions.time_cog import TimeCog - | |___________________________________________^ -8 | -9 | @pytest.fixture - | -help: Organize imports -6 | -7 | from bot.extensions.time_cog import TimeCog -8 | -9 + -10 | @pytest.fixture -11 | def time_cog(mock_bot): -12 | """Instantiate the TimeCog with a mock bot.""" - -error[I001][*]: Import block is un-sorted or un-formatted - --> tests/extensions/test_translator_cog.py:1:1 - | -1 | / from discord import Embed -2 | | from discord.app_commands import Choice -3 | | from unittest.mock import AsyncMock, MagicMock -4 | | -5 | | import pytest -6 | | -7 | | from bot.extensions.translator_cog import language_autocomplete, TranslatorCog - | |______________________________________________________________________________^ - | -help: Organize imports - - from discord import Embed - - from discord.app_commands import Choice -1 | from unittest.mock import AsyncMock, MagicMock -2 | -3 | import pytest -4 + from discord import Embed -5 + from discord.app_commands import Choice -6 | - - from bot.extensions.translator_cog import language_autocomplete, TranslatorCog -7 + from bot.extensions.translator_cog import TranslatorCog, language_autocomplete -8 | -9 | -10 | @pytest.fixture - -Found 5 errors. -[*] 5 fixable with the `--fix` option. From 8580536cc4fcc5f2610b166a2a89dbe821c51c70 Mon Sep 17 00:00:00 2001 From: Eyad Jawad Date: Tue, 7 Jul 2026 17:14:10 +0300 Subject: [PATCH 4/4] Format using black --- bot/extensions/translator_cog.py | 15 ++++++++++++--- tests/extensions/test_translator_cog.py | 22 +++++++++++++--------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/bot/extensions/translator_cog.py b/bot/extensions/translator_cog.py index 98869912..f01e1560 100644 --- a/bot/extensions/translator_cog.py +++ b/bot/extensions/translator_cog.py @@ -37,7 +37,14 @@ class TranslatorCog( ) @autocomplete(translate_into=language_autocomplete) @autocomplete(translate_from=language_autocomplete) - async def translator(self, ctx: Context, *, sentence: str, translate_from: str | None = "auto", translate_into: str): + async def translator( + self, + ctx: Context, + *, + sentence: str, + translate_from: str | None = "auto", + translate_into: str, + ): """Translate a sentence or word from any language into any languages. :param ctx: The context object. @@ -45,7 +52,7 @@ async def translator(self, ctx: Context, *, sentence: str, translate_from: str | :param sentence: The sentence or word to be translated. :type sentence: str :param translate_from: The language code for the source language. - :type translate_from: str | None + :type translate_from: str | None :param translate_into: The language code for the target language. :type translate_into: str :return: Embed with original input and its translation @@ -53,7 +60,9 @@ async def translator(self, ctx: Context, *, sentence: str, translate_from: str | await ctx.defer() text_translator = Translator() - translated_text = text_translator.translate(sentence, src=translate_from, dest=translate_into) + translated_text = text_translator.translate( + sentence, src=translate_from, dest=translate_into + ) embed = Embed(color=self.bot.default_color) diff --git a/tests/extensions/test_translator_cog.py b/tests/extensions/test_translator_cog.py index 7be93f58..5e078d34 100644 --- a/tests/extensions/test_translator_cog.py +++ b/tests/extensions/test_translator_cog.py @@ -13,6 +13,7 @@ def translator_cog(mock_bot): return TranslatorCog(mock_bot) + @pytest.mark.asyncio async def test_translator(translator_cog, mock_bot): ctx = MagicMock() @@ -25,11 +26,11 @@ async def test_translator(translator_cog, mock_bot): translated_text = "مضحك" await translator_cog.translator( - translator_cog, - ctx, - sentence="Funny", - translate_from="English", - translate_into="Arabic" + translator_cog, + ctx, + sentence="Funny", + translate_from="English", + translate_into="Arabic", ) result = Embed(color=mock_bot.default_color) @@ -53,21 +54,24 @@ async def test_language_autocomplete_empty_input(): empty = await language_autocomplete(None, "") assert len(empty) == 25 + @pytest.mark.asyncio async def test_language_autocomplete_invalid_input(): invalid = await language_autocomplete(None, "1232") assert invalid == [] + @pytest.mark.asyncio async def test_language_autocomplete_ara_input(): ara = await language_autocomplete(None, "ara") assert ara == [ - Choice(name='Arabic', value='arabic'), - Choice(name='Gujarati', value='gujarati'), - Choice(name='Marathi', value='marathi') + Choice(name="Arabic", value="arabic"), + Choice(name="Gujarati", value="gujarati"), + Choice(name="Marathi", value="marathi"), ] + @pytest.mark.asyncio async def test_language_autocomplete_zu_input(): zu = await language_autocomplete(None, "zu") - assert zu == [Choice(name='Zulu', value='zulu')] + assert zu == [Choice(name="Zulu", value="zulu")]