Skip to content

Commit

Permalink
fix: correctly typed
Browse files Browse the repository at this point in the history
  • Loading branch information
ssut committed Nov 20, 2024
1 parent d2ce980 commit e197495
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 104 deletions.
42 changes: 26 additions & 16 deletions googletrans/client.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
"""
A Translation module.
Expand Down Expand Up @@ -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":
Expand Down Expand Up @@ -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
Expand All @@ -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",
Expand All @@ -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]],
Expand Down Expand Up @@ -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
Expand Down
Empty file added tests/__init__.py
Empty file.
131 changes: 72 additions & 59 deletions tests/test_client.py
Original file line number Diff line number Diff line change
@@ -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",
Expand All @@ -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"
Expand All @@ -105,52 +118,51 @@ 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"
assert result[2].lang == "mk"
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:
Expand All @@ -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")
Loading

0 comments on commit e197495

Please sign in to comment.