nidhal baccouri
commited on
Commit
·
78d0ff1
1
Parent(s):
721a708
added black for formatting
Browse files- Makefile +1 -1
- deep_translator/__init__.py +14 -14
- deep_translator/__main__.py +1 -2
- deep_translator/base.py +22 -15
- deep_translator/cli.py +51 -35
- deep_translator/constants.py +166 -176
- deep_translator/deepl.py +22 -14
- deep_translator/detection.py +19 -14
- deep_translator/engines.py +3 -4
- deep_translator/exceptions.py +29 -18
- deep_translator/google.py +30 -18
- deep_translator/libre.py +20 -14
- deep_translator/linguee.py +28 -23
- deep_translator/microsoft.py +31 -21
- deep_translator/mymemory.py +30 -27
- deep_translator/papago.py +17 -18
- deep_translator/pons.py +25 -24
- deep_translator/qcri.py +11 -12
- deep_translator/validate.py +1 -3
- deep_translator/yandex.py +26 -25
- poetry.lock +151 -1
- pyproject.toml +1 -0
- tests/test_cli.py +3 -5
- tests/test_data.py +2 -2
- tests/test_deepl.py +12 -12
- tests/test_google.py +7 -7
- tests/test_libre.py +6 -6
- tests/test_linguee.py +3 -3
- tests/test_microsoft_trans.py +21 -8
- tests/test_mymemory.py +3 -5
- tests/test_pons.py +2 -3
Makefile
CHANGED
@@ -48,7 +48,7 @@ clean-test: ## remove test and coverage artifacts
|
|
48 |
rm -fr .pytest_cache
|
49 |
|
50 |
lint: ## check style with flake8
|
51 |
-
|
52 |
|
53 |
test: ## run tests quickly with the default Python
|
54 |
pytest
|
|
|
48 |
rm -fr .pytest_cache
|
49 |
|
50 |
lint: ## check style with flake8
|
51 |
+
poetry run black deep_translator tests
|
52 |
|
53 |
test: ## run tests quickly with the default Python
|
54 |
pytest
|
deep_translator/__init__.py
CHANGED
@@ -1,20 +1,20 @@
|
|
1 |
"""Top-level package for Deep Translator"""
|
2 |
|
3 |
-
from .google import GoogleTranslator
|
4 |
-
from .pons import PonsTranslator
|
5 |
-
from .linguee import LingueeTranslator
|
6 |
-
from .mymemory import MyMemoryTranslator
|
7 |
-
from .yandex import YandexTranslator
|
8 |
-
from .qcri import QcriTranslator
|
9 |
-
from .deepl import DeeplTranslator
|
10 |
-
from .detection import single_detection, batch_detection
|
11 |
-
from .microsoft import MicrosoftTranslator
|
12 |
-
from .papago import PapagoTranslator
|
13 |
-
from .libre import LibreTranslator
|
14 |
|
15 |
__author__ = """Nidhal Baccouri"""
|
16 |
-
__email__ =
|
17 |
-
__version__ =
|
18 |
|
19 |
__all__ = [
|
20 |
"GoogleTranslator",
|
@@ -28,5 +28,5 @@ __all__ = [
|
|
28 |
"LibreTranslator",
|
29 |
"PapagoTranslator",
|
30 |
"single_detection",
|
31 |
-
"batch_detection"
|
32 |
]
|
|
|
1 |
"""Top-level package for Deep Translator"""
|
2 |
|
3 |
+
from deep_translator.google import GoogleTranslator
|
4 |
+
from deep_translator.pons import PonsTranslator
|
5 |
+
from deep_translator.linguee import LingueeTranslator
|
6 |
+
from deep_translator.mymemory import MyMemoryTranslator
|
7 |
+
from deep_translator.yandex import YandexTranslator
|
8 |
+
from deep_translator.qcri import QcriTranslator
|
9 |
+
from deep_translator.deepl import DeeplTranslator
|
10 |
+
from deep_translator.detection import single_detection, batch_detection
|
11 |
+
from deep_translator.microsoft import MicrosoftTranslator
|
12 |
+
from deep_translator.papago import PapagoTranslator
|
13 |
+
from deep_translator.libre import LibreTranslator
|
14 |
|
15 |
__author__ = """Nidhal Baccouri"""
|
16 |
+
__email__ = "[email protected]"
|
17 |
+
__version__ = "1.7.1"
|
18 |
|
19 |
__all__ = [
|
20 |
"GoogleTranslator",
|
|
|
28 |
"LibreTranslator",
|
29 |
"PapagoTranslator",
|
30 |
"single_detection",
|
31 |
+
"batch_detection",
|
32 |
]
|
deep_translator/__main__.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1 |
-
|
2 |
-
from .cli import CLI
|
3 |
|
4 |
|
5 |
def main():
|
|
|
1 |
+
from deep_translator.cli import CLI
|
|
|
2 |
|
3 |
|
4 |
def main():
|
deep_translator/base.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
"""base translator class"""
|
2 |
|
3 |
-
from .constants import GOOGLE_LANGUAGES_TO_CODES
|
4 |
-
from .exceptions import InvalidSourceOrTargetLanguage
|
5 |
from abc import ABC, abstractmethod
|
6 |
|
7 |
|
@@ -9,15 +9,18 @@ class BaseTranslator(ABC):
|
|
9 |
"""
|
10 |
Abstract class that serve as a base translator for other different translators
|
11 |
"""
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
21 |
"""
|
22 |
@param source: source language to translate from
|
23 |
@param target: target language to translate to
|
@@ -47,7 +50,7 @@ class BaseTranslator(ABC):
|
|
47 |
@return: mapped value of the language or raise an exception if the language is not supported
|
48 |
"""
|
49 |
for language in languages:
|
50 |
-
if language in self.languages.values() or language ==
|
51 |
yield language
|
52 |
elif language in self.languages.keys():
|
53 |
yield self.languages[language]
|
@@ -69,7 +72,11 @@ class BaseTranslator(ABC):
|
|
69 |
@param language: a string for 1 language
|
70 |
@return: bool or raise an Exception
|
71 |
"""
|
72 |
-
if
|
|
|
|
|
|
|
|
|
73 |
return True
|
74 |
else:
|
75 |
return False
|
@@ -82,7 +89,7 @@ class BaseTranslator(ABC):
|
|
82 |
@param kwargs: additional arguments
|
83 |
@return: str
|
84 |
"""
|
85 |
-
return NotImplemented(
|
86 |
|
87 |
def _translate_file(self, path, **kwargs):
|
88 |
"""
|
@@ -93,7 +100,7 @@ class BaseTranslator(ABC):
|
|
93 |
@return: str
|
94 |
"""
|
95 |
try:
|
96 |
-
with open(path,
|
97 |
text = f.read().strip()
|
98 |
return self.translate(text)
|
99 |
except Exception as e:
|
|
|
1 |
"""base translator class"""
|
2 |
|
3 |
+
from deep_translator.constants import GOOGLE_LANGUAGES_TO_CODES
|
4 |
+
from deep_translator.exceptions import InvalidSourceOrTargetLanguage
|
5 |
from abc import ABC, abstractmethod
|
6 |
|
7 |
|
|
|
9 |
"""
|
10 |
Abstract class that serve as a base translator for other different translators
|
11 |
"""
|
12 |
+
|
13 |
+
def __init__(
|
14 |
+
self,
|
15 |
+
base_url=None,
|
16 |
+
source="auto",
|
17 |
+
target="en",
|
18 |
+
payload_key=None,
|
19 |
+
element_tag=None,
|
20 |
+
element_query=None,
|
21 |
+
languages=None,
|
22 |
+
**url_params
|
23 |
+
):
|
24 |
"""
|
25 |
@param source: source language to translate from
|
26 |
@param target: target language to translate to
|
|
|
50 |
@return: mapped value of the language or raise an exception if the language is not supported
|
51 |
"""
|
52 |
for language in languages:
|
53 |
+
if language in self.languages.values() or language == "auto":
|
54 |
yield language
|
55 |
elif language in self.languages.keys():
|
56 |
yield self.languages[language]
|
|
|
72 |
@param language: a string for 1 language
|
73 |
@return: bool or raise an Exception
|
74 |
"""
|
75 |
+
if (
|
76 |
+
language == "auto"
|
77 |
+
or language in self.languages.keys()
|
78 |
+
or language in self.languages.values()
|
79 |
+
):
|
80 |
return True
|
81 |
else:
|
82 |
return False
|
|
|
89 |
@param kwargs: additional arguments
|
90 |
@return: str
|
91 |
"""
|
92 |
+
return NotImplemented("You need to implement the translate method!")
|
93 |
|
94 |
def _translate_file(self, path, **kwargs):
|
95 |
"""
|
|
|
100 |
@return: str
|
101 |
"""
|
102 |
try:
|
103 |
+
with open(path, "r", encoding="utf-8") as f:
|
104 |
text = f.read().strip()
|
105 |
return self.translate(text)
|
106 |
except Exception as e:
|
deep_translator/cli.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
"""Console script for deep_translator."""
|
2 |
import argparse
|
3 |
-
from .engines import __engines__
|
4 |
|
5 |
|
6 |
class CLI(object):
|
@@ -12,9 +12,13 @@ class CLI(object):
|
|
12 |
self.args = self.parse_args()
|
13 |
translator_class = self.translators_dict.get(self.args.translator, None)
|
14 |
if not translator_class:
|
15 |
-
raise Exception(
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
18 |
|
19 |
def translate(self):
|
20 |
"""
|
@@ -22,9 +26,9 @@ class CLI(object):
|
|
22 |
@return: None
|
23 |
"""
|
24 |
res = self.translator.translate(self.args.text)
|
25 |
-
print("Translation from {
|
26 |
print("-" * 50)
|
27 |
-
print("Translation result: {}"
|
28 |
|
29 |
def get_supported_languages(self):
|
30 |
"""
|
@@ -32,42 +36,54 @@ class CLI(object):
|
|
32 |
@return: None
|
33 |
"""
|
34 |
|
35 |
-
translator_supported_languages = self.translator.get_supported_languages(
|
36 |
-
|
|
|
|
|
37 |
print(translator_supported_languages)
|
38 |
|
39 |
def parse_args(self):
|
40 |
"""
|
41 |
function responsible for parsing terminal arguments and provide them for further use in the translation process
|
42 |
"""
|
43 |
-
parser = argparse.ArgumentParser(
|
44 |
-
|
45 |
-
|
|
|
|
|
46 |
|
47 |
-
parser.add_argument(
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
parser.add_argument(
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
return parsed_args
|
72 |
|
73 |
def run(self):
|
|
|
1 |
"""Console script for deep_translator."""
|
2 |
import argparse
|
3 |
+
from deep_translator.engines import __engines__
|
4 |
|
5 |
|
6 |
class CLI(object):
|
|
|
12 |
self.args = self.parse_args()
|
13 |
translator_class = self.translators_dict.get(self.args.translator, None)
|
14 |
if not translator_class:
|
15 |
+
raise Exception(
|
16 |
+
f"Translator {self.args.translator} is not supported."
|
17 |
+
f"Supported translators: {list(self.translators_dict.keys())}"
|
18 |
+
)
|
19 |
+
self.translator = translator_class(
|
20 |
+
source=self.args.source, target=self.args.target
|
21 |
+
)
|
22 |
|
23 |
def translate(self):
|
24 |
"""
|
|
|
26 |
@return: None
|
27 |
"""
|
28 |
res = self.translator.translate(self.args.text)
|
29 |
+
print(f"Translation from {self.args.source} to {self.args.target}")
|
30 |
print("-" * 50)
|
31 |
+
print(f"Translation result: {res}")
|
32 |
|
33 |
def get_supported_languages(self):
|
34 |
"""
|
|
|
36 |
@return: None
|
37 |
"""
|
38 |
|
39 |
+
translator_supported_languages = self.translator.get_supported_languages(
|
40 |
+
as_dict=True
|
41 |
+
)
|
42 |
+
print(f"Languages supported by '{self.args.translator}' are :\n")
|
43 |
print(translator_supported_languages)
|
44 |
|
45 |
def parse_args(self):
|
46 |
"""
|
47 |
function responsible for parsing terminal arguments and provide them for further use in the translation process
|
48 |
"""
|
49 |
+
parser = argparse.ArgumentParser(
|
50 |
+
add_help=True,
|
51 |
+
description="Official CLI for deep-translator",
|
52 |
+
usage="dt --help",
|
53 |
+
)
|
54 |
|
55 |
+
parser.add_argument(
|
56 |
+
"--translator",
|
57 |
+
"-trans",
|
58 |
+
default="google",
|
59 |
+
type=str,
|
60 |
+
help="name of the translator you want to use",
|
61 |
+
)
|
62 |
+
parser.add_argument(
|
63 |
+
"--source",
|
64 |
+
"-src",
|
65 |
+
default="auto",
|
66 |
+
type=str,
|
67 |
+
help="source language to translate from",
|
68 |
+
)
|
69 |
+
parser.add_argument(
|
70 |
+
"--target", "-tg", type=str, help="target language to translate to"
|
71 |
+
)
|
72 |
+
parser.add_argument(
|
73 |
+
"--text", "-txt", type=str, help="text you want to translate"
|
74 |
+
)
|
75 |
+
parser.add_argument(
|
76 |
+
"--languages",
|
77 |
+
"-lang",
|
78 |
+
action="store_true",
|
79 |
+
help="all the languages available with the translator"
|
80 |
+
"Run the command deep_translator -trans <translator service> -lang",
|
81 |
+
)
|
82 |
+
parsed_args = (
|
83 |
+
parser.parse_args(self.custom_args)
|
84 |
+
if self.custom_args
|
85 |
+
else parser.parse_args()
|
86 |
+
)
|
87 |
return parsed_args
|
88 |
|
89 |
def run(self):
|
deep_translator/constants.py
CHANGED
@@ -1,5 +1,3 @@
|
|
1 |
-
import requests
|
2 |
-
|
3 |
BASE_URLS = {
|
4 |
"GOOGLE_TRANSLATE": "https://translate.google.com/m",
|
5 |
"PONS": "https://en.pons.com/translate/",
|
@@ -17,150 +15,150 @@ BASE_URLS = {
|
|
17 |
}
|
18 |
|
19 |
GOOGLE_CODES_TO_LANGUAGES = {
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
}
|
130 |
|
131 |
GOOGLE_LANGUAGES_TO_CODES = {v: k for k, v in GOOGLE_CODES_TO_LANGUAGES.items()}
|
132 |
|
133 |
# This dictionary maps the primary name of language to its secondary names in list manner (if any)
|
134 |
GOOGLE_LANGUAGES_SECONDARY_NAMES = {
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
}
|
139 |
|
140 |
|
141 |
PONS_CODES_TO_LANGUAGES = {
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
}
|
165 |
|
166 |
PONS_LANGUAGES_TO_CODES = {v: k for k, v in PONS_CODES_TO_LANGUAGES.items()}
|
@@ -192,7 +190,7 @@ LINGUEE_LANGUAGES_TO_CODES = {
|
|
192 |
"swedish": "sv",
|
193 |
"latvian": "lv",
|
194 |
"estonian": "et",
|
195 |
-
"japanese": "ja"
|
196 |
}
|
197 |
|
198 |
LINGUEE_CODE_TO_LANGUAGE = {v: k for k, v in LINGUEE_LANGUAGES_TO_CODES.items()}
|
@@ -221,56 +219,48 @@ DEEPL_LANGUAGE_TO_CODE = {
|
|
221 |
"slovak": "sk",
|
222 |
"slovenian": "sl",
|
223 |
"swedish": "sv",
|
224 |
-
"chinese": "zh"
|
225 |
}
|
226 |
|
227 |
DEEPL_CODE_TO_LANGUAGE = {v: k for k, v in DEEPL_LANGUAGE_TO_CODE.items()}
|
228 |
|
229 |
PAPAGO_CODE_TO_LANGUAGE = {
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
}
|
241 |
|
242 |
PAPAGO_LANGUAGE_TO_CODE = {v: k for v, k in PAPAGO_CODE_TO_LANGUAGE.items()}
|
243 |
|
244 |
-
QCRI_CODE_TO_LANGUAGE = {
|
245 |
-
'ar': 'Arabic',
|
246 |
-
'en': 'English',
|
247 |
-
'es': 'Spanish'
|
248 |
-
}
|
249 |
|
250 |
-
QCRI_LANGUAGE_TO_CODE = {
|
251 |
-
v: k for k, v in QCRI_CODE_TO_LANGUAGE.items()
|
252 |
-
}
|
253 |
|
254 |
LIBRE_CODES_TO_LANGUAGES = {
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
}
|
273 |
|
274 |
-
LIBRE_LANGUAGES_TO_CODES = {
|
275 |
-
v: k for k, v in LIBRE_CODES_TO_LANGUAGES.items()
|
276 |
-
}
|
|
|
|
|
|
|
1 |
BASE_URLS = {
|
2 |
"GOOGLE_TRANSLATE": "https://translate.google.com/m",
|
3 |
"PONS": "https://en.pons.com/translate/",
|
|
|
15 |
}
|
16 |
|
17 |
GOOGLE_CODES_TO_LANGUAGES = {
|
18 |
+
"af": "afrikaans",
|
19 |
+
"sq": "albanian",
|
20 |
+
"am": "amharic",
|
21 |
+
"ar": "arabic",
|
22 |
+
"hy": "armenian",
|
23 |
+
"az": "azerbaijani",
|
24 |
+
"eu": "basque",
|
25 |
+
"be": "belarusian",
|
26 |
+
"bn": "bengali",
|
27 |
+
"bs": "bosnian",
|
28 |
+
"bg": "bulgarian",
|
29 |
+
"ca": "catalan",
|
30 |
+
"ceb": "cebuano",
|
31 |
+
"ny": "chichewa",
|
32 |
+
"zh-CN": "chinese (simplified)",
|
33 |
+
"zh-TW": "chinese (traditional)",
|
34 |
+
"co": "corsican",
|
35 |
+
"hr": "croatian",
|
36 |
+
"cs": "czech",
|
37 |
+
"da": "danish",
|
38 |
+
"nl": "dutch",
|
39 |
+
"en": "english",
|
40 |
+
"eo": "esperanto",
|
41 |
+
"et": "estonian",
|
42 |
+
"tl": "filipino",
|
43 |
+
"fi": "finnish",
|
44 |
+
"fr": "french",
|
45 |
+
"fy": "frisian",
|
46 |
+
"gl": "galician",
|
47 |
+
"ka": "georgian",
|
48 |
+
"de": "german",
|
49 |
+
"el": "greek",
|
50 |
+
"gu": "gujarati",
|
51 |
+
"ht": "haitian creole",
|
52 |
+
"ha": "hausa",
|
53 |
+
"haw": "hawaiian",
|
54 |
+
"iw": "hebrew",
|
55 |
+
"hi": "hindi",
|
56 |
+
"hmn": "hmong",
|
57 |
+
"hu": "hungarian",
|
58 |
+
"is": "icelandic",
|
59 |
+
"ig": "igbo",
|
60 |
+
"id": "indonesian",
|
61 |
+
"ga": "irish",
|
62 |
+
"it": "italian",
|
63 |
+
"ja": "japanese",
|
64 |
+
"jw": "javanese",
|
65 |
+
"kn": "kannada",
|
66 |
+
"kk": "kazakh",
|
67 |
+
"km": "khmer",
|
68 |
+
"rw": "kinyarwanda",
|
69 |
+
"ko": "korean",
|
70 |
+
"ku": "kurdish",
|
71 |
+
"ky": "kyrgyz",
|
72 |
+
"lo": "lao",
|
73 |
+
"la": "latin",
|
74 |
+
"lv": "latvian",
|
75 |
+
"lt": "lithuanian",
|
76 |
+
"lb": "luxembourgish",
|
77 |
+
"mk": "macedonian",
|
78 |
+
"mg": "malagasy",
|
79 |
+
"ms": "malay",
|
80 |
+
"ml": "malayalam",
|
81 |
+
"mt": "maltese",
|
82 |
+
"mi": "maori",
|
83 |
+
"mr": "marathi",
|
84 |
+
"mn": "mongolian",
|
85 |
+
"my": "myanmar",
|
86 |
+
"ne": "nepali",
|
87 |
+
"no": "norwegian",
|
88 |
+
"or": "odia",
|
89 |
+
"ps": "pashto",
|
90 |
+
"fa": "persian",
|
91 |
+
"pl": "polish",
|
92 |
+
"pt": "portuguese",
|
93 |
+
"pa": "punjabi",
|
94 |
+
"ro": "romanian",
|
95 |
+
"ru": "russian",
|
96 |
+
"sm": "samoan",
|
97 |
+
"gd": "scots gaelic",
|
98 |
+
"sr": "serbian",
|
99 |
+
"st": "sesotho",
|
100 |
+
"sn": "shona",
|
101 |
+
"sd": "sindhi",
|
102 |
+
"si": "sinhala",
|
103 |
+
"sk": "slovak",
|
104 |
+
"sl": "slovenian",
|
105 |
+
"so": "somali",
|
106 |
+
"es": "spanish",
|
107 |
+
"su": "sundanese",
|
108 |
+
"sw": "swahili",
|
109 |
+
"sv": "swedish",
|
110 |
+
"tg": "tajik",
|
111 |
+
"ta": "tamil",
|
112 |
+
"tt": "tatar",
|
113 |
+
"te": "telugu",
|
114 |
+
"th": "thai",
|
115 |
+
"tr": "turkish",
|
116 |
+
"tk": "turkmen",
|
117 |
+
"uk": "ukrainian",
|
118 |
+
"ur": "urdu",
|
119 |
+
"ug": "uyghur",
|
120 |
+
"uz": "uzbek",
|
121 |
+
"vi": "vietnamese",
|
122 |
+
"cy": "welsh",
|
123 |
+
"xh": "xhosa",
|
124 |
+
"yi": "yiddish",
|
125 |
+
"yo": "yoruba",
|
126 |
+
"zu": "zulu",
|
127 |
}
|
128 |
|
129 |
GOOGLE_LANGUAGES_TO_CODES = {v: k for k, v in GOOGLE_CODES_TO_LANGUAGES.items()}
|
130 |
|
131 |
# This dictionary maps the primary name of language to its secondary names in list manner (if any)
|
132 |
GOOGLE_LANGUAGES_SECONDARY_NAMES = {
|
133 |
+
"myanmar": ["burmese"],
|
134 |
+
"odia": ["oriya"],
|
135 |
+
"kurdish": ["kurmanji"],
|
136 |
}
|
137 |
|
138 |
|
139 |
PONS_CODES_TO_LANGUAGES = {
|
140 |
+
"ar": "arabic",
|
141 |
+
"bg": "bulgarian",
|
142 |
+
"zh-cn": "chinese",
|
143 |
+
"cs": "czech",
|
144 |
+
"da": "danish",
|
145 |
+
"nl": "dutch",
|
146 |
+
"en": "english",
|
147 |
+
"fr": "french",
|
148 |
+
"de": "german",
|
149 |
+
"el": "greek",
|
150 |
+
"hu": "hungarian",
|
151 |
+
"it": "italian",
|
152 |
+
"la": "latin",
|
153 |
+
"no": "norwegian",
|
154 |
+
"pl": "polish",
|
155 |
+
"pt": "portuguese",
|
156 |
+
"ru": "russian",
|
157 |
+
"sl": "slovenian",
|
158 |
+
"es": "spanish",
|
159 |
+
"sv": "swedish",
|
160 |
+
"tr": "turkish",
|
161 |
+
"elv": "elvish",
|
162 |
}
|
163 |
|
164 |
PONS_LANGUAGES_TO_CODES = {v: k for k, v in PONS_CODES_TO_LANGUAGES.items()}
|
|
|
190 |
"swedish": "sv",
|
191 |
"latvian": "lv",
|
192 |
"estonian": "et",
|
193 |
+
"japanese": "ja",
|
194 |
}
|
195 |
|
196 |
LINGUEE_CODE_TO_LANGUAGE = {v: k for k, v in LINGUEE_LANGUAGES_TO_CODES.items()}
|
|
|
219 |
"slovak": "sk",
|
220 |
"slovenian": "sl",
|
221 |
"swedish": "sv",
|
222 |
+
"chinese": "zh",
|
223 |
}
|
224 |
|
225 |
DEEPL_CODE_TO_LANGUAGE = {v: k for k, v in DEEPL_LANGUAGE_TO_CODE.items()}
|
226 |
|
227 |
PAPAGO_CODE_TO_LANGUAGE = {
|
228 |
+
"ko": "Korean",
|
229 |
+
"en": "English",
|
230 |
+
"ja": "Japanese",
|
231 |
+
"zh-CN": "Chinese",
|
232 |
+
"zh-TW": "Chinese traditional",
|
233 |
+
"es": "Spanish",
|
234 |
+
"fr": "French",
|
235 |
+
"vi": "Vietnamese",
|
236 |
+
"th": "Thai",
|
237 |
+
"id": "Indonesia",
|
238 |
}
|
239 |
|
240 |
PAPAGO_LANGUAGE_TO_CODE = {v: k for v, k in PAPAGO_CODE_TO_LANGUAGE.items()}
|
241 |
|
242 |
+
QCRI_CODE_TO_LANGUAGE = {"ar": "Arabic", "en": "English", "es": "Spanish"}
|
|
|
|
|
|
|
|
|
243 |
|
244 |
+
QCRI_LANGUAGE_TO_CODE = {v: k for k, v in QCRI_CODE_TO_LANGUAGE.items()}
|
|
|
|
|
245 |
|
246 |
LIBRE_CODES_TO_LANGUAGES = {
|
247 |
+
"en": "English",
|
248 |
+
"ar": "Arabic",
|
249 |
+
"zh": "Chinese",
|
250 |
+
"fr": "French",
|
251 |
+
"de": "German",
|
252 |
+
"hi": "Hindi",
|
253 |
+
"id": "Indonesian",
|
254 |
+
"ga": "Irish",
|
255 |
+
"it": "Italian",
|
256 |
+
"ja": "Japanese",
|
257 |
+
"ko": "Korean",
|
258 |
+
"pl": "Polish",
|
259 |
+
"pt": "Portuguese",
|
260 |
+
"ru": "Russian",
|
261 |
+
"es": "Spanish",
|
262 |
+
"tr": "Turkish",
|
263 |
+
"vi": "Vietnamese",
|
264 |
}
|
265 |
|
266 |
+
LIBRE_LANGUAGES_TO_CODES = {v: k for k, v in LIBRE_CODES_TO_LANGUAGES.items()}
|
|
|
|
deep_translator/deepl.py
CHANGED
@@ -2,9 +2,11 @@ import requests
|
|
2 |
|
3 |
from deep_translator.validate import is_empty, validate_input
|
4 |
from deep_translator.constants import BASE_URLS, DEEPL_LANGUAGE_TO_CODE
|
5 |
-
from deep_translator.exceptions import (
|
6 |
-
|
7 |
-
|
|
|
|
|
8 |
from deep_translator.base import BaseTranslator
|
9 |
|
10 |
|
@@ -13,7 +15,9 @@ class DeeplTranslator(BaseTranslator):
|
|
13 |
class that wraps functions, which use the DeeplTranslator translator under the hood to translate word(s)
|
14 |
"""
|
15 |
|
16 |
-
def __init__(
|
|
|
|
|
17 |
"""
|
18 |
@param api_key: your DeeplTranslator api key.
|
19 |
Get one here: https://www.deepl.com/docs-api/accessing-the-api/
|
@@ -22,17 +26,20 @@ class DeeplTranslator(BaseTranslator):
|
|
22 |
"""
|
23 |
if not api_key:
|
24 |
raise ServerException(401)
|
25 |
-
self.version =
|
26 |
self.api_key = api_key
|
27 |
-
url =
|
28 |
-
|
29 |
-
|
|
|
|
|
30 |
super().__init__(
|
31 |
base_url=url,
|
32 |
source=source,
|
33 |
target=target,
|
34 |
languages=DEEPL_LANGUAGE_TO_CODE,
|
35 |
-
**kwargs
|
|
|
36 |
|
37 |
def translate(self, text, **kwargs):
|
38 |
"""
|
@@ -44,17 +51,18 @@ class DeeplTranslator(BaseTranslator):
|
|
44 |
return text
|
45 |
|
46 |
# Create the request parameters.
|
47 |
-
translate_endpoint =
|
48 |
params = {
|
49 |
"auth_key": self.api_key,
|
50 |
"source_lang": self._source,
|
51 |
"target_lang": self._target,
|
52 |
-
"text": text
|
53 |
}
|
54 |
# Do the request and check the connection.
|
55 |
try:
|
56 |
response = requests.get(
|
57 |
-
self._base_url + translate_endpoint, params=params
|
|
|
58 |
except ConnectionError:
|
59 |
raise ServerException(503)
|
60 |
# If the answer is not success, raise server exception.
|
@@ -67,7 +75,7 @@ class DeeplTranslator(BaseTranslator):
|
|
67 |
if not res:
|
68 |
raise TranslationNotFound(text)
|
69 |
# Process and return the response.
|
70 |
-
return res[
|
71 |
|
72 |
def translate_file(self, path, **kwargs):
|
73 |
return self._translate_file(path, **kwargs)
|
@@ -80,7 +88,7 @@ class DeeplTranslator(BaseTranslator):
|
|
80 |
return self._translate_batch(batch, **kwargs)
|
81 |
|
82 |
|
83 |
-
if __name__ ==
|
84 |
d = DeeplTranslator(target="en", api_key="some-key")
|
85 |
t = d.translate("Ich habe keine ahnung")
|
86 |
print("text: ", t)
|
|
|
2 |
|
3 |
from deep_translator.validate import is_empty, validate_input
|
4 |
from deep_translator.constants import BASE_URLS, DEEPL_LANGUAGE_TO_CODE
|
5 |
+
from deep_translator.exceptions import (
|
6 |
+
ServerException,
|
7 |
+
TranslationNotFound,
|
8 |
+
AuthorizationException,
|
9 |
+
)
|
10 |
from deep_translator.base import BaseTranslator
|
11 |
|
12 |
|
|
|
15 |
class that wraps functions, which use the DeeplTranslator translator under the hood to translate word(s)
|
16 |
"""
|
17 |
|
18 |
+
def __init__(
|
19 |
+
self, api_key=None, source="de", target="en", use_free_api=True, **kwargs
|
20 |
+
):
|
21 |
"""
|
22 |
@param api_key: your DeeplTranslator api key.
|
23 |
Get one here: https://www.deepl.com/docs-api/accessing-the-api/
|
|
|
26 |
"""
|
27 |
if not api_key:
|
28 |
raise ServerException(401)
|
29 |
+
self.version = "v2"
|
30 |
self.api_key = api_key
|
31 |
+
url = (
|
32 |
+
BASE_URLS.get("DEEPL_FREE").format(version=self.version)
|
33 |
+
if use_free_api
|
34 |
+
else BASE_URLS.get("DEEPL").format(version=self.version)
|
35 |
+
)
|
36 |
super().__init__(
|
37 |
base_url=url,
|
38 |
source=source,
|
39 |
target=target,
|
40 |
languages=DEEPL_LANGUAGE_TO_CODE,
|
41 |
+
**kwargs
|
42 |
+
)
|
43 |
|
44 |
def translate(self, text, **kwargs):
|
45 |
"""
|
|
|
51 |
return text
|
52 |
|
53 |
# Create the request parameters.
|
54 |
+
translate_endpoint = "translate"
|
55 |
params = {
|
56 |
"auth_key": self.api_key,
|
57 |
"source_lang": self._source,
|
58 |
"target_lang": self._target,
|
59 |
+
"text": text,
|
60 |
}
|
61 |
# Do the request and check the connection.
|
62 |
try:
|
63 |
response = requests.get(
|
64 |
+
self._base_url + translate_endpoint, params=params
|
65 |
+
)
|
66 |
except ConnectionError:
|
67 |
raise ServerException(503)
|
68 |
# If the answer is not success, raise server exception.
|
|
|
75 |
if not res:
|
76 |
raise TranslationNotFound(text)
|
77 |
# Process and return the response.
|
78 |
+
return res["translations"][0]["text"]
|
79 |
|
80 |
def translate_file(self, path, **kwargs):
|
81 |
return self._translate_file(path, **kwargs)
|
|
|
88 |
return self._translate_batch(batch, **kwargs)
|
89 |
|
90 |
|
91 |
+
if __name__ == "__main__":
|
92 |
d = DeeplTranslator(target="en", api_key="some-key")
|
93 |
t = d.translate("Ich habe keine ahnung")
|
94 |
print("text: ", t)
|
deep_translator/detection.py
CHANGED
@@ -5,7 +5,13 @@ import requests
|
|
5 |
from requests.exceptions import HTTPError
|
6 |
|
7 |
# Module global config
|
8 |
-
config = {
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
|
11 |
def get_request_body(text, api_key, *args, **kwargs):
|
@@ -19,20 +25,20 @@ def get_request_body(text, api_key, *args, **kwargs):
|
|
19 |
|
20 |
"""
|
21 |
if not api_key:
|
22 |
-
raise Exception(
|
23 |
-
|
|
|
|
|
24 |
if not text:
|
25 |
raise Exception("Please provide an input text")
|
26 |
|
27 |
else:
|
28 |
try:
|
29 |
-
headers = config[
|
30 |
-
headers[
|
31 |
-
response = requests.post(config[
|
32 |
-
json={'q': text},
|
33 |
-
headers=headers)
|
34 |
|
35 |
-
body = response.json().get(
|
36 |
return body
|
37 |
|
38 |
except HTTPError as e:
|
@@ -51,11 +57,11 @@ def single_detection(text, api_key=None, detailed=False, *args, **kwargs):
|
|
51 |
@param detailed: set to True if you want to get detailed information about the detection process
|
52 |
"""
|
53 |
body = get_request_body(text, api_key)
|
54 |
-
detections = body.get(
|
55 |
if detailed:
|
56 |
return detections[0]
|
57 |
|
58 |
-
lang = detections[0].get(
|
59 |
if lang:
|
60 |
return lang
|
61 |
|
@@ -69,10 +75,9 @@ def batch_detection(text_list, api_key, detailed=False, *args, **kwargs):
|
|
69 |
@param detailed: set to True if you want to get detailed information about the detection process
|
70 |
"""
|
71 |
body = get_request_body(text_list, api_key)
|
72 |
-
detections = body.get(
|
73 |
res = [obj[0] for obj in detections]
|
74 |
if detailed:
|
75 |
return res
|
76 |
else:
|
77 |
-
return [obj[
|
78 |
-
|
|
|
5 |
from requests.exceptions import HTTPError
|
6 |
|
7 |
# Module global config
|
8 |
+
config = {
|
9 |
+
"url": "https://ws.detectlanguage.com/0.2/detect",
|
10 |
+
"headers": {
|
11 |
+
"User-Agent": "Detect Language API Python Client 1.4.0",
|
12 |
+
"Authorization": "Bearer {}",
|
13 |
+
},
|
14 |
+
}
|
15 |
|
16 |
|
17 |
def get_request_body(text, api_key, *args, **kwargs):
|
|
|
25 |
|
26 |
"""
|
27 |
if not api_key:
|
28 |
+
raise Exception(
|
29 |
+
"you need to get an API_KEY for this to work. "
|
30 |
+
"Get one for free here: https://detectlanguage.com/documentation"
|
31 |
+
)
|
32 |
if not text:
|
33 |
raise Exception("Please provide an input text")
|
34 |
|
35 |
else:
|
36 |
try:
|
37 |
+
headers = config["headers"]
|
38 |
+
headers["Authorization"] = headers["Authorization"].format(api_key)
|
39 |
+
response = requests.post(config["url"], json={"q": text}, headers=headers)
|
|
|
|
|
40 |
|
41 |
+
body = response.json().get("data")
|
42 |
return body
|
43 |
|
44 |
except HTTPError as e:
|
|
|
57 |
@param detailed: set to True if you want to get detailed information about the detection process
|
58 |
"""
|
59 |
body = get_request_body(text, api_key)
|
60 |
+
detections = body.get("detections")
|
61 |
if detailed:
|
62 |
return detections[0]
|
63 |
|
64 |
+
lang = detections[0].get("language", None)
|
65 |
if lang:
|
66 |
return lang
|
67 |
|
|
|
75 |
@param detailed: set to True if you want to get detailed information about the detection process
|
76 |
"""
|
77 |
body = get_request_body(text_list, api_key)
|
78 |
+
detections = body.get("detections")
|
79 |
res = [obj[0] for obj in detections]
|
80 |
if detailed:
|
81 |
return res
|
82 |
else:
|
83 |
+
return [obj["language"] for obj in res]
|
|
deep_translator/engines.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1 |
-
|
2 |
-
from .base import BaseTranslator
|
3 |
|
4 |
__engines__ = {
|
5 |
-
|
6 |
-
|
7 |
}
|
|
|
1 |
+
from deep_translator.base import BaseTranslator
|
|
|
2 |
|
3 |
__engines__ = {
|
4 |
+
translator.__name__.replace("Translator", "").lower(): translator
|
5 |
+
for translator in BaseTranslator.__subclasses__()
|
6 |
}
|
deep_translator/exceptions.py
CHANGED
@@ -30,9 +30,11 @@ class NotValidPayload(BaseError):
|
|
30 |
exception thrown if the user enters an invalid payload
|
31 |
"""
|
32 |
|
33 |
-
def __init__(
|
34 |
-
|
35 |
-
|
|
|
|
|
36 |
super(NotValidPayload, self).__init__(val, message)
|
37 |
|
38 |
|
@@ -41,9 +43,7 @@ class InvalidSourceOrTargetLanguage(BaseError):
|
|
41 |
exception thrown if the user enters an invalid payload
|
42 |
"""
|
43 |
|
44 |
-
def __init__(self,
|
45 |
-
val,
|
46 |
-
message="Invalid source or target language!"):
|
47 |
super(InvalidSourceOrTargetLanguage, self).__init__(val, message)
|
48 |
|
49 |
|
@@ -52,9 +52,11 @@ class TranslationNotFound(BaseError):
|
|
52 |
exception thrown if no translation was found for the text provided by the user
|
53 |
"""
|
54 |
|
55 |
-
def __init__(
|
56 |
-
|
57 |
-
|
|
|
|
|
58 |
super(TranslationNotFound, self).__init__(val, message)
|
59 |
|
60 |
|
@@ -63,9 +65,9 @@ class ElementNotFoundInGetRequest(BaseError):
|
|
63 |
exception thrown if the html element was not found in the body parsed by beautifulsoup
|
64 |
"""
|
65 |
|
66 |
-
def __init__(
|
67 |
-
|
68 |
-
|
69 |
super(ElementNotFoundInGetRequest, self).__init__(val, message)
|
70 |
|
71 |
|
@@ -75,7 +77,9 @@ class NotValidLength(BaseError):
|
|
75 |
"""
|
76 |
|
77 |
def __init__(self, val, min_chars, max_chars):
|
78 |
-
message =
|
|
|
|
|
79 |
super(NotValidLength, self).__init__(val, message)
|
80 |
|
81 |
|
@@ -84,8 +88,11 @@ class RequestError(Exception):
|
|
84 |
exception thrown if an error occurred during the request call, e.g a connection problem.
|
85 |
"""
|
86 |
|
87 |
-
def __init__(
|
88 |
-
|
|
|
|
|
|
|
89 |
self.message = message
|
90 |
|
91 |
def __str__(self):
|
@@ -99,7 +106,7 @@ class MicrosoftAPIerror(Exception):
|
|
99 |
|
100 |
def __init__(self, api_message):
|
101 |
self.api_message = str(api_message)
|
102 |
-
self.message="Microsoft API returned the following error"
|
103 |
|
104 |
def __str__(self):
|
105 |
return "{}: {}".format(self.message, self.api_message)
|
@@ -110,7 +117,10 @@ class TooManyRequests(Exception):
|
|
110 |
exception thrown if an error occurred during the request call, e.g a connection problem.
|
111 |
"""
|
112 |
|
113 |
-
def __init__(
|
|
|
|
|
|
|
114 |
self.message = message
|
115 |
|
116 |
def __str__(self):
|
@@ -121,6 +131,7 @@ class ServerException(Exception):
|
|
121 |
"""
|
122 |
Default YandexTranslate exception from the official website
|
123 |
"""
|
|
|
124 |
errors = {
|
125 |
400: "ERR_BAD_REQUEST",
|
126 |
401: "ERR_KEY_INVALID",
|
@@ -142,5 +153,5 @@ class ServerException(Exception):
|
|
142 |
|
143 |
class AuthorizationException(Exception):
|
144 |
def __init__(self, api_key, *args):
|
145 |
-
msg =
|
146 |
super().__init__(msg, *args)
|
|
|
30 |
exception thrown if the user enters an invalid payload
|
31 |
"""
|
32 |
|
33 |
+
def __init__(
|
34 |
+
self,
|
35 |
+
val,
|
36 |
+
message="text must be a valid text with maximum 5000 character, otherwise it cannot be translated",
|
37 |
+
):
|
38 |
super(NotValidPayload, self).__init__(val, message)
|
39 |
|
40 |
|
|
|
43 |
exception thrown if the user enters an invalid payload
|
44 |
"""
|
45 |
|
46 |
+
def __init__(self, val, message="Invalid source or target language!"):
|
|
|
|
|
47 |
super(InvalidSourceOrTargetLanguage, self).__init__(val, message)
|
48 |
|
49 |
|
|
|
52 |
exception thrown if no translation was found for the text provided by the user
|
53 |
"""
|
54 |
|
55 |
+
def __init__(
|
56 |
+
self,
|
57 |
+
val,
|
58 |
+
message="No translation was found using the current translator. Try another translator?",
|
59 |
+
):
|
60 |
super(TranslationNotFound, self).__init__(val, message)
|
61 |
|
62 |
|
|
|
65 |
exception thrown if the html element was not found in the body parsed by beautifulsoup
|
66 |
"""
|
67 |
|
68 |
+
def __init__(
|
69 |
+
self, val, message="Required element was not found in the API response"
|
70 |
+
):
|
71 |
super(ElementNotFoundInGetRequest, self).__init__(val, message)
|
72 |
|
73 |
|
|
|
77 |
"""
|
78 |
|
79 |
def __init__(self, val, min_chars, max_chars):
|
80 |
+
message = (
|
81 |
+
f"Text length need to be between {min_chars} and {max_chars} characters"
|
82 |
+
)
|
83 |
super(NotValidLength, self).__init__(val, message)
|
84 |
|
85 |
|
|
|
88 |
exception thrown if an error occurred during the request call, e.g a connection problem.
|
89 |
"""
|
90 |
|
91 |
+
def __init__(
|
92 |
+
self,
|
93 |
+
message="Request exception can happen due to an api connection error. "
|
94 |
+
"Please check your connection and try again",
|
95 |
+
):
|
96 |
self.message = message
|
97 |
|
98 |
def __str__(self):
|
|
|
106 |
|
107 |
def __init__(self, api_message):
|
108 |
self.api_message = str(api_message)
|
109 |
+
self.message = "Microsoft API returned the following error"
|
110 |
|
111 |
def __str__(self):
|
112 |
return "{}: {}".format(self.message, self.api_message)
|
|
|
117 |
exception thrown if an error occurred during the request call, e.g a connection problem.
|
118 |
"""
|
119 |
|
120 |
+
def __init__(
|
121 |
+
self,
|
122 |
+
message="Server Error: You made too many requests to the server. According to google, you are allowed to make 5 requests per second and up to 200k requests per day. You can wait and try again later or you can try the translate_batch function",
|
123 |
+
):
|
124 |
self.message = message
|
125 |
|
126 |
def __str__(self):
|
|
|
131 |
"""
|
132 |
Default YandexTranslate exception from the official website
|
133 |
"""
|
134 |
+
|
135 |
errors = {
|
136 |
400: "ERR_BAD_REQUEST",
|
137 |
401: "ERR_KEY_INVALID",
|
|
|
153 |
|
154 |
class AuthorizationException(Exception):
|
155 |
def __init__(self, api_key, *args):
|
156 |
+
msg = "Unauthorized access with the api key " + api_key
|
157 |
super().__init__(msg, *args)
|
deep_translator/google.py
CHANGED
@@ -3,7 +3,11 @@ google translator API
|
|
3 |
"""
|
4 |
|
5 |
from deep_translator.constants import BASE_URLS
|
6 |
-
from deep_translator.exceptions import
|
|
|
|
|
|
|
|
|
7 |
from deep_translator.base import BaseTranslator
|
8 |
from deep_translator.validate import validate_input, is_empty
|
9 |
from bs4 import BeautifulSoup
|
@@ -21,13 +25,15 @@ class GoogleTranslator(BaseTranslator):
|
|
21 |
@param target: target language to translate to
|
22 |
"""
|
23 |
self.proxies = proxies
|
24 |
-
super().__init__(
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
|
|
|
|
31 |
|
32 |
self._alt_element_query = {"class": "result-container"}
|
33 |
|
@@ -41,22 +47,22 @@ class GoogleTranslator(BaseTranslator):
|
|
41 |
text = text.strip()
|
42 |
if self._same_source_target() or is_empty(text):
|
43 |
return text
|
44 |
-
self._url_params[
|
45 |
-
self._url_params[
|
46 |
|
47 |
if self.payload_key:
|
48 |
self._url_params[self.payload_key] = text
|
49 |
|
50 |
-
response = requests.get(
|
51 |
-
|
52 |
-
|
53 |
if response.status_code == 429:
|
54 |
raise TooManyRequests()
|
55 |
|
56 |
if response.status_code != 200:
|
57 |
raise RequestError()
|
58 |
|
59 |
-
soup = BeautifulSoup(response.text,
|
60 |
|
61 |
element = soup.find(self._element_tag, self._element_query)
|
62 |
|
@@ -65,9 +71,15 @@ class GoogleTranslator(BaseTranslator):
|
|
65 |
if not element:
|
66 |
raise TranslationNotFound(text)
|
67 |
if element.get_text(strip=True) == text.strip():
|
68 |
-
to_translate_alpha =
|
69 |
-
translated_alpha =
|
70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
self._url_params["tl"] = self._target
|
72 |
if "hl" not in self._url_params:
|
73 |
return text.strip()
|
@@ -96,6 +108,6 @@ class GoogleTranslator(BaseTranslator):
|
|
96 |
return self._translate_batch(batch, **kwargs)
|
97 |
|
98 |
|
99 |
-
if __name__ ==
|
100 |
t = GoogleTranslator().translate("hallo welt")
|
101 |
print("translation: ", t)
|
|
|
3 |
"""
|
4 |
|
5 |
from deep_translator.constants import BASE_URLS
|
6 |
+
from deep_translator.exceptions import (
|
7 |
+
TooManyRequests,
|
8 |
+
TranslationNotFound,
|
9 |
+
RequestError,
|
10 |
+
)
|
11 |
from deep_translator.base import BaseTranslator
|
12 |
from deep_translator.validate import validate_input, is_empty
|
13 |
from bs4 import BeautifulSoup
|
|
|
25 |
@param target: target language to translate to
|
26 |
"""
|
27 |
self.proxies = proxies
|
28 |
+
super().__init__(
|
29 |
+
base_url=BASE_URLS.get("GOOGLE_TRANSLATE"),
|
30 |
+
source=source,
|
31 |
+
target=target,
|
32 |
+
element_tag="div",
|
33 |
+
element_query={"class": "t0"},
|
34 |
+
payload_key="q", # key of text in the url
|
35 |
+
**kwargs
|
36 |
+
)
|
37 |
|
38 |
self._alt_element_query = {"class": "result-container"}
|
39 |
|
|
|
47 |
text = text.strip()
|
48 |
if self._same_source_target() or is_empty(text):
|
49 |
return text
|
50 |
+
self._url_params["tl"] = self._target
|
51 |
+
self._url_params["sl"] = self._source
|
52 |
|
53 |
if self.payload_key:
|
54 |
self._url_params[self.payload_key] = text
|
55 |
|
56 |
+
response = requests.get(
|
57 |
+
self._base_url, params=self._url_params, proxies=self.proxies
|
58 |
+
)
|
59 |
if response.status_code == 429:
|
60 |
raise TooManyRequests()
|
61 |
|
62 |
if response.status_code != 200:
|
63 |
raise RequestError()
|
64 |
|
65 |
+
soup = BeautifulSoup(response.text, "html.parser")
|
66 |
|
67 |
element = soup.find(self._element_tag, self._element_query)
|
68 |
|
|
|
71 |
if not element:
|
72 |
raise TranslationNotFound(text)
|
73 |
if element.get_text(strip=True) == text.strip():
|
74 |
+
to_translate_alpha = "".join(ch for ch in text.strip() if ch.isalnum())
|
75 |
+
translated_alpha = "".join(
|
76 |
+
ch for ch in element.get_text(strip=True) if ch.isalnum()
|
77 |
+
)
|
78 |
+
if (
|
79 |
+
to_translate_alpha
|
80 |
+
and translated_alpha
|
81 |
+
and to_translate_alpha == translated_alpha
|
82 |
+
):
|
83 |
self._url_params["tl"] = self._target
|
84 |
if "hl" not in self._url_params:
|
85 |
return text.strip()
|
|
|
108 |
return self._translate_batch(batch, **kwargs)
|
109 |
|
110 |
|
111 |
+
if __name__ == "__main__":
|
112 |
t = GoogleTranslator().translate("hallo welt")
|
113 |
print("translation: ", t)
|
deep_translator/libre.py
CHANGED
@@ -4,12 +4,14 @@ LibreTranslate API
|
|
4 |
|
5 |
import requests
|
6 |
|
7 |
-
from .validate import is_empty, validate_input
|
8 |
-
from .base import BaseTranslator
|
9 |
-
from .constants import BASE_URLS,LIBRE_LANGUAGES_TO_CODES
|
10 |
-
from .exceptions import (
|
11 |
-
|
12 |
-
|
|
|
|
|
13 |
|
14 |
|
15 |
class LibreTranslator(BaseTranslator):
|
@@ -27,10 +29,12 @@ class LibreTranslator(BaseTranslator):
|
|
27 |
if not api_key:
|
28 |
raise ServerException(401)
|
29 |
self.api_key = api_key
|
30 |
-
super().__init__(
|
31 |
-
|
32 |
-
|
33 |
-
|
|
|
|
|
34 |
|
35 |
def translate(self, text, **kwargs):
|
36 |
"""
|
@@ -42,19 +46,21 @@ class LibreTranslator(BaseTranslator):
|
|
42 |
if self._same_source_target() or is_empty(text):
|
43 |
return text
|
44 |
|
45 |
-
translate_endpoint =
|
46 |
params = {
|
47 |
"q": text,
|
48 |
"source": self._source,
|
49 |
"target": self._target,
|
50 |
-
"format":
|
51 |
}
|
52 |
# Add API Key if required
|
53 |
if self.api_key:
|
54 |
params["api_key"] = self.api_key
|
55 |
# Do the request and check the connection.
|
56 |
try:
|
57 |
-
response = requests.post(
|
|
|
|
|
58 |
except ConnectionError:
|
59 |
raise ServerException(503)
|
60 |
# If the answer is not success, raise server exception.
|
@@ -68,7 +74,7 @@ class LibreTranslator(BaseTranslator):
|
|
68 |
if not res:
|
69 |
raise TranslationNotFound(text)
|
70 |
# Process and return the response.
|
71 |
-
return res[
|
72 |
|
73 |
def translate_file(self, path, **kwargs):
|
74 |
"""
|
|
|
4 |
|
5 |
import requests
|
6 |
|
7 |
+
from deep_translator.validate import is_empty, validate_input
|
8 |
+
from deep_translator.base import BaseTranslator
|
9 |
+
from deep_translator.constants import BASE_URLS, LIBRE_LANGUAGES_TO_CODES
|
10 |
+
from deep_translator.exceptions import (
|
11 |
+
ServerException,
|
12 |
+
TranslationNotFound,
|
13 |
+
AuthorizationException,
|
14 |
+
)
|
15 |
|
16 |
|
17 |
class LibreTranslator(BaseTranslator):
|
|
|
29 |
if not api_key:
|
30 |
raise ServerException(401)
|
31 |
self.api_key = api_key
|
32 |
+
super().__init__(
|
33 |
+
base_url=BASE_URLS.get("LIBRE"),
|
34 |
+
source=source,
|
35 |
+
target=target,
|
36 |
+
languages=LIBRE_LANGUAGES_TO_CODES,
|
37 |
+
)
|
38 |
|
39 |
def translate(self, text, **kwargs):
|
40 |
"""
|
|
|
46 |
if self._same_source_target() or is_empty(text):
|
47 |
return text
|
48 |
|
49 |
+
translate_endpoint = "translate"
|
50 |
params = {
|
51 |
"q": text,
|
52 |
"source": self._source,
|
53 |
"target": self._target,
|
54 |
+
"format": "text",
|
55 |
}
|
56 |
# Add API Key if required
|
57 |
if self.api_key:
|
58 |
params["api_key"] = self.api_key
|
59 |
# Do the request and check the connection.
|
60 |
try:
|
61 |
+
response = requests.post(
|
62 |
+
self._base_url + translate_endpoint, params=params
|
63 |
+
)
|
64 |
except ConnectionError:
|
65 |
raise ServerException(503)
|
66 |
# If the answer is not success, raise server exception.
|
|
|
74 |
if not res:
|
75 |
raise TranslationNotFound(text)
|
76 |
# Process and return the response.
|
77 |
+
return res["translatedText"]
|
78 |
|
79 |
def translate_file(self, path, **kwargs):
|
80 |
"""
|
deep_translator/linguee.py
CHANGED
@@ -1,15 +1,16 @@
|
|
1 |
"""
|
2 |
linguee translator API
|
3 |
"""
|
4 |
-
from .validate import validate_input, is_empty
|
5 |
-
from .constants import BASE_URLS, LINGUEE_LANGUAGES_TO_CODES
|
6 |
-
from .exceptions import (
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
13 |
from bs4 import BeautifulSoup
|
14 |
import requests
|
15 |
from requests.utils import requote_uri
|
@@ -26,14 +27,15 @@ class LingueeTranslator(BaseTranslator):
|
|
26 |
@param target: target language to translate to
|
27 |
"""
|
28 |
self.proxies = proxies
|
29 |
-
super().__init__(
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
|
|
37 |
|
38 |
def translate(self, word, return_all=False, **kwargs):
|
39 |
"""
|
@@ -49,7 +51,9 @@ class LingueeTranslator(BaseTranslator):
|
|
49 |
|
50 |
if validate_input(word, max_chars=50):
|
51 |
# %s-%s/translation/%s.html
|
52 |
-
url =
|
|
|
|
|
53 |
url = requote_uri(url)
|
54 |
response = requests.get(url, proxies=self.proxies)
|
55 |
|
@@ -58,7 +62,7 @@ class LingueeTranslator(BaseTranslator):
|
|
58 |
|
59 |
if response.status_code != 200:
|
60 |
raise RequestError()
|
61 |
-
soup = BeautifulSoup(response.text,
|
62 |
elements = soup.find_all(self._element_tag, self._element_query)
|
63 |
if not elements:
|
64 |
raise ElementNotFoundInGetRequest(elements)
|
@@ -66,10 +70,12 @@ class LingueeTranslator(BaseTranslator):
|
|
66 |
filtered_elements = []
|
67 |
for el in elements:
|
68 |
try:
|
69 |
-
pronoun = el.find(
|
|
|
|
|
70 |
except AttributeError:
|
71 |
-
pronoun =
|
72 |
-
filtered_elements.append(el.get_text(strip=True).replace(pronoun,
|
73 |
|
74 |
if not filtered_elements:
|
75 |
raise TranslationNotFound(word)
|
@@ -90,4 +96,3 @@ class LingueeTranslator(BaseTranslator):
|
|
90 |
for word in words:
|
91 |
translated_words.append(self.translate(word=word, **kwargs))
|
92 |
return translated_words
|
93 |
-
|
|
|
1 |
"""
|
2 |
linguee translator API
|
3 |
"""
|
4 |
+
from deep_translator.validate import validate_input, is_empty
|
5 |
+
from deep_translator.constants import BASE_URLS, LINGUEE_LANGUAGES_TO_CODES
|
6 |
+
from deep_translator.exceptions import (
|
7 |
+
TranslationNotFound,
|
8 |
+
NotValidPayload,
|
9 |
+
ElementNotFoundInGetRequest,
|
10 |
+
RequestError,
|
11 |
+
TooManyRequests,
|
12 |
+
)
|
13 |
+
from deep_translator.base import BaseTranslator
|
14 |
from bs4 import BeautifulSoup
|
15 |
import requests
|
16 |
from requests.utils import requote_uri
|
|
|
27 |
@param target: target language to translate to
|
28 |
"""
|
29 |
self.proxies = proxies
|
30 |
+
super().__init__(
|
31 |
+
base_url=BASE_URLS.get("LINGUEE"),
|
32 |
+
source=source,
|
33 |
+
target=target,
|
34 |
+
languages=LINGUEE_LANGUAGES_TO_CODES,
|
35 |
+
element_tag="a",
|
36 |
+
element_query={"class": "dictLink featured"},
|
37 |
+
payload_key=None, # key of text in the url
|
38 |
+
)
|
39 |
|
40 |
def translate(self, word, return_all=False, **kwargs):
|
41 |
"""
|
|
|
51 |
|
52 |
if validate_input(word, max_chars=50):
|
53 |
# %s-%s/translation/%s.html
|
54 |
+
url = (
|
55 |
+
f"{self._base_url}{self._source}-{self._target}/translation/{word}.html"
|
56 |
+
)
|
57 |
url = requote_uri(url)
|
58 |
response = requests.get(url, proxies=self.proxies)
|
59 |
|
|
|
62 |
|
63 |
if response.status_code != 200:
|
64 |
raise RequestError()
|
65 |
+
soup = BeautifulSoup(response.text, "html.parser")
|
66 |
elements = soup.find_all(self._element_tag, self._element_query)
|
67 |
if not elements:
|
68 |
raise ElementNotFoundInGetRequest(elements)
|
|
|
70 |
filtered_elements = []
|
71 |
for el in elements:
|
72 |
try:
|
73 |
+
pronoun = el.find("span", {"class": "placeholder"}).get_text(
|
74 |
+
strip=True
|
75 |
+
)
|
76 |
except AttributeError:
|
77 |
+
pronoun = ""
|
78 |
+
filtered_elements.append(el.get_text(strip=True).replace(pronoun, ""))
|
79 |
|
80 |
if not filtered_elements:
|
81 |
raise TranslationNotFound(word)
|
|
|
96 |
for word in words:
|
97 |
translated_words.append(self.translate(word=word, **kwargs))
|
98 |
return translated_words
|
|
deep_translator/microsoft.py
CHANGED
@@ -3,10 +3,10 @@
|
|
3 |
import requests
|
4 |
import logging
|
5 |
import sys
|
6 |
-
from .constants import BASE_URLS
|
7 |
-
from .exceptions import ServerException, MicrosoftAPIerror
|
8 |
-
from .base import BaseTranslator
|
9 |
-
from .validate import validate_input
|
10 |
|
11 |
|
12 |
class MicrosoftTranslator(BaseTranslator):
|
@@ -14,7 +14,15 @@ class MicrosoftTranslator(BaseTranslator):
|
|
14 |
the class that wraps functions, which use the Microsoft translator under the hood to translate word(s)
|
15 |
"""
|
16 |
|
17 |
-
def __init__(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
"""
|
19 |
@params api_key and target are the required params
|
20 |
@param api_key: your Microsoft API key
|
@@ -41,17 +49,16 @@ class MicrosoftTranslator(BaseTranslator):
|
|
41 |
source=source,
|
42 |
target=target,
|
43 |
languages=MICROSOFT_CODES_TO_LANGUAGES,
|
44 |
-
**kwargs
|
45 |
)
|
46 |
|
47 |
def _get_supported_languages(self):
|
48 |
|
49 |
-
microsoft_languages_api_url =
|
50 |
-
"https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&scope=translation"
|
51 |
microsoft_languages_response = requests.get(microsoft_languages_api_url)
|
52 |
-
translation_dict = microsoft_languages_response.json()[
|
53 |
|
54 |
-
return {translation_dict[k][
|
55 |
|
56 |
def translate(self, text, **kwargs):
|
57 |
"""
|
@@ -63,28 +70,31 @@ class MicrosoftTranslator(BaseTranslator):
|
|
63 |
# I have not added multiple text processing here since it is covered by the translate_batch method
|
64 |
|
65 |
if validate_input(text):
|
66 |
-
self._url_params[
|
67 |
-
self._url_params[
|
68 |
|
69 |
-
valid_microsoft_json = [{
|
70 |
try:
|
71 |
-
requested = requests.post(
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
|
|
|
|
76 |
except requests.exceptions.RequestException:
|
77 |
exc_type, value, traceback = sys.exc_info()
|
78 |
logging.warning(f"Returned error: {exc_type.__name__}")
|
79 |
|
80 |
# Where Microsoft API responds with an api error, it returns a dict in response.json()
|
81 |
if type(requested.json()) is dict:
|
82 |
-
error_message = requested.json()[
|
83 |
raise MicrosoftAPIerror(error_message)
|
84 |
# Where it responds with a translation, its response.json() is a list e.g. [{'translations': [{'text': 'Hello world!', 'to': 'en'}]}]
|
85 |
elif type(requested.json()) is list:
|
86 |
-
all_translations = [
|
87 |
-
|
|
|
88 |
return "\n".join(all_translations)
|
89 |
|
90 |
def translate_file(self, path, **kwargs):
|
|
|
3 |
import requests
|
4 |
import logging
|
5 |
import sys
|
6 |
+
from deep_translator.constants import BASE_URLS
|
7 |
+
from deep_translator.exceptions import ServerException, MicrosoftAPIerror
|
8 |
+
from deep_translator.base import BaseTranslator
|
9 |
+
from deep_translator.validate import validate_input
|
10 |
|
11 |
|
12 |
class MicrosoftTranslator(BaseTranslator):
|
|
|
14 |
the class that wraps functions, which use the Microsoft translator under the hood to translate word(s)
|
15 |
"""
|
16 |
|
17 |
+
def __init__(
|
18 |
+
self,
|
19 |
+
api_key=None,
|
20 |
+
region=None,
|
21 |
+
source=None,
|
22 |
+
target=None,
|
23 |
+
proxies=None,
|
24 |
+
**kwargs,
|
25 |
+
):
|
26 |
"""
|
27 |
@params api_key and target are the required params
|
28 |
@param api_key: your Microsoft API key
|
|
|
49 |
source=source,
|
50 |
target=target,
|
51 |
languages=MICROSOFT_CODES_TO_LANGUAGES,
|
52 |
+
**kwargs,
|
53 |
)
|
54 |
|
55 |
def _get_supported_languages(self):
|
56 |
|
57 |
+
microsoft_languages_api_url = "https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&scope=translation"
|
|
|
58 |
microsoft_languages_response = requests.get(microsoft_languages_api_url)
|
59 |
+
translation_dict = microsoft_languages_response.json()["translation"]
|
60 |
|
61 |
+
return {translation_dict[k]["name"].lower(): k for k in translation_dict.keys()}
|
62 |
|
63 |
def translate(self, text, **kwargs):
|
64 |
"""
|
|
|
70 |
# I have not added multiple text processing here since it is covered by the translate_batch method
|
71 |
|
72 |
if validate_input(text):
|
73 |
+
self._url_params["from"] = self._source
|
74 |
+
self._url_params["to"] = self._target
|
75 |
|
76 |
+
valid_microsoft_json = [{"text": text}]
|
77 |
try:
|
78 |
+
requested = requests.post(
|
79 |
+
self._base_url,
|
80 |
+
params=self._url_params,
|
81 |
+
headers=self.headers,
|
82 |
+
json=valid_microsoft_json,
|
83 |
+
proxies=self.proxies,
|
84 |
+
)
|
85 |
except requests.exceptions.RequestException:
|
86 |
exc_type, value, traceback = sys.exc_info()
|
87 |
logging.warning(f"Returned error: {exc_type.__name__}")
|
88 |
|
89 |
# Where Microsoft API responds with an api error, it returns a dict in response.json()
|
90 |
if type(requested.json()) is dict:
|
91 |
+
error_message = requested.json()["error"]
|
92 |
raise MicrosoftAPIerror(error_message)
|
93 |
# Where it responds with a translation, its response.json() is a list e.g. [{'translations': [{'text': 'Hello world!', 'to': 'en'}]}]
|
94 |
elif type(requested.json()) is list:
|
95 |
+
all_translations = [
|
96 |
+
i["text"] for i in requested.json()[0]["translations"]
|
97 |
+
]
|
98 |
return "\n".join(all_translations)
|
99 |
|
100 |
def translate_file(self, path, **kwargs):
|
deep_translator/mymemory.py
CHANGED
@@ -1,13 +1,14 @@
|
|
1 |
"""
|
2 |
mymemory translator API
|
3 |
"""
|
4 |
-
from .validate import is_empty, validate_input
|
5 |
-
from .constants import BASE_URLS
|
6 |
-
from .exceptions import (
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
|
|
11 |
import requests
|
12 |
|
13 |
|
@@ -15,18 +16,20 @@ class MyMemoryTranslator(BaseTranslator):
|
|
15 |
"""
|
16 |
class that uses the mymemory translator to translate texts
|
17 |
"""
|
|
|
18 |
def __init__(self, source="auto", target="en", proxies=None, **kwargs):
|
19 |
"""
|
20 |
@param source: source language to translate from
|
21 |
@param target: target language to translate to
|
22 |
"""
|
23 |
self.proxies = proxies
|
24 |
-
self.email = kwargs.get(
|
25 |
-
super().__init__(
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
|
|
30 |
|
31 |
def translate(self, text, return_all=False, **kwargs):
|
32 |
"""
|
@@ -41,15 +44,15 @@ class MyMemoryTranslator(BaseTranslator):
|
|
41 |
if self._same_source_target() or is_empty(text):
|
42 |
return text
|
43 |
|
44 |
-
self._url_params[
|
45 |
if self.payload_key:
|
46 |
self._url_params[self.payload_key] = text
|
47 |
if self.email:
|
48 |
-
self._url_params[
|
49 |
|
50 |
-
response = requests.get(
|
51 |
-
|
52 |
-
|
53 |
|
54 |
if response.status_code == 429:
|
55 |
raise TooManyRequests()
|
@@ -60,24 +63,24 @@ class MyMemoryTranslator(BaseTranslator):
|
|
60 |
if not data:
|
61 |
TranslationNotFound(text)
|
62 |
|
63 |
-
translation = data.get(
|
64 |
if translation:
|
65 |
return translation
|
66 |
|
67 |
elif not translation:
|
68 |
-
all_matches = data.get(
|
69 |
-
matches = (match[
|
70 |
next_match = next(matches)
|
71 |
return next_match if not return_all else list(all_matches)
|
72 |
|
73 |
def translate_file(self, path, **kwargs):
|
74 |
"""
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
return self._translate_file(path, **kwargs)
|
82 |
|
83 |
def translate_batch(self, batch=None, **kwargs):
|
|
|
1 |
"""
|
2 |
mymemory translator API
|
3 |
"""
|
4 |
+
from deep_translator.validate import is_empty, validate_input
|
5 |
+
from deep_translator.constants import BASE_URLS
|
6 |
+
from deep_translator.exceptions import (
|
7 |
+
TranslationNotFound,
|
8 |
+
RequestError,
|
9 |
+
TooManyRequests,
|
10 |
+
)
|
11 |
+
from deep_translator.base import BaseTranslator
|
12 |
import requests
|
13 |
|
14 |
|
|
|
16 |
"""
|
17 |
class that uses the mymemory translator to translate texts
|
18 |
"""
|
19 |
+
|
20 |
def __init__(self, source="auto", target="en", proxies=None, **kwargs):
|
21 |
"""
|
22 |
@param source: source language to translate from
|
23 |
@param target: target language to translate to
|
24 |
"""
|
25 |
self.proxies = proxies
|
26 |
+
self.email = kwargs.get("email", None)
|
27 |
+
super().__init__(
|
28 |
+
base_url=BASE_URLS.get("MYMEMORY"),
|
29 |
+
source=source,
|
30 |
+
target=target,
|
31 |
+
payload_key="q",
|
32 |
+
)
|
33 |
|
34 |
def translate(self, text, return_all=False, **kwargs):
|
35 |
"""
|
|
|
44 |
if self._same_source_target() or is_empty(text):
|
45 |
return text
|
46 |
|
47 |
+
self._url_params["langpair"] = f"{self._source}|{self._target}"
|
48 |
if self.payload_key:
|
49 |
self._url_params[self.payload_key] = text
|
50 |
if self.email:
|
51 |
+
self._url_params["de"] = self.email
|
52 |
|
53 |
+
response = requests.get(
|
54 |
+
self._base_url, params=self._url_params, proxies=self.proxies
|
55 |
+
)
|
56 |
|
57 |
if response.status_code == 429:
|
58 |
raise TooManyRequests()
|
|
|
63 |
if not data:
|
64 |
TranslationNotFound(text)
|
65 |
|
66 |
+
translation = data.get("responseData").get("translatedText")
|
67 |
if translation:
|
68 |
return translation
|
69 |
|
70 |
elif not translation:
|
71 |
+
all_matches = data.get("matches")
|
72 |
+
matches = (match["translation"] for match in all_matches)
|
73 |
next_match = next(matches)
|
74 |
return next_match if not return_all else list(all_matches)
|
75 |
|
76 |
def translate_file(self, path, **kwargs):
|
77 |
"""
|
78 |
+
translate directly from file
|
79 |
+
@param path: path to the target file
|
80 |
+
@type path: str
|
81 |
+
@param kwargs: additional args
|
82 |
+
@return: str
|
83 |
+
"""
|
84 |
return self._translate_file(path, **kwargs)
|
85 |
|
86 |
def translate_batch(self, batch=None, **kwargs):
|
deep_translator/papago.py
CHANGED
@@ -2,12 +2,12 @@
|
|
2 |
google translator API
|
3 |
"""
|
4 |
import json
|
5 |
-
from .constants import BASE_URLS, PAPAGO_LANGUAGE_TO_CODE
|
6 |
-
from .exceptions import TranslationNotFound
|
7 |
-
from .base import BaseTranslator
|
8 |
import requests
|
9 |
|
10 |
-
from .validate import validate_input
|
11 |
|
12 |
|
13 |
class PapagoTranslator(BaseTranslator):
|
@@ -15,14 +15,17 @@ class PapagoTranslator(BaseTranslator):
|
|
15 |
class that wraps functions, which use google translate under the hood to translate text(s)
|
16 |
"""
|
17 |
|
18 |
-
def __init__(
|
|
|
|
|
19 |
"""
|
20 |
@param source: source language to translate from
|
21 |
@param target: target language to translate to
|
22 |
"""
|
23 |
if not client_id or not secret_key:
|
24 |
raise Exception(
|
25 |
-
"Please pass your client id and secret key! visit the papago website for more infos"
|
|
|
26 |
|
27 |
self.client_id = client_id
|
28 |
self.secret_key = secret_key
|
@@ -31,7 +34,7 @@ class PapagoTranslator(BaseTranslator):
|
|
31 |
source=source,
|
32 |
target=target,
|
33 |
languages=PAPAGO_LANGUAGE_TO_CODE,
|
34 |
-
**kwargs
|
35 |
)
|
36 |
|
37 |
def translate(self, text, **kwargs):
|
@@ -41,21 +44,17 @@ class PapagoTranslator(BaseTranslator):
|
|
41 |
@return: str: translated text
|
42 |
"""
|
43 |
if validate_input(text):
|
44 |
-
payload = {
|
45 |
-
"source": self._source,
|
46 |
-
"target": self._target,
|
47 |
-
"text": text
|
48 |
-
}
|
49 |
headers = {
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
}
|
54 |
-
response = requests.post(
|
55 |
-
self._base_url, headers=headers, data=payload)
|
56 |
if response.status_code != 200:
|
57 |
raise Exception(
|
58 |
-
f
|
|
|
59 |
res_body = json.loads(response.text)
|
60 |
if "message" not in res_body:
|
61 |
raise TranslationNotFound(text)
|
|
|
2 |
google translator API
|
3 |
"""
|
4 |
import json
|
5 |
+
from deep_translator.constants import BASE_URLS, PAPAGO_LANGUAGE_TO_CODE
|
6 |
+
from deep_translator.exceptions import TranslationNotFound
|
7 |
+
from deep_translator.base import BaseTranslator
|
8 |
import requests
|
9 |
|
10 |
+
from deep_translator.validate import validate_input
|
11 |
|
12 |
|
13 |
class PapagoTranslator(BaseTranslator):
|
|
|
15 |
class that wraps functions, which use google translate under the hood to translate text(s)
|
16 |
"""
|
17 |
|
18 |
+
def __init__(
|
19 |
+
self, client_id=None, secret_key=None, source="auto", target="en", **kwargs
|
20 |
+
):
|
21 |
"""
|
22 |
@param source: source language to translate from
|
23 |
@param target: target language to translate to
|
24 |
"""
|
25 |
if not client_id or not secret_key:
|
26 |
raise Exception(
|
27 |
+
"Please pass your client id and secret key! visit the papago website for more infos"
|
28 |
+
)
|
29 |
|
30 |
self.client_id = client_id
|
31 |
self.secret_key = secret_key
|
|
|
34 |
source=source,
|
35 |
target=target,
|
36 |
languages=PAPAGO_LANGUAGE_TO_CODE,
|
37 |
+
**kwargs,
|
38 |
)
|
39 |
|
40 |
def translate(self, text, **kwargs):
|
|
|
44 |
@return: str: translated text
|
45 |
"""
|
46 |
if validate_input(text):
|
47 |
+
payload = {"source": self._source, "target": self._target, "text": text}
|
|
|
|
|
|
|
|
|
48 |
headers = {
|
49 |
+
"X-Naver-Client-Id": self.client_id,
|
50 |
+
"X-Naver-Client-Secret": self.secret_key,
|
51 |
+
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
52 |
}
|
53 |
+
response = requests.post(self._base_url, headers=headers, data=payload)
|
|
|
54 |
if response.status_code != 200:
|
55 |
raise Exception(
|
56 |
+
f"Translation error! -> status code: {response.status_code}"
|
57 |
+
)
|
58 |
res_body = json.loads(response.text)
|
59 |
if "message" not in res_body:
|
60 |
raise TranslationNotFound(text)
|
deep_translator/pons.py
CHANGED
@@ -4,15 +4,16 @@ pons translator API
|
|
4 |
from bs4 import BeautifulSoup
|
5 |
import requests
|
6 |
|
7 |
-
from .validate import validate_input, is_empty
|
8 |
-
from .constants import BASE_URLS, PONS_CODES_TO_LANGUAGES
|
9 |
-
from .exceptions import (
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
|
|
16 |
from requests.utils import requote_uri
|
17 |
|
18 |
|
@@ -27,15 +28,16 @@ class PonsTranslator(BaseTranslator):
|
|
27 |
@param target: target language to translate to
|
28 |
"""
|
29 |
self.proxies = proxies
|
30 |
-
super().__init__(
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
|
|
39 |
|
40 |
def translate(self, word, return_all=False, **kwargs):
|
41 |
"""
|
@@ -49,7 +51,7 @@ class PonsTranslator(BaseTranslator):
|
|
49 |
if validate_input(word, max_chars=50):
|
50 |
if self._same_source_target() or is_empty(word):
|
51 |
return word
|
52 |
-
url = "{}{}-{}/{}"
|
53 |
url = requote_uri(url)
|
54 |
response = requests.get(url, proxies=self.proxies)
|
55 |
|
@@ -59,7 +61,7 @@ class PonsTranslator(BaseTranslator):
|
|
59 |
if response.status_code != 200:
|
60 |
raise RequestError()
|
61 |
|
62 |
-
soup = BeautifulSoup(response.text,
|
63 |
elements = soup.findAll(self._element_tag, self._element_query)
|
64 |
|
65 |
if not elements:
|
@@ -67,9 +69,9 @@ class PonsTranslator(BaseTranslator):
|
|
67 |
|
68 |
filtered_elements = []
|
69 |
for el in elements:
|
70 |
-
temp =
|
71 |
-
for e in el.findAll(
|
72 |
-
temp += e.get_text() +
|
73 |
filtered_elements.append(temp)
|
74 |
|
75 |
if not filtered_elements:
|
@@ -96,4 +98,3 @@ class PonsTranslator(BaseTranslator):
|
|
96 |
for word in words:
|
97 |
translated_words.append(self.translate(word=word, **kwargs))
|
98 |
return translated_words
|
99 |
-
|
|
|
4 |
from bs4 import BeautifulSoup
|
5 |
import requests
|
6 |
|
7 |
+
from deep_translator.validate import validate_input, is_empty
|
8 |
+
from deep_translator.constants import BASE_URLS, PONS_CODES_TO_LANGUAGES
|
9 |
+
from deep_translator.exceptions import (
|
10 |
+
TranslationNotFound,
|
11 |
+
NotValidPayload,
|
12 |
+
ElementNotFoundInGetRequest,
|
13 |
+
RequestError,
|
14 |
+
TooManyRequests,
|
15 |
+
)
|
16 |
+
from deep_translator.base import BaseTranslator
|
17 |
from requests.utils import requote_uri
|
18 |
|
19 |
|
|
|
28 |
@param target: target language to translate to
|
29 |
"""
|
30 |
self.proxies = proxies
|
31 |
+
super().__init__(
|
32 |
+
base_url=BASE_URLS.get("PONS"),
|
33 |
+
languages=PONS_CODES_TO_LANGUAGES,
|
34 |
+
source=source,
|
35 |
+
target=target,
|
36 |
+
payload_key=None,
|
37 |
+
element_tag="div",
|
38 |
+
element_query={"class": "target"},
|
39 |
+
**kwargs,
|
40 |
+
)
|
41 |
|
42 |
def translate(self, word, return_all=False, **kwargs):
|
43 |
"""
|
|
|
51 |
if validate_input(word, max_chars=50):
|
52 |
if self._same_source_target() or is_empty(word):
|
53 |
return word
|
54 |
+
url = f"{self._base_url}{self._source}-{self._target}/{word}"
|
55 |
url = requote_uri(url)
|
56 |
response = requests.get(url, proxies=self.proxies)
|
57 |
|
|
|
61 |
if response.status_code != 200:
|
62 |
raise RequestError()
|
63 |
|
64 |
+
soup = BeautifulSoup(response.text, "html.parser")
|
65 |
elements = soup.findAll(self._element_tag, self._element_query)
|
66 |
|
67 |
if not elements:
|
|
|
69 |
|
70 |
filtered_elements = []
|
71 |
for el in elements:
|
72 |
+
temp = ""
|
73 |
+
for e in el.findAll("a"):
|
74 |
+
temp += e.get_text() + " "
|
75 |
filtered_elements.append(temp)
|
76 |
|
77 |
if not filtered_elements:
|
|
|
98 |
for word in words:
|
99 |
translated_words.append(self.translate(word=word, **kwargs))
|
100 |
return translated_words
|
|
deep_translator/qcri.py
CHANGED
@@ -1,8 +1,7 @@
|
|
1 |
-
|
2 |
import requests
|
3 |
-
from .constants import BASE_URLS, QCRI_LANGUAGE_TO_CODE
|
4 |
-
from .exceptions import
|
5 |
-
from .base import BaseTranslator
|
6 |
|
7 |
|
8 |
class QcriTranslator(BaseTranslator):
|
@@ -24,23 +23,23 @@ class QcriTranslator(BaseTranslator):
|
|
24 |
"translate": "translate",
|
25 |
}
|
26 |
|
27 |
-
self.params = {
|
28 |
-
"key": self.api_key
|
29 |
-
}
|
30 |
super().__init__(
|
31 |
base_url=BASE_URLS.get("QcriTranslator"),
|
32 |
source=source,
|
33 |
target=target,
|
34 |
languages=QCRI_LANGUAGE_TO_CODE,
|
35 |
-
**kwargs
|
36 |
)
|
37 |
|
38 |
def _get(self, endpoint, params=None, return_text=True):
|
39 |
if not params:
|
40 |
params = self.params
|
41 |
try:
|
42 |
-
res = requests.get(
|
43 |
-
endpoint=self.api_endpoints[endpoint]),
|
|
|
|
|
44 |
return res.text if return_text else res
|
45 |
except Exception as e:
|
46 |
raise e
|
@@ -60,9 +59,9 @@ class QcriTranslator(BaseTranslator):
|
|
60 |
def translate(self, text, **kwargs):
|
61 |
params = {
|
62 |
"key": self.api_key,
|
63 |
-
"langpair": "{}-{
|
64 |
"domain": kwargs["domain"],
|
65 |
-
"text": text
|
66 |
}
|
67 |
try:
|
68 |
response = self._get("translate", params=params, return_text=False)
|
|
|
|
|
1 |
import requests
|
2 |
+
from deep_translator.constants import BASE_URLS, QCRI_LANGUAGE_TO_CODE
|
3 |
+
from deep_translator.exceptions import ServerException, TranslationNotFound
|
4 |
+
from deep_translator.base import BaseTranslator
|
5 |
|
6 |
|
7 |
class QcriTranslator(BaseTranslator):
|
|
|
23 |
"translate": "translate",
|
24 |
}
|
25 |
|
26 |
+
self.params = {"key": self.api_key}
|
|
|
|
|
27 |
super().__init__(
|
28 |
base_url=BASE_URLS.get("QcriTranslator"),
|
29 |
source=source,
|
30 |
target=target,
|
31 |
languages=QCRI_LANGUAGE_TO_CODE,
|
32 |
+
**kwargs,
|
33 |
)
|
34 |
|
35 |
def _get(self, endpoint, params=None, return_text=True):
|
36 |
if not params:
|
37 |
params = self.params
|
38 |
try:
|
39 |
+
res = requests.get(
|
40 |
+
self._base_url.format(endpoint=self.api_endpoints[endpoint]),
|
41 |
+
params=params,
|
42 |
+
)
|
43 |
return res.text if return_text else res
|
44 |
except Exception as e:
|
45 |
raise e
|
|
|
59 |
def translate(self, text, **kwargs):
|
60 |
params = {
|
61 |
"key": self.api_key,
|
62 |
+
"langpair": f"{self._source}-{self._target}",
|
63 |
"domain": kwargs["domain"],
|
64 |
+
"text": text,
|
65 |
}
|
66 |
try:
|
67 |
response = self._get("translate", params=params, return_text=False)
|
deep_translator/validate.py
CHANGED
@@ -1,6 +1,4 @@
|
|
1 |
-
|
2 |
-
from .exceptions import NotValidPayload, NotValidLength
|
3 |
-
import string
|
4 |
|
5 |
|
6 |
def is_empty(text: str):
|
|
|
1 |
+
from deep_translator.exceptions import NotValidPayload, NotValidLength
|
|
|
|
|
2 |
|
3 |
|
4 |
def is_empty(text: str):
|
deep_translator/yandex.py
CHANGED
@@ -2,10 +2,15 @@
|
|
2 |
Yandex translator API
|
3 |
"""
|
4 |
import requests
|
5 |
-
from .constants import BASE_URLS
|
6 |
-
from .exceptions import (
|
7 |
-
|
8 |
-
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
|
11 |
class YandexTranslator(BaseTranslator):
|
@@ -27,10 +32,7 @@ class YandexTranslator(BaseTranslator):
|
|
27 |
"translate": "translate",
|
28 |
}
|
29 |
super().__init__(
|
30 |
-
base_url=BASE_URLS.get("YANDEX"),
|
31 |
-
source=source,
|
32 |
-
target=target,
|
33 |
-
**kwargs
|
34 |
)
|
35 |
|
36 |
def _get_supported_languages(self):
|
@@ -44,11 +46,9 @@ class YandexTranslator(BaseTranslator):
|
|
44 |
def dirs(self, proxies=None):
|
45 |
|
46 |
try:
|
47 |
-
url = self._base_url.format(
|
48 |
-
version=self.api_version, endpoint="getLangs")
|
49 |
print("url: ", url)
|
50 |
-
response = requests.get(
|
51 |
-
url, params={"key": self.api_key}, proxies=proxies)
|
52 |
except requests.exceptions.ConnectionError:
|
53 |
raise ServerException(503)
|
54 |
else:
|
@@ -66,8 +66,7 @@ class YandexTranslator(BaseTranslator):
|
|
66 |
"key": self.api_key,
|
67 |
}
|
68 |
try:
|
69 |
-
url = self._base_url.format(
|
70 |
-
version=self.api_version, endpoint="detect")
|
71 |
response = requests.post(url, data=params, proxies=proxies)
|
72 |
|
73 |
except RequestError:
|
@@ -78,8 +77,8 @@ class YandexTranslator(BaseTranslator):
|
|
78 |
raise ServerException(response.status_code)
|
79 |
else:
|
80 |
response = response.json()
|
81 |
-
language = response[
|
82 |
-
status_code = response[
|
83 |
if status_code != 200:
|
84 |
raise RequestError()
|
85 |
elif not language:
|
@@ -91,28 +90,31 @@ class YandexTranslator(BaseTranslator):
|
|
91 |
params = {
|
92 |
"text": text,
|
93 |
"format": "plain",
|
94 |
-
"lang": self._target
|
95 |
-
|
|
|
|
|
96 |
}
|
97 |
try:
|
98 |
url = self._base_url.format(
|
99 |
-
version=self.api_version, endpoint="translate"
|
|
|
100 |
response = requests.post(url, data=params, proxies=proxies)
|
101 |
except ConnectionError:
|
102 |
raise ServerException(503)
|
103 |
else:
|
104 |
response = response.json()
|
105 |
|
106 |
-
if response[
|
107 |
raise TooManyRequests()
|
108 |
|
109 |
-
if response[
|
110 |
-
raise ServerException(response[
|
111 |
|
112 |
-
if not response[
|
113 |
raise TranslationNotFound()
|
114 |
|
115 |
-
return response[
|
116 |
|
117 |
def translate_file(self, path, **kwargs):
|
118 |
"""
|
@@ -129,4 +131,3 @@ class YandexTranslator(BaseTranslator):
|
|
129 |
@return: list of translations
|
130 |
"""
|
131 |
return self._translate_batch(batch, **kwargs)
|
132 |
-
|
|
|
2 |
Yandex translator API
|
3 |
"""
|
4 |
import requests
|
5 |
+
from deep_translator.constants import BASE_URLS
|
6 |
+
from deep_translator.exceptions import (
|
7 |
+
RequestError,
|
8 |
+
ServerException,
|
9 |
+
TranslationNotFound,
|
10 |
+
TooManyRequests,
|
11 |
+
)
|
12 |
+
from deep_translator.base import BaseTranslator
|
13 |
+
from deep_translator.validate import validate_input
|
14 |
|
15 |
|
16 |
class YandexTranslator(BaseTranslator):
|
|
|
32 |
"translate": "translate",
|
33 |
}
|
34 |
super().__init__(
|
35 |
+
base_url=BASE_URLS.get("YANDEX"), source=source, target=target, **kwargs
|
|
|
|
|
|
|
36 |
)
|
37 |
|
38 |
def _get_supported_languages(self):
|
|
|
46 |
def dirs(self, proxies=None):
|
47 |
|
48 |
try:
|
49 |
+
url = self._base_url.format(version=self.api_version, endpoint="getLangs")
|
|
|
50 |
print("url: ", url)
|
51 |
+
response = requests.get(url, params={"key": self.api_key}, proxies=proxies)
|
|
|
52 |
except requests.exceptions.ConnectionError:
|
53 |
raise ServerException(503)
|
54 |
else:
|
|
|
66 |
"key": self.api_key,
|
67 |
}
|
68 |
try:
|
69 |
+
url = self._base_url.format(version=self.api_version, endpoint="detect")
|
|
|
70 |
response = requests.post(url, data=params, proxies=proxies)
|
71 |
|
72 |
except RequestError:
|
|
|
77 |
raise ServerException(response.status_code)
|
78 |
else:
|
79 |
response = response.json()
|
80 |
+
language = response["lang"]
|
81 |
+
status_code = response["code"]
|
82 |
if status_code != 200:
|
83 |
raise RequestError()
|
84 |
elif not language:
|
|
|
90 |
params = {
|
91 |
"text": text,
|
92 |
"format": "plain",
|
93 |
+
"lang": self._target
|
94 |
+
if self._source == "auto"
|
95 |
+
else "{}-{}".format(self._source, self._target),
|
96 |
+
"key": self.api_key,
|
97 |
}
|
98 |
try:
|
99 |
url = self._base_url.format(
|
100 |
+
version=self.api_version, endpoint="translate"
|
101 |
+
)
|
102 |
response = requests.post(url, data=params, proxies=proxies)
|
103 |
except ConnectionError:
|
104 |
raise ServerException(503)
|
105 |
else:
|
106 |
response = response.json()
|
107 |
|
108 |
+
if response["code"] == 429:
|
109 |
raise TooManyRequests()
|
110 |
|
111 |
+
if response["code"] != 200:
|
112 |
+
raise ServerException(response["code"])
|
113 |
|
114 |
+
if not response["text"]:
|
115 |
raise TranslationNotFound()
|
116 |
|
117 |
+
return response["text"]
|
118 |
|
119 |
def translate_file(self, path, **kwargs):
|
120 |
"""
|
|
|
131 |
@return: list of translations
|
132 |
"""
|
133 |
return self._translate_batch(batch, **kwargs)
|
|
poetry.lock
CHANGED
@@ -54,6 +54,29 @@ soupsieve = ">1.2"
|
|
54 |
html5lib = ["html5lib"]
|
55 |
lxml = ["lxml"]
|
56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
[[package]]
|
58 |
name = "bleach"
|
59 |
version = "4.1.0"
|
@@ -97,6 +120,18 @@ python-versions = ">=3.5.0"
|
|
97 |
[package.extras]
|
98 |
unicode_backport = ["unicodedata2"]
|
99 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
[[package]]
|
101 |
name = "colorama"
|
102 |
version = "0.4.4"
|
@@ -236,6 +271,14 @@ category = "dev"
|
|
236 |
optional = false
|
237 |
python-versions = ">=3.6"
|
238 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
239 |
[[package]]
|
240 |
name = "packaging"
|
241 |
version = "21.3"
|
@@ -247,6 +290,14 @@ python-versions = ">=3.6"
|
|
247 |
[package.dependencies]
|
248 |
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
|
249 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
250 |
[[package]]
|
251 |
name = "pkginfo"
|
252 |
version = "1.8.2"
|
@@ -258,6 +309,18 @@ python-versions = "*"
|
|
258 |
[package.extras]
|
259 |
testing = ["coverage", "nose"]
|
260 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
261 |
[[package]]
|
262 |
name = "pluggy"
|
263 |
version = "1.0.0"
|
@@ -561,6 +624,14 @@ category = "dev"
|
|
561 |
optional = false
|
562 |
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
563 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
564 |
[[package]]
|
565 |
name = "tqdm"
|
566 |
version = "4.62.3"
|
@@ -597,6 +668,14 @@ rfc3986 = ">=1.4.0"
|
|
597 |
tqdm = ">=4.14"
|
598 |
urllib3 = ">=1.26.0"
|
599 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
600 |
[[package]]
|
601 |
name = "typing-extensions"
|
602 |
version = "4.0.1"
|
@@ -641,7 +720,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-
|
|
641 |
[metadata]
|
642 |
lock-version = "1.1"
|
643 |
python-versions = "^3.7"
|
644 |
-
content-hash = "
|
645 |
|
646 |
[metadata.files]
|
647 |
alabaster = [
|
@@ -664,6 +743,31 @@ beautifulsoup4 = [
|
|
664 |
{file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"},
|
665 |
{file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"},
|
666 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
667 |
bleach = [
|
668 |
{file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"},
|
669 |
{file = "bleach-4.1.0.tar.gz", hash = "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da"},
|
@@ -728,6 +832,10 @@ charset-normalizer = [
|
|
728 |
{file = "charset-normalizer-2.0.11.tar.gz", hash = "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c"},
|
729 |
{file = "charset_normalizer-2.0.11-py3-none-any.whl", hash = "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45"},
|
730 |
]
|
|
|
|
|
|
|
|
|
731 |
colorama = [
|
732 |
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
733 |
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
@@ -876,14 +984,26 @@ markupsafe = [
|
|
876 |
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
|
877 |
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
|
878 |
]
|
|
|
|
|
|
|
|
|
879 |
packaging = [
|
880 |
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
881 |
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
882 |
]
|
|
|
|
|
|
|
|
|
883 |
pkginfo = [
|
884 |
{file = "pkginfo-1.8.2-py2.py3-none-any.whl", hash = "sha256:c24c487c6a7f72c66e816ab1796b96ac6c3d14d49338293d2141664330b55ffc"},
|
885 |
{file = "pkginfo-1.8.2.tar.gz", hash = "sha256:542e0d0b6750e2e21c20179803e40ab50598d8066d51097a0e382cba9eb02bff"},
|
886 |
]
|
|
|
|
|
|
|
|
|
887 |
pluggy = [
|
888 |
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
889 |
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
@@ -984,6 +1104,10 @@ toml = [
|
|
984 |
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
985 |
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
986 |
]
|
|
|
|
|
|
|
|
|
987 |
tqdm = [
|
988 |
{file = "tqdm-4.62.3-py2.py3-none-any.whl", hash = "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c"},
|
989 |
{file = "tqdm-4.62.3.tar.gz", hash = "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"},
|
@@ -992,6 +1116,32 @@ twine = [
|
|
992 |
{file = "twine-3.8.0-py3-none-any.whl", hash = "sha256:d0550fca9dc19f3d5e8eadfce0c227294df0a2a951251a4385797c8a6198b7c8"},
|
993 |
{file = "twine-3.8.0.tar.gz", hash = "sha256:8efa52658e0ae770686a13b675569328f1fba9837e5de1867bfe5f46a9aefe19"},
|
994 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
995 |
typing-extensions = [
|
996 |
{file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
|
997 |
{file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
|
|
|
54 |
html5lib = ["html5lib"]
|
55 |
lxml = ["lxml"]
|
56 |
|
57 |
+
[[package]]
|
58 |
+
name = "black"
|
59 |
+
version = "22.1.0"
|
60 |
+
description = "The uncompromising code formatter."
|
61 |
+
category = "dev"
|
62 |
+
optional = false
|
63 |
+
python-versions = ">=3.6.2"
|
64 |
+
|
65 |
+
[package.dependencies]
|
66 |
+
click = ">=8.0.0"
|
67 |
+
mypy-extensions = ">=0.4.3"
|
68 |
+
pathspec = ">=0.9.0"
|
69 |
+
platformdirs = ">=2"
|
70 |
+
tomli = ">=1.1.0"
|
71 |
+
typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""}
|
72 |
+
typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
|
73 |
+
|
74 |
+
[package.extras]
|
75 |
+
colorama = ["colorama (>=0.4.3)"]
|
76 |
+
d = ["aiohttp (>=3.7.4)"]
|
77 |
+
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
|
78 |
+
uvloop = ["uvloop (>=0.15.2)"]
|
79 |
+
|
80 |
[[package]]
|
81 |
name = "bleach"
|
82 |
version = "4.1.0"
|
|
|
120 |
[package.extras]
|
121 |
unicode_backport = ["unicodedata2"]
|
122 |
|
123 |
+
[[package]]
|
124 |
+
name = "click"
|
125 |
+
version = "8.0.4"
|
126 |
+
description = "Composable command line interface toolkit"
|
127 |
+
category = "dev"
|
128 |
+
optional = false
|
129 |
+
python-versions = ">=3.6"
|
130 |
+
|
131 |
+
[package.dependencies]
|
132 |
+
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
133 |
+
importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
|
134 |
+
|
135 |
[[package]]
|
136 |
name = "colorama"
|
137 |
version = "0.4.4"
|
|
|
271 |
optional = false
|
272 |
python-versions = ">=3.6"
|
273 |
|
274 |
+
[[package]]
|
275 |
+
name = "mypy-extensions"
|
276 |
+
version = "0.4.3"
|
277 |
+
description = "Experimental type system extensions for programs checked with the mypy typechecker."
|
278 |
+
category = "dev"
|
279 |
+
optional = false
|
280 |
+
python-versions = "*"
|
281 |
+
|
282 |
[[package]]
|
283 |
name = "packaging"
|
284 |
version = "21.3"
|
|
|
290 |
[package.dependencies]
|
291 |
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
|
292 |
|
293 |
+
[[package]]
|
294 |
+
name = "pathspec"
|
295 |
+
version = "0.9.0"
|
296 |
+
description = "Utility library for gitignore style pattern matching of file paths."
|
297 |
+
category = "dev"
|
298 |
+
optional = false
|
299 |
+
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
300 |
+
|
301 |
[[package]]
|
302 |
name = "pkginfo"
|
303 |
version = "1.8.2"
|
|
|
309 |
[package.extras]
|
310 |
testing = ["coverage", "nose"]
|
311 |
|
312 |
+
[[package]]
|
313 |
+
name = "platformdirs"
|
314 |
+
version = "2.5.1"
|
315 |
+
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
316 |
+
category = "dev"
|
317 |
+
optional = false
|
318 |
+
python-versions = ">=3.7"
|
319 |
+
|
320 |
+
[package.extras]
|
321 |
+
docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
|
322 |
+
test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
|
323 |
+
|
324 |
[[package]]
|
325 |
name = "pluggy"
|
326 |
version = "1.0.0"
|
|
|
624 |
optional = false
|
625 |
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
626 |
|
627 |
+
[[package]]
|
628 |
+
name = "tomli"
|
629 |
+
version = "2.0.1"
|
630 |
+
description = "A lil' TOML parser"
|
631 |
+
category = "dev"
|
632 |
+
optional = false
|
633 |
+
python-versions = ">=3.7"
|
634 |
+
|
635 |
[[package]]
|
636 |
name = "tqdm"
|
637 |
version = "4.62.3"
|
|
|
668 |
tqdm = ">=4.14"
|
669 |
urllib3 = ">=1.26.0"
|
670 |
|
671 |
+
[[package]]
|
672 |
+
name = "typed-ast"
|
673 |
+
version = "1.5.2"
|
674 |
+
description = "a fork of Python 2 and 3 ast modules with type comment support"
|
675 |
+
category = "dev"
|
676 |
+
optional = false
|
677 |
+
python-versions = ">=3.6"
|
678 |
+
|
679 |
[[package]]
|
680 |
name = "typing-extensions"
|
681 |
version = "4.0.1"
|
|
|
720 |
[metadata]
|
721 |
lock-version = "1.1"
|
722 |
python-versions = "^3.7"
|
723 |
+
content-hash = "465ff9b79ec7a4f8f67638bed33190079fbe1dcca8261d36813c7787e30624f2"
|
724 |
|
725 |
[metadata.files]
|
726 |
alabaster = [
|
|
|
743 |
{file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"},
|
744 |
{file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"},
|
745 |
]
|
746 |
+
black = [
|
747 |
+
{file = "black-22.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6"},
|
748 |
+
{file = "black-22.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866"},
|
749 |
+
{file = "black-22.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71"},
|
750 |
+
{file = "black-22.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab"},
|
751 |
+
{file = "black-22.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5"},
|
752 |
+
{file = "black-22.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b1a5ed73ab4c482208d20434f700d514f66ffe2840f63a6252ecc43a9bc77e8a"},
|
753 |
+
{file = "black-22.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35944b7100af4a985abfcaa860b06af15590deb1f392f06c8683b4381e8eeaf0"},
|
754 |
+
{file = "black-22.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7835fee5238fc0a0baf6c9268fb816b5f5cd9b8793423a75e8cd663c48d073ba"},
|
755 |
+
{file = "black-22.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dae63f2dbf82882fa3b2a3c49c32bffe144970a573cd68d247af6560fc493ae1"},
|
756 |
+
{file = "black-22.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa1db02410b1924b6749c245ab38d30621564e658297484952f3d8a39fce7e8"},
|
757 |
+
{file = "black-22.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c8226f50b8c34a14608b848dc23a46e5d08397d009446353dad45e04af0c8e28"},
|
758 |
+
{file = "black-22.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2d6f331c02f0f40aa51a22e479c8209d37fcd520c77721c034517d44eecf5912"},
|
759 |
+
{file = "black-22.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:742ce9af3086e5bd07e58c8feb09dbb2b047b7f566eb5f5bc63fd455814979f3"},
|
760 |
+
{file = "black-22.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fdb8754b453fb15fad3f72cd9cad3e16776f0964d67cf30ebcbf10327a3777a3"},
|
761 |
+
{file = "black-22.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5660feab44c2e3cb24b2419b998846cbb01c23c7fe645fee45087efa3da2d61"},
|
762 |
+
{file = "black-22.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:6f2f01381f91c1efb1451998bd65a129b3ed6f64f79663a55fe0e9b74a5f81fd"},
|
763 |
+
{file = "black-22.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:efbadd9b52c060a8fc3b9658744091cb33c31f830b3f074422ed27bad2b18e8f"},
|
764 |
+
{file = "black-22.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8871fcb4b447206904932b54b567923e5be802b9b19b744fdff092bd2f3118d0"},
|
765 |
+
{file = "black-22.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccad888050f5393f0d6029deea2a33e5ae371fd182a697313bdbd835d3edaf9c"},
|
766 |
+
{file = "black-22.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07e5c049442d7ca1a2fc273c79d1aecbbf1bc858f62e8184abe1ad175c4f7cc2"},
|
767 |
+
{file = "black-22.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:373922fc66676133ddc3e754e4509196a8c392fec3f5ca4486673e685a421321"},
|
768 |
+
{file = "black-22.1.0-py3-none-any.whl", hash = "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d"},
|
769 |
+
{file = "black-22.1.0.tar.gz", hash = "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5"},
|
770 |
+
]
|
771 |
bleach = [
|
772 |
{file = "bleach-4.1.0-py2.py3-none-any.whl", hash = "sha256:4d2651ab93271d1129ac9cbc679f524565cc8a1b791909c4a51eac4446a15994"},
|
773 |
{file = "bleach-4.1.0.tar.gz", hash = "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da"},
|
|
|
832 |
{file = "charset-normalizer-2.0.11.tar.gz", hash = "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c"},
|
833 |
{file = "charset_normalizer-2.0.11-py3-none-any.whl", hash = "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45"},
|
834 |
]
|
835 |
+
click = [
|
836 |
+
{file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"},
|
837 |
+
{file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"},
|
838 |
+
]
|
839 |
colorama = [
|
840 |
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
841 |
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
|
|
984 |
{file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"},
|
985 |
{file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"},
|
986 |
]
|
987 |
+
mypy-extensions = [
|
988 |
+
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
989 |
+
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
990 |
+
]
|
991 |
packaging = [
|
992 |
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
993 |
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
994 |
]
|
995 |
+
pathspec = [
|
996 |
+
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
|
997 |
+
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
|
998 |
+
]
|
999 |
pkginfo = [
|
1000 |
{file = "pkginfo-1.8.2-py2.py3-none-any.whl", hash = "sha256:c24c487c6a7f72c66e816ab1796b96ac6c3d14d49338293d2141664330b55ffc"},
|
1001 |
{file = "pkginfo-1.8.2.tar.gz", hash = "sha256:542e0d0b6750e2e21c20179803e40ab50598d8066d51097a0e382cba9eb02bff"},
|
1002 |
]
|
1003 |
+
platformdirs = [
|
1004 |
+
{file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"},
|
1005 |
+
{file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"},
|
1006 |
+
]
|
1007 |
pluggy = [
|
1008 |
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
1009 |
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
|
|
1104 |
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
1105 |
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
1106 |
]
|
1107 |
+
tomli = [
|
1108 |
+
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
1109 |
+
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
1110 |
+
]
|
1111 |
tqdm = [
|
1112 |
{file = "tqdm-4.62.3-py2.py3-none-any.whl", hash = "sha256:8dd278a422499cd6b727e6ae4061c40b48fce8b76d1ccbf5d34fca9b7f925b0c"},
|
1113 |
{file = "tqdm-4.62.3.tar.gz", hash = "sha256:d359de7217506c9851b7869f3708d8ee53ed70a1b8edbba4dbcb47442592920d"},
|
|
|
1116 |
{file = "twine-3.8.0-py3-none-any.whl", hash = "sha256:d0550fca9dc19f3d5e8eadfce0c227294df0a2a951251a4385797c8a6198b7c8"},
|
1117 |
{file = "twine-3.8.0.tar.gz", hash = "sha256:8efa52658e0ae770686a13b675569328f1fba9837e5de1867bfe5f46a9aefe19"},
|
1118 |
]
|
1119 |
+
typed-ast = [
|
1120 |
+
{file = "typed_ast-1.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:183b183b7771a508395d2cbffd6db67d6ad52958a5fdc99f450d954003900266"},
|
1121 |
+
{file = "typed_ast-1.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:676d051b1da67a852c0447621fdd11c4e104827417bf216092ec3e286f7da596"},
|
1122 |
+
{file = "typed_ast-1.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc2542e83ac8399752bc16e0b35e038bdb659ba237f4222616b4e83fb9654985"},
|
1123 |
+
{file = "typed_ast-1.5.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74cac86cc586db8dfda0ce65d8bcd2bf17b58668dfcc3652762f3ef0e6677e76"},
|
1124 |
+
{file = "typed_ast-1.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:18fe320f354d6f9ad3147859b6e16649a0781425268c4dde596093177660e71a"},
|
1125 |
+
{file = "typed_ast-1.5.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:31d8c6b2df19a777bc8826770b872a45a1f30cfefcfd729491baa5237faae837"},
|
1126 |
+
{file = "typed_ast-1.5.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:963a0ccc9a4188524e6e6d39b12c9ca24cc2d45a71cfdd04a26d883c922b4b78"},
|
1127 |
+
{file = "typed_ast-1.5.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0eb77764ea470f14fcbb89d51bc6bbf5e7623446ac4ed06cbd9ca9495b62e36e"},
|
1128 |
+
{file = "typed_ast-1.5.2-cp36-cp36m-win_amd64.whl", hash = "sha256:294a6903a4d087db805a7656989f613371915fc45c8cc0ddc5c5a0a8ad9bea4d"},
|
1129 |
+
{file = "typed_ast-1.5.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:26a432dc219c6b6f38be20a958cbe1abffcc5492821d7e27f08606ef99e0dffd"},
|
1130 |
+
{file = "typed_ast-1.5.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7407cfcad702f0b6c0e0f3e7ab876cd1d2c13b14ce770e412c0c4b9728a0f88"},
|
1131 |
+
{file = "typed_ast-1.5.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f30ddd110634c2d7534b2d4e0e22967e88366b0d356b24de87419cc4410c41b7"},
|
1132 |
+
{file = "typed_ast-1.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8c08d6625bb258179b6e512f55ad20f9dfef019bbfbe3095247401e053a3ea30"},
|
1133 |
+
{file = "typed_ast-1.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:90904d889ab8e81a956f2c0935a523cc4e077c7847a836abee832f868d5c26a4"},
|
1134 |
+
{file = "typed_ast-1.5.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bbebc31bf11762b63bf61aaae232becb41c5bf6b3461b80a4df7e791fabb3aca"},
|
1135 |
+
{file = "typed_ast-1.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c29dd9a3a9d259c9fa19d19738d021632d673f6ed9b35a739f48e5f807f264fb"},
|
1136 |
+
{file = "typed_ast-1.5.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:58ae097a325e9bb7a684572d20eb3e1809802c5c9ec7108e85da1eb6c1a3331b"},
|
1137 |
+
{file = "typed_ast-1.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:da0a98d458010bf4fe535f2d1e367a2e2060e105978873c04c04212fb20543f7"},
|
1138 |
+
{file = "typed_ast-1.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:33b4a19ddc9fc551ebabca9765d54d04600c4a50eda13893dadf67ed81d9a098"},
|
1139 |
+
{file = "typed_ast-1.5.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1098df9a0592dd4c8c0ccfc2e98931278a6c6c53cb3a3e2cf7e9ee3b06153344"},
|
1140 |
+
{file = "typed_ast-1.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42c47c3b43fe3a39ddf8de1d40dbbfca60ac8530a36c9b198ea5b9efac75c09e"},
|
1141 |
+
{file = "typed_ast-1.5.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f290617f74a610849bd8f5514e34ae3d09eafd521dceaa6cf68b3f4414266d4e"},
|
1142 |
+
{file = "typed_ast-1.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:df05aa5b241e2e8045f5f4367a9f6187b09c4cdf8578bb219861c4e27c443db5"},
|
1143 |
+
{file = "typed_ast-1.5.2.tar.gz", hash = "sha256:525a2d4088e70a9f75b08b3f87a51acc9cde640e19cc523c7e41aa355564ae27"},
|
1144 |
+
]
|
1145 |
typing-extensions = [
|
1146 |
{file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
|
1147 |
{file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
|
pyproject.toml
CHANGED
@@ -40,6 +40,7 @@ twine = "^3.4.2"
|
|
40 |
pytest = "^6.2.4"
|
41 |
pytest-runner = "^5.3.1"
|
42 |
toml = "^0.10.2"
|
|
|
43 |
|
44 |
[build-system]
|
45 |
requires = ["poetry-core>=1.0.0"]
|
|
|
40 |
pytest = "^6.2.4"
|
41 |
pytest-runner = "^5.3.1"
|
42 |
toml = "^0.10.2"
|
43 |
+
black = "^22.1.0"
|
44 |
|
45 |
[build-system]
|
46 |
requires = ["poetry-core>=1.0.0"]
|
tests/test_cli.py
CHANGED
@@ -9,15 +9,13 @@ import sys
|
|
9 |
|
10 |
@pytest.fixture
|
11 |
def mock_args():
|
12 |
-
sys.argv[1:] = [
|
13 |
return CLI(sys.argv[1:]).parse_args()
|
14 |
|
15 |
|
16 |
def test_source(mock_args):
|
17 |
-
assert mock_args.source ==
|
18 |
|
19 |
|
20 |
def test_target(mock_args):
|
21 |
-
assert mock_args.target ==
|
22 |
-
|
23 |
-
|
|
|
9 |
|
10 |
@pytest.fixture
|
11 |
def mock_args():
|
12 |
+
sys.argv[1:] = ["--source", "en", "--target", "de", "--text", "hello"]
|
13 |
return CLI(sys.argv[1:]).parse_args()
|
14 |
|
15 |
|
16 |
def test_source(mock_args):
|
17 |
+
assert mock_args.source == "en"
|
18 |
|
19 |
|
20 |
def test_target(mock_args):
|
21 |
+
assert mock_args.target == "de"
|
|
|
|
tests/test_data.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
test_text_standard =
|
2 |
|
3 |
TRANSLATED_RESULTS = {
|
4 |
"afrikaans": "Hello Wêreld.",
|
@@ -108,5 +108,5 @@ TRANSLATED_RESULTS = {
|
|
108 |
"xhosa": "Molo Lizwe.",
|
109 |
"yiddish": "העלא וועלט.",
|
110 |
"yoruba": "Mo ki O Ile Aiye.",
|
111 |
-
"zulu": "Sawubona Mhlaba."
|
112 |
}
|
|
|
1 |
+
test_text_standard = "Hello world."
|
2 |
|
3 |
TRANSLATED_RESULTS = {
|
4 |
"afrikaans": "Hello Wêreld.",
|
|
|
108 |
"xhosa": "Molo Lizwe.",
|
109 |
"yiddish": "העלא וועלט.",
|
110 |
"yoruba": "Mo ki O Ile Aiye.",
|
111 |
+
"zulu": "Sawubona Mhlaba.",
|
112 |
}
|
tests/test_deepl.py
CHANGED
@@ -4,26 +4,26 @@ from deep_translator.deepl import DeeplTranslator
|
|
4 |
from deep_translator.exceptions import AuthorizationException
|
5 |
|
6 |
|
7 |
-
@patch(
|
8 |
def test_simple_translation(mock_requests):
|
9 |
-
translator = DeeplTranslator(
|
|
|
|
|
10 |
# Set the request response mock.
|
11 |
mock_response = Mock()
|
12 |
mock_response.status_code = 200
|
13 |
-
mock_response.json.return_value = {
|
14 |
-
"translations": [{
|
15 |
-
"text": "hola"
|
16 |
-
}]
|
17 |
-
}
|
18 |
mock_requests.get.return_value = mock_response
|
19 |
-
translation = translator.translate(
|
20 |
-
assert translation ==
|
21 |
|
22 |
|
23 |
-
@patch(
|
24 |
def test_wrong_api_key(mock_requests):
|
25 |
-
translator = DeeplTranslator(
|
|
|
|
|
26 |
# Set the response status_code only.
|
27 |
mock_requests.return_value = Mock(status_code=403)
|
28 |
with pytest.raises(AuthorizationException):
|
29 |
-
translator.translate(
|
|
|
4 |
from deep_translator.exceptions import AuthorizationException
|
5 |
|
6 |
|
7 |
+
@patch("deep_translator.deepl.requests")
|
8 |
def test_simple_translation(mock_requests):
|
9 |
+
translator = DeeplTranslator(
|
10 |
+
api_key="imagine-this-is-an-valid-api-key", source="en", target="es"
|
11 |
+
)
|
12 |
# Set the request response mock.
|
13 |
mock_response = Mock()
|
14 |
mock_response.status_code = 200
|
15 |
+
mock_response.json.return_value = {"translations": [{"text": "hola"}]}
|
|
|
|
|
|
|
|
|
16 |
mock_requests.get.return_value = mock_response
|
17 |
+
translation = translator.translate("hello")
|
18 |
+
assert translation == "hola"
|
19 |
|
20 |
|
21 |
+
@patch("deep_translator.deepl.requests.get")
|
22 |
def test_wrong_api_key(mock_requests):
|
23 |
+
translator = DeeplTranslator(
|
24 |
+
api_key="this-is-a-wrong-api-key!", source="en", target="es"
|
25 |
+
)
|
26 |
# Set the response status_code only.
|
27 |
mock_requests.return_value = Mock(status_code=403)
|
28 |
with pytest.raises(AuthorizationException):
|
29 |
+
translator.translate("Hello")
|
tests/test_google.py
CHANGED
@@ -12,12 +12,12 @@ def google_translator():
|
|
12 |
"""Sample pytest fixture.
|
13 |
See more at: http://doc.pytest.org/en/latest/fixture.html
|
14 |
"""
|
15 |
-
return GoogleTranslator(target=
|
16 |
|
17 |
|
18 |
def test_content(google_translator):
|
19 |
"""Sample pytest test function with the pytest fixture as an argument."""
|
20 |
-
assert google_translator.translate(text=
|
21 |
|
22 |
|
23 |
def test_abbreviations_and_languages_mapping():
|
@@ -47,9 +47,9 @@ def test_empty_text(google_translator):
|
|
47 |
def test_payload(google_translator):
|
48 |
|
49 |
with pytest.raises(exceptions.NotValidPayload):
|
50 |
-
google_translator.translate(text=
|
51 |
-
google_translator.translate(text=
|
52 |
-
google_translator.translate(text=
|
53 |
|
54 |
with pytest.raises(exceptions.NotValidPayload):
|
55 |
google_translator.translate(text=123)
|
@@ -61,8 +61,8 @@ def test_payload(google_translator):
|
|
61 |
google_translator.translate(text=[])
|
62 |
|
63 |
with pytest.raises(exceptions.NotValidLength):
|
64 |
-
google_translator.translate("a"*5001)
|
65 |
|
66 |
|
67 |
def test_one_character_words():
|
68 |
-
assert GoogleTranslator(source=
|
|
|
12 |
"""Sample pytest fixture.
|
13 |
See more at: http://doc.pytest.org/en/latest/fixture.html
|
14 |
"""
|
15 |
+
return GoogleTranslator(target="en")
|
16 |
|
17 |
|
18 |
def test_content(google_translator):
|
19 |
"""Sample pytest test function with the pytest fixture as an argument."""
|
20 |
+
assert google_translator.translate(text="좋은") == "good"
|
21 |
|
22 |
|
23 |
def test_abbreviations_and_languages_mapping():
|
|
|
47 |
def test_payload(google_translator):
|
48 |
|
49 |
with pytest.raises(exceptions.NotValidPayload):
|
50 |
+
google_translator.translate(text="1234")
|
51 |
+
google_translator.translate(text="{}")
|
52 |
+
google_translator.translate(text="%@")
|
53 |
|
54 |
with pytest.raises(exceptions.NotValidPayload):
|
55 |
google_translator.translate(text=123)
|
|
|
61 |
google_translator.translate(text=[])
|
62 |
|
63 |
with pytest.raises(exceptions.NotValidLength):
|
64 |
+
google_translator.translate("a" * 5001)
|
65 |
|
66 |
|
67 |
def test_one_character_words():
|
68 |
+
assert GoogleTranslator(source="es", target="en").translate("o") == "or"
|
tests/test_libre.py
CHANGED
@@ -9,24 +9,24 @@ from deep_translator.constants import LIBRE_CODES_TO_LANGUAGES
|
|
9 |
|
10 |
@pytest.fixture
|
11 |
def libre():
|
12 |
-
return LibreTranslator(source="en", target=
|
13 |
|
14 |
|
15 |
def test_inputs():
|
16 |
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
17 |
-
LibreTranslator(source="", target="", api_key=
|
18 |
|
19 |
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
20 |
-
LibreTranslator(source="auto", target="", api_key=
|
21 |
|
22 |
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
23 |
-
LibreTranslator(source="", target="en", api_key=
|
24 |
|
25 |
|
26 |
def test_abbreviations_and_languages_mapping():
|
27 |
for abb, lang in LIBRE_CODES_TO_LANGUAGES.items():
|
28 |
-
l1 = LibreTranslator(abb, api_key=
|
29 |
-
l2 = LibreTranslator(lang, api_key=
|
30 |
assert l1._source == l2._source
|
31 |
|
32 |
|
|
|
9 |
|
10 |
@pytest.fixture
|
11 |
def libre():
|
12 |
+
return LibreTranslator(source="en", target="fr", api_key="some_key")
|
13 |
|
14 |
|
15 |
def test_inputs():
|
16 |
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
17 |
+
LibreTranslator(source="", target="", api_key="some_key")
|
18 |
|
19 |
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
20 |
+
LibreTranslator(source="auto", target="", api_key="some_key")
|
21 |
|
22 |
with pytest.raises(exceptions.InvalidSourceOrTargetLanguage):
|
23 |
+
LibreTranslator(source="", target="en", api_key="some_key")
|
24 |
|
25 |
|
26 |
def test_abbreviations_and_languages_mapping():
|
27 |
for abb, lang in LIBRE_CODES_TO_LANGUAGES.items():
|
28 |
+
l1 = LibreTranslator(abb, api_key="some_key")
|
29 |
+
l2 = LibreTranslator(lang, api_key="some_key")
|
30 |
assert l1._source == l2._source
|
31 |
|
32 |
|
tests/test_linguee.py
CHANGED
@@ -8,14 +8,14 @@ from deep_translator import exceptions, LingueeTranslator
|
|
8 |
|
9 |
@pytest.fixture
|
10 |
def linguee():
|
11 |
-
return LingueeTranslator(source="english", target=
|
12 |
|
13 |
|
14 |
def test_content(linguee):
|
15 |
"""Sample pytest test function with the pytest fixture as an argument."""
|
16 |
# from bs4 import BeautifulSoup
|
17 |
# assert 'GitHub' in BeautifulSoup(response.content).title.string
|
18 |
-
assert linguee.translate(word=
|
19 |
|
20 |
|
21 |
def test_inputs():
|
@@ -46,4 +46,4 @@ def test_payload(linguee):
|
|
46 |
linguee.translate([])
|
47 |
|
48 |
with pytest.raises(exceptions.NotValidLength):
|
49 |
-
linguee.translate("a"*51)
|
|
|
8 |
|
9 |
@pytest.fixture
|
10 |
def linguee():
|
11 |
+
return LingueeTranslator(source="english", target="german")
|
12 |
|
13 |
|
14 |
def test_content(linguee):
|
15 |
"""Sample pytest test function with the pytest fixture as an argument."""
|
16 |
# from bs4 import BeautifulSoup
|
17 |
# assert 'GitHub' in BeautifulSoup(response.content).title.string
|
18 |
+
assert linguee.translate(word="good") is not None
|
19 |
|
20 |
|
21 |
def test_inputs():
|
|
|
46 |
linguee.translate([])
|
47 |
|
48 |
with pytest.raises(exceptions.NotValidLength):
|
49 |
+
linguee.translate("a" * 51)
|
tests/test_microsoft_trans.py
CHANGED
@@ -10,22 +10,31 @@ from deep_translator import exceptions, MicrosoftTranslator
|
|
10 |
|
11 |
|
12 |
# mocked request.post
|
13 |
-
@patch.object(requests,
|
14 |
def test_microsoft_successful_post_mock(mock_request_post):
|
15 |
-
returned_json = [{
|
|
|
16 |
def res():
|
17 |
r = requests.Response()
|
|
|
18 |
def json_func():
|
19 |
return returned_json
|
|
|
20 |
r.json = json_func
|
21 |
return r
|
|
|
22 |
mock_request_post.return_value = res()
|
23 |
-
assert
|
|
|
|
|
|
|
|
|
|
|
24 |
|
25 |
|
26 |
def test_MicrosoftAPIerror():
|
27 |
with pytest.raises(exceptions.MicrosoftAPIerror):
|
28 |
-
MicrosoftTranslator(api_key="empty", source=
|
29 |
|
30 |
|
31 |
# the remaining tests are actual requests to Microsoft API and use an api key
|
@@ -36,13 +45,17 @@ APIkey = None
|
|
36 |
|
37 |
@pytest.mark.skipif(APIkey is None, reason="api_key is not provided")
|
38 |
def test_microsoft_successful_post_onetarget():
|
39 |
-
posted = MicrosoftTranslator(api_key=APIkey, target="en").translate(
|
|
|
|
|
40 |
assert isinstance(posted, str)
|
41 |
|
42 |
|
43 |
@pytest.mark.skipif(APIkey is None, reason="api_key is not provided")
|
44 |
def test_microsoft_successful_post_twotargets():
|
45 |
-
posted = MicrosoftTranslator(api_key=APIkey, target=["en", "ru"]).translate(
|
|
|
|
|
46 |
assert isinstance(posted, str)
|
47 |
|
48 |
|
@@ -58,5 +71,5 @@ def test_incorrect_target_attributes():
|
|
58 |
def test_abbreviations():
|
59 |
m1 = MicrosoftTranslator(api_key=APIkey, source="en", target="fr")
|
60 |
m2 = MicrosoftTranslator(api_key=APIkey, source="English", target="French")
|
61 |
-
assert
|
62 |
-
assert
|
|
|
10 |
|
11 |
|
12 |
# mocked request.post
|
13 |
+
@patch.object(requests, "post")
|
14 |
def test_microsoft_successful_post_mock(mock_request_post):
|
15 |
+
returned_json = [{"translations": [{"text": "See you later!", "to": "en"}]}]
|
16 |
+
|
17 |
def res():
|
18 |
r = requests.Response()
|
19 |
+
|
20 |
def json_func():
|
21 |
return returned_json
|
22 |
+
|
23 |
r.json = json_func
|
24 |
return r
|
25 |
+
|
26 |
mock_request_post.return_value = res()
|
27 |
+
assert (
|
28 |
+
MicrosoftTranslator(api_key="an_api_key", source="de", target="en").translate(
|
29 |
+
"auf wiedersehen!"
|
30 |
+
)
|
31 |
+
== "See you later!"
|
32 |
+
)
|
33 |
|
34 |
|
35 |
def test_MicrosoftAPIerror():
|
36 |
with pytest.raises(exceptions.MicrosoftAPIerror):
|
37 |
+
MicrosoftTranslator(api_key="empty", source="de", target="en").translate("text")
|
38 |
|
39 |
|
40 |
# the remaining tests are actual requests to Microsoft API and use an api key
|
|
|
45 |
|
46 |
@pytest.mark.skipif(APIkey is None, reason="api_key is not provided")
|
47 |
def test_microsoft_successful_post_onetarget():
|
48 |
+
posted = MicrosoftTranslator(api_key=APIkey, target="en").translate(
|
49 |
+
"auf wiedersehen!"
|
50 |
+
)
|
51 |
assert isinstance(posted, str)
|
52 |
|
53 |
|
54 |
@pytest.mark.skipif(APIkey is None, reason="api_key is not provided")
|
55 |
def test_microsoft_successful_post_twotargets():
|
56 |
+
posted = MicrosoftTranslator(api_key=APIkey, target=["en", "ru"]).translate(
|
57 |
+
"auf wiedersehen!"
|
58 |
+
)
|
59 |
assert isinstance(posted, str)
|
60 |
|
61 |
|
|
|
71 |
def test_abbreviations():
|
72 |
m1 = MicrosoftTranslator(api_key=APIkey, source="en", target="fr")
|
73 |
m2 = MicrosoftTranslator(api_key=APIkey, source="English", target="French")
|
74 |
+
assert "".join(m1._source) == "".join(m2._source)
|
75 |
+
assert "".join(m1._target) == "".join(m2._target)
|
tests/test_mymemory.py
CHANGED
@@ -8,14 +8,14 @@ from deep_translator import exceptions, MyMemoryTranslator
|
|
8 |
|
9 |
@pytest.fixture
|
10 |
def mymemory():
|
11 |
-
return MyMemoryTranslator(source="en", target=
|
12 |
|
13 |
|
14 |
def test_content(mymemory):
|
15 |
"""Sample pytest test function with the pytest fixture as an argument."""
|
16 |
# from bs4 import BeautifulSoup
|
17 |
# assert 'GitHub' in BeautifulSoup(response.content).title.string
|
18 |
-
assert mymemory.translate(text=
|
19 |
|
20 |
|
21 |
def test_inputs():
|
@@ -46,6 +46,4 @@ def test_payload(mymemory):
|
|
46 |
mymemory.translate(text=[])
|
47 |
|
48 |
with pytest.raises(exceptions.NotValidLength):
|
49 |
-
mymemory.translate(text="a"*501)
|
50 |
-
|
51 |
-
|
|
|
8 |
|
9 |
@pytest.fixture
|
10 |
def mymemory():
|
11 |
+
return MyMemoryTranslator(source="en", target="fr")
|
12 |
|
13 |
|
14 |
def test_content(mymemory):
|
15 |
"""Sample pytest test function with the pytest fixture as an argument."""
|
16 |
# from bs4 import BeautifulSoup
|
17 |
# assert 'GitHub' in BeautifulSoup(response.content).title.string
|
18 |
+
assert mymemory.translate(text="good") is not None
|
19 |
|
20 |
|
21 |
def test_inputs():
|
|
|
46 |
mymemory.translate(text=[])
|
47 |
|
48 |
with pytest.raises(exceptions.NotValidLength):
|
49 |
+
mymemory.translate(text="a" * 501)
|
|
|
|
tests/test_pons.py
CHANGED
@@ -8,14 +8,14 @@ from deep_translator import exceptions, PonsTranslator
|
|
8 |
|
9 |
@pytest.fixture
|
10 |
def pons():
|
11 |
-
return PonsTranslator(source="english", target=
|
12 |
|
13 |
|
14 |
def test_content(pons):
|
15 |
"""Sample pytest test function with the pytest fixture as an argument."""
|
16 |
# from bs4 import BeautifulSoup
|
17 |
# assert 'GitHub' in BeautifulSoup(response.content).title.string
|
18 |
-
assert pons.translate(word=
|
19 |
|
20 |
|
21 |
def test_inputs():
|
@@ -46,4 +46,3 @@ def test_payload(pons):
|
|
46 |
|
47 |
with pytest.raises(exceptions.NotValidLength):
|
48 |
pons.translate("a" * 51)
|
49 |
-
|
|
|
8 |
|
9 |
@pytest.fixture
|
10 |
def pons():
|
11 |
+
return PonsTranslator(source="english", target="french")
|
12 |
|
13 |
|
14 |
def test_content(pons):
|
15 |
"""Sample pytest test function with the pytest fixture as an argument."""
|
16 |
# from bs4 import BeautifulSoup
|
17 |
# assert 'GitHub' in BeautifulSoup(response.content).title.string
|
18 |
+
assert pons.translate(word="good") is not None
|
19 |
|
20 |
|
21 |
def test_inputs():
|
|
|
46 |
|
47 |
with pytest.raises(exceptions.NotValidLength):
|
48 |
pons.translate("a" * 51)
|
|