Skip to content

Commit

Permalink
Merge pull request nidhaloff#130 from Vincent-Stragier/master
Browse files Browse the repository at this point in the history
Autogenerate the a dictionary of translators to hide class inheritance inconsistancy.
  • Loading branch information
nidhaloff authored Feb 23, 2022
2 parents ed150d4 + 697d292 commit 0cfe8e5
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 45 deletions.
7 changes: 6 additions & 1 deletion deep_translator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .microsoft import MicrosoftTranslator
from .papago import PapagoTranslator
from .libre import LibreTranslator
from .engine import generate_engines_dict, engine

__author__ = """Nidhal Baccouri"""
__email__ = '[email protected]'
Expand All @@ -29,4 +30,8 @@
"PapagoTranslator",
"single_detection",
"batch_detection"
]
]

__engines__ = generate_engines_dict(__all__, locals())
del generate_engines_dict
engine.translation_engines = __engines__
29 changes: 3 additions & 26 deletions deep_translator/cli.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,16 @@
"""Console script for deep_translator."""

from .google_trans import GoogleTranslator
from .mymemory import MyMemoryTranslator
from .pons import PonsTranslator
from .linguee import LingueeTranslator
from .yandex import YandexTranslator
from .deepl import DeepL
from .qcri import QCRI
from .papago import PapagoTranslator
from .microsoft import MicrosoftTranslator
from .libre import LibreTranslator
from . import __engines__
import argparse


class CLI(object):

translators_dict = None
translators_dict = __engines__
translator = None

def __init__(self, custom_args=None):
self.translators_dict = {
'google': GoogleTranslator,
'pons': PonsTranslator,
'linguee': LingueeTranslator,
'mymemory': MyMemoryTranslator,
'deepl': DeepL,
'libre': LibreTranslator,
'yandex': YandexTranslator,
'microsoft': MicrosoftTranslator,
'qcri': QCRI,
'papago': PapagoTranslator
}
self.custom_args = custom_args
self.args = self.parse_args()

# print(f'{__engines__}')
translator_class = self.translators_dict.get(self.args.translator, None)
if not translator_class:
raise Exception(f"Translator {self.args.translator} is not supported."
Expand Down
19 changes: 13 additions & 6 deletions deep_translator/deepl.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import requests
from .constants import BASE_URLS, DEEPL_LANGUAGE_TO_CODE
from .exceptions import (ServerException,
TranslationNotFound,
LanguageNotSupportedException,
AuthorizationException)
TranslationNotFound,
LanguageNotSupportedException,
AuthorizationException)
from .parent import BaseTranslator


