diff --git a/googletrans/client.py b/googletrans/client.py index 8516f12..ae50637 100644 --- a/googletrans/client.py +++ b/googletrans/client.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ A Translation module. @@ -107,11 +106,7 @@ def _pick_service_url(self) -> str: return random.choice(self.service_urls) async def _translate( - self, - text: str, - dest: str, - src: str, - override: typing.Dict[str, typing.Any] + self, text: str, dest: str, src: str, override: typing.Dict[str, typing.Any] ) -> typing.Tuple[typing.List[typing.Any], Response]: token = "xxxx" # dummy default value here as it is not used by api client if self.client_type == "webapp": @@ -144,11 +139,7 @@ async def _translate( return DUMMY_DATA, r def build_request( - self, - text: str, - dest: str, - src: str, - override: typing.Dict[str, typing.Any] + self, text: str, dest: str, src: str, override: typing.Dict[str, typing.Any] ) -> httpx.Request: """Async helper for making the translation request""" token = "xxxx" # dummy default value here as it is not used by api client @@ -169,8 +160,7 @@ def build_request( return self.client.build_request("GET", url, params=params) def _parse_extra_data( - self, - data: typing.List[typing.Any] + self, data: typing.List[typing.Any] ) -> typing.Dict[str, typing.Any]: response_parts_name_mapping = { 0: "translation", @@ -195,6 +185,20 @@ def _parse_extra_data( return extra + @typing.overload + async def translate( + self, text: str, dest: str = ..., src: str = ..., **kwargs: typing.Any + ) -> Translated: ... + + @typing.overload + async def translate( + self, + text: typing.List[str], + dest: str = ..., + src: str = ..., + **kwargs: typing.Any, + ) -> typing.List[Translated]: ... + async def translate( self, text: typing.Union[str, typing.List[str]], @@ -309,10 +313,16 @@ async def translate( return result + @typing.overload + async def detect(self, text: str, **kwargs: typing.Any) -> Detected: ... + + @typing.overload async def detect( - self, - text: typing.Union[str, typing.List[str]], - **kwargs: typing.Any + self, text: typing.List[str], **kwargs: typing.Any + ) -> typing.List[Detected]: ... + + async def detect( + self, text: typing.Union[str, typing.List[str]], **kwargs: typing.Any ) -> typing.Union[Detected, typing.List[Detected]]: """Detect language of the input text diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_client.py b/tests/test_client.py index 035c609..9fde14f 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,13 +1,16 @@ +from unittest.mock import patch + +import pytest from httpcore import TimeoutException from httpcore._exceptions import ConnectError -from httpx import Timeout, Client, ConnectTimeout -from unittest.mock import patch +from httpx import Client, ConnectTimeout, Timeout from pytest import raises from googletrans import Translator -def test_bind_multiple_service_urls(): +@pytest.mark.asyncio +async def test_bind_multiple_service_urls(): service_urls = [ "translate.google.com", "translate.google.co.kr", @@ -16,87 +19,97 @@ def test_bind_multiple_service_urls(): translator = Translator(service_urls=service_urls) assert translator.service_urls == service_urls - assert translator.translate("test", dest="ko") - assert translator.detect("Hello") + assert await translator.translate("test", dest="ko") + assert await translator.detect("Hello") -def test_api_service_urls(): +@pytest.mark.asyncio +async def test_api_service_urls(): service_urls = ["translate.googleapis.com"] translator = Translator(service_urls=service_urls) assert translator.service_urls == service_urls - assert translator.translate("test", dest="ko") - assert translator.detect("Hello") + assert await translator.translate("test", dest="ko") + assert await translator.detect("Hello") -def test_source_language(translator): - result = translator.translate("안녕하세요.") +@pytest.mark.asyncio +async def test_source_language(translator: Translator): + result = await translator.translate("안녕하세요.") assert result.src == "ko" -def test_pronunciation(translator): - result = translator.translate("안녕하세요.", dest="ja") +@pytest.mark.asyncio +async def test_pronunciation(translator: Translator): + result = await translator.translate("안녕하세요.", dest="ja") assert result.pronunciation == "Kon'nichiwa." -def test_pronunciation_issue_175(translator): - result = translator.translate("Hello", src="en", dest="ru") - +@pytest.mark.asyncio +async def test_pronunciation_issue_175(translator: Translator): + result = await translator.translate("Hello", src="en", dest="ru") assert result.pronunciation is not None -def test_latin_to_english(translator): - result = translator.translate("veritas lux mea", src="la", dest="en") +@pytest.mark.asyncio +async def test_latin_to_english(translator: Translator): + result = await translator.translate("veritas lux mea", src="la", dest="en") assert result.text == "truth is my light" -def test_unicode(translator): - result = translator.translate("안녕하세요.", src="ko", dest="ja") +@pytest.mark.asyncio +async def test_unicode(translator: Translator): + result = await translator.translate("안녕하세요.", src="ko", dest="ja") assert result.text == "こんにちは。" -def test_emoji(translator): - result = translator.translate("😀") +@pytest.mark.asyncio +async def test_emoji(translator: Translator): + result = await translator.translate("😀") assert result.text == "😀" -def test_language_name(translator): - result = translator.translate("Hello", src="ENGLISH", dest="iRiSh") +@pytest.mark.asyncio +async def test_language_name(translator: Translator): + result = await translator.translate("Hello", src="ENGLISH", dest="iRiSh") assert result.text == "Dia duit" -def test_language_name_with_space(translator): - result = translator.translate("Hello", src="en", dest="chinese (simplified)") +@pytest.mark.asyncio +async def test_language_name_with_space(translator: Translator): + result = await translator.translate("Hello", src="en", dest="chinese (simplified)") assert result.dest == "zh-cn" -def test_language_rfc1766(translator): - result = translator.translate("luna", src="it_ch@euro", dest="en") +@pytest.mark.asyncio +async def test_language_rfc1766(translator: Translator): + result = await translator.translate("luna", src="it_ch@euro", dest="en") assert result.text == "moon" -def test_special_chars(translator): +@pytest.mark.asyncio +async def test_special_chars(translator: Translator): text = "©×《》" - - result = translator.translate(text, src="en", dest="en") + result = await translator.translate(text, src="en", dest="en") assert result.text == text -def test_translate_list(translator): +@pytest.mark.asyncio +async def test_translate_list(translator: Translator): args = (["test", "exam", "exam paper"], "ko", "en") - translations = translator.translate(*args) - + translations = await translator.translate(*args) assert translations[0].text == "시험" assert translations[1].text == "시험" assert translations[2].text == "시험지" -def test_detect_language(translator): - ko = translator.detect("한국어") - en = translator.detect("English") - rubg = translator.detect("тест") - russ = translator.detect("привет") +@pytest.mark.asyncio +async def test_detect_language(translator: Translator): + ko = await translator.detect("한국어") + en = await translator.detect("English") + rubg = await translator.detect("тест") + russ = await translator.detect("привет") assert ko.lang == "ko" assert en.lang == "en" @@ -105,10 +118,10 @@ def test_detect_language(translator): #'bg'] -def test_detect_list(translator): +@pytest.mark.asyncio +async def test_detect_list(translator: Translator): items = ["한국어", " English", "тест", "привет"] - - result = translator.detect(items) + result = await translator.detect(items) assert result[0].lang == "ko" assert result[1].lang == "en" @@ -116,41 +129,40 @@ def test_detect_list(translator): assert result[3].lang == "ru" -def test_src_in_special_cases(translator): +@pytest.mark.asyncio +async def test_src_in_special_cases(translator: Translator): args = ("tere", "en", "ee") - - result = translator.translate(*args) - + result = await translator.translate(*args) assert result.text in ("hello", "hi,") -def test_src_not_in_supported_languages(translator): +@pytest.mark.asyncio +async def test_src_not_in_supported_languages(translator: Translator): args = ("Hello", "en", "zzz") - with raises(ValueError): - translator.translate(*args) + await translator.translate(*args) -def test_dest_in_special_cases(translator): +@pytest.mark.asyncio +async def test_dest_in_special_cases(translator: Translator): args = ("hello", "ee", "en") - - result = translator.translate(*args) - + result = await translator.translate(*args) assert result.text == "tere" -def test_dest_not_in_supported_languages(translator): +@pytest.mark.asyncio +async def test_dest_not_in_supported_languages(translator: Translator): args = ("Hello", "zzz", "en") - with raises(ValueError): - translator.translate(*args) + await translator.translate(*args) -def test_timeout(): +@pytest.mark.asyncio +async def test_timeout(): # httpx will raise ConnectError in some conditions with raises((TimeoutException, ConnectError, ConnectTimeout)): translator = Translator(timeout=Timeout(0.0001)) - translator.translate("안녕하세요.") + await translator.translate("안녕하세요.") class MockResponse: @@ -159,7 +171,8 @@ def __init__(self, status_code): self.text = "tkk:'translation'" +@pytest.mark.asyncio @patch.object(Client, "get", return_value=MockResponse("403")) -def test_403_error(session_mock): +async def test_403_error(session_mock): translator = Translator() - assert translator.translate("test", dest="ko") + assert await translator.translate("test", dest="ko") diff --git a/tests/test_gtoken.py b/tests/test_gtoken.py index 258a400..37fd3b4 100644 --- a/tests/test_gtoken.py +++ b/tests/test_gtoken.py @@ -1,67 +1,74 @@ -# -*- coding: utf-8 -*- +from typing import Any, Callable + import httpx +import pytest from googletrans import gtoken -from pytest import fixture -@fixture(scope="session") -def acquirer(): - client = httpx.Client(http2=True) +@pytest.fixture(scope="session") +def acquirer() -> gtoken.TokenAcquirer: + client = httpx.AsyncClient(http2=True) return gtoken.TokenAcquirer(client=client) -def test_acquire_token(acquirer): - text = "test" +@pytest.mark.asyncio +async def test_acquire_token(acquirer: gtoken.TokenAcquirer) -> None: + text: str = "test" - result = acquirer.do(text) + result: str = await acquirer.do(text) assert result -def test_acquire_token_ascii_less_than_2048(acquirer): - text = "Ѐ" +@pytest.mark.asyncio +async def test_acquire_token_ascii_less_than_2048( + acquirer: gtoken.TokenAcquirer, +) -> None: + text: str = "Ѐ" - result = acquirer.do(text) + result: str = await acquirer.do(text) assert result -def test_acquire_token_ascii_matches_special_condition(acquirer): - def unichar(i): - try: - return unichr(i) - except NameError: - return chr(i) +@pytest.mark.asyncio +async def test_acquire_token_ascii_matches_special_condition( + acquirer: gtoken.TokenAcquirer, +) -> None: + def unichar(i: int) -> str: + return chr(i) - text = unichar(55296) + unichar(56320) + text: str = unichar(55296) + unichar(56320) - result = acquirer.do(text) + result: str = await acquirer.do(text) assert result -def test_acquire_token_ascii_else(acquirer): - text = "가" +@pytest.mark.asyncio +async def test_acquire_token_ascii_else(acquirer: gtoken.TokenAcquirer) -> None: + text: str = "가" - result = acquirer.do(text) + result: str = await acquirer.do(text) assert result -def test_reuse_valid_token(acquirer): - text = "test" +@pytest.mark.asyncio +async def test_reuse_valid_token(acquirer: gtoken.TokenAcquirer) -> None: + text: str = "test" - first = acquirer.do(text) - second = acquirer.do(text) + first: str = await acquirer.do(text) + second: str = await acquirer.do(text) assert first == second -def test_map_lazy_return(acquirer): - value = True +def test_map_lazy_return(acquirer: gtoken.TokenAcquirer) -> None: + value: bool = True - func = acquirer._lazy(value) + func: Callable[[], Any] = acquirer._lazy(value) assert callable(func) assert func() == value