class DeepL(object):
Expand All @@ -26,9 +27,11 @@ def __init__(self, api_key=None, source="en", target="en", use_free_api=True, **
self.source = self._map_language_to_code(source)
self.target = self._map_language_to_code(target)
if use_free_api:
self.__base_url = BASE_URLS.get("DEEPL_FREE").format(version=self.version)
self.__base_url = BASE_URLS.get(
"DEEPL_FREE").format(version=self.version)
else:
self.__base_url = BASE_URLS.get("DEEPL").format(version=self.version)
self.__base_url = BASE_URLS.get(
"DEEPL").format(version=self.version)

def translate(self, text, **kwargs):
"""
Expand All @@ -45,7 +48,8 @@ def translate(self, text, **kwargs):
}
# Do the request and check the connection.
try:
response = requests.get(self.__base_url + translate_endpoint, params=params)
response = requests.get(
self.__base_url + translate_endpoint, params=params)
except ConnectionError:
raise ServerException(503)
# If the answer is not success, raise server exception.
Expand Down Expand Up @@ -83,6 +87,9 @@ def _map_language_to_code(self, lang, **kwargs):
raise LanguageNotSupportedException(lang)


BaseTranslator.register(DeepL)


if __name__ == '__main__':
d = DeepL(target="de")
t = d.translate("I have no idea")
Expand Down
45 changes: 45 additions & 0 deletions deep_translator/engine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from .parent import BaseTranslator

# BaseTranslator.register(YandexTranslator)
# BaseTranslator.register(QCRI)
# BaseTranslator.register(DeepL)
# BaseTranslator.register(MicrosoftTranslator)
# BaseTranslator.register(PapagoTranslator)


def generate_engines_dict(_all: list, _locals: dict) -> dict:
base_translator_type = BaseTranslator

def is_translator(__object: object) -> bool:
try:
return issubclass(__object, base_translator_type)
except TypeError:
return False

translation_engines = {}
for _object in _all:
__object = _locals.get(_object, 'failed')
key_name = _object.replace('Translator', '').lower()
if is_translator(__object):
translation_engines.update({key_name: __object})
return translation_engines


def engine(engine_name: str, *args, **kwargs) -> BaseTranslator:
"""Return translation engine.
Free and keyless engines are 'google', 'pons', 'linguee', 'mymemory',
'libre'.
Args:
engine_name: the name of the engine
*args: positional argument to pass to the engine
**kwargs: named argument to pass to the engine
Return:
A translation engine
"""
try:
return engine.translation_engines[engine_name.lower()](*args, **kwargs)
except KeyError:
keys = '\', \''.join(engine.translation_engines.keys())
raise(KeyError(f'Please provide a valid engine name (\'{keys}\')'))
7 changes: 6 additions & 1 deletion deep_translator/microsoft.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from .constants import BASE_URLS, MICROSOFT_CODES_TO_LANGUAGES
from .exceptions import LanguageNotSupportedException, ServerException, MicrosoftAPIerror
from .parent import BaseTranslator


class MicrosoftTranslator:
Expand Down Expand Up @@ -121,7 +122,8 @@ def translate(self, text, **kwargs):
raise MicrosoftAPIerror(error_message)
# Where it responds with a translation, its response.json() is a list e.g. [{'translations': [{'text': 'Hello world!', 'to': 'en'}]}]
elif type(requested.json()) is list:
all_translations = [i['text'] for i in requested.json()[0]['translations']]
all_translations = [i['text']
for i in requested.json()[0]['translations']]
return "\n".join(all_translations)

def translate_file(self, path, **kwargs):
Expand All @@ -144,3 +146,6 @@ def translate_batch(self, batch, **kwargs):
@return: list of translations
"""
return [self.translate(text, **kwargs) for text in batch]


BaseTranslator.register(MicrosoftTranslator)
17 changes: 12 additions & 5 deletions deep_translator/papago.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import json
from .constants import BASE_URLS, PAPAGO_LANGUAGE_TO_CODE
from .exceptions import LanguageNotSupportedException, TranslationNotFound, NotValidPayload
from .parent import BaseTranslator
import requests
import warnings
import logging
Expand All @@ -22,13 +23,15 @@ def __init__(self, client_id=None, secret_key=None, source="auto", target="en",
@param target: target language to translate to
"""
if not client_id or not secret_key:
raise Exception("Please pass your client id and secret key! visit the papago website for more infos")
raise Exception(
"Please pass your client id and secret key! visit the papago website for more infos")

self.__base_url = BASE_URLS.get("PAPAGO_API")
self.client_id = client_id
self.secret_key = secret_key
if self.is_language_supported(source, target):
self._source, self._target = self._map_language_to_code(source.lower(), target.lower())
self._source, self._target = self._map_language_to_code(
source.lower(), target.lower())

@staticmethod
def get_supported_languages(as_dict=False, **kwargs):
Expand Down Expand Up @@ -82,9 +85,11 @@ def translate(self, text, **kwargs):
'X-Naver-Client-Secret': self.secret_key,
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
response = requests.post(self.__base_url, headers=headers, data=payload)
response = requests.post(
self.__base_url, headers=headers, data=payload)
if response.status_code != 200:
raise Exception(f'Translation error! -> status code: {response.status_code}')
raise Exception(
f'Translation error! -> status code: {response.status_code}')
res_body = json.loads(response.text)
if "message" not in res_body:
raise TranslationNotFound(text)
Expand Down Expand Up @@ -120,7 +125,8 @@ def translate_sentences(self, sentences=None, **kwargs):
@param sentences: list of sentences to translate
@return: list of all translated sentences
"""
warnings.warn("deprecated. Use the translate_batch function instead", DeprecationWarning, stacklevel=2)
warnings.warn("deprecated. Use the translate_batch function instead",
DeprecationWarning, stacklevel=2)
logging.warning("deprecated. Use the translate_batch function instead")
if not sentences:
raise NotValidPayload(sentences)
Expand Down Expand Up @@ -152,3 +158,4 @@ def translate_batch(self, batch=None, **kwargs):
return arr


BaseTranslator.register(PapagoTranslator)
6 changes: 5 additions & 1 deletion deep_translator/qcri.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import requests
from .constants import BASE_URLS, QCRI_LANGUAGE_TO_CODE
from .exceptions import (ServerException, TranslationNotFound)
from .parent import BaseTranslator


class QCRI(object):
Expand Down Expand Up @@ -34,7 +35,8 @@ def _get(self, endpoint, params=None, return_text=True):
if not params:
params = self.params
try:
res = requests.get(self.__base_url.format(endpoint=self.api_endpoints[endpoint]), params=params)
res = requests.get(self.__base_url.format(
endpoint=self.api_endpoints[endpoint]), params=params)
return res.text if return_text else res
except Exception as e:
raise e
Expand Down Expand Up @@ -90,3 +92,5 @@ def translate_batch(self, batch, domain, **kwargs):
"""
return [self.translate(domain, text, **kwargs) for text in batch]


BaseTranslator.register(QCRI)
19 changes: 14 additions & 5 deletions deep_translator/yandex.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"""
import requests
from .constants import BASE_URLS
from .exceptions import (RequestError, ServerException, TranslationNotFound, TooManyRequests)
from .exceptions import (RequestError, ServerException,
TranslationNotFound, TooManyRequests)
from .parent import BaseTranslator


class YandexTranslator(object):
Expand Down Expand Up @@ -47,9 +49,11 @@ def languages(self):
def dirs(self, proxies=None):

try:
url = self.__base_url.format(version=self.api_version, endpoint="getLangs")
url = self.__base_url.format(
version=self.api_version, endpoint="getLangs")
print("url: ", url)
response = requests.get(url, params={"key": self.api_key}, proxies=proxies)
response = requests.get(
url, params={"key": self.api_key}, proxies=proxies)
except requests.exceptions.ConnectionError:
raise ServerException(503)
else:
Expand All @@ -67,7 +71,8 @@ def detect(self, text, proxies=None):
"key": self.api_key,
}
try:
url = self.__base_url.format(version=self.api_version, endpoint="detect")
url = self.__base_url.format(
version=self.api_version, endpoint="detect")
response = requests.post(url, data=params, proxies=proxies)

except RequestError:
Expand All @@ -94,7 +99,8 @@ def translate(self, text, proxies=None, **kwargs):
"key": self.api_key
}
try:
url = self.__base_url.format(version=self.api_version, endpoint="translate")
url = self.__base_url.format(
version=self.api_version, endpoint="translate")
response = requests.post(url, data=params, proxies=proxies)
except ConnectionError:
raise ServerException(503)
Expand Down Expand Up @@ -133,3 +139,6 @@ def translate_batch(self, batch, **kwargs):
@return: list of translations
"""
return [self.translate(text, **kwargs) for text in batch]


BaseTranslator.register(YandexTranslator)

0 comments on commit 0cfe8e5

Please sign in to comment.