From 5308ac8fbb7c84ac6fcb589646668918c0b35191 Mon Sep 17 00:00:00 2001 From: ti-oluwa <105179638+ti-oluwa@users.noreply.github.com> Date: Tue, 26 Dec 2023 19:02:31 +0100 Subject: [PATCH] Minor Refactoring. Published package to PYPI. --- .gitignore | 1 + README.md | 2 +- dist/tranzlate-0.0.1-py3-none-any.whl | Bin 0 -> 21542 bytes dist/tranzlate-0.0.1.tar.gz | Bin 0 -> 23539 bytes pyproject.toml | 54 +++++++++++++++ requirements.txt | 6 +- tests/fixtures/test_file.txt | 2 +- tests/test_translator.py | 2 +- tranzlate/__init__.py | 5 +- tranzlate/translator.py | 91 ++++++++++++++------------ 10 files changed, 111 insertions(+), 52 deletions(-) create mode 100644 dist/tranzlate-0.0.1-py3-none-any.whl create mode 100644 dist/tranzlate-0.0.1.tar.gz create mode 100644 pyproject.toml diff --git a/.gitignore b/.gitignore index 59ee0a5..19c5631 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ **/__pycache__/** +**/tranzlate.egg-info diff --git a/README.md b/README.md index 712c301..da77457 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ import tranzlate translator = tranzlate.Translator() markup = '

Good Morning!

' -translated_markup = translator.translate(markup, target_lang='yo') +translated_markup = translator.translate(markup, target_lang='yo', is_markup=True) print(translated_markup) # Output:

Eku ojumo!

diff --git a/dist/tranzlate-0.0.1-py3-none-any.whl b/dist/tranzlate-0.0.1-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..3c6752eec2fd8a9370c7f76a941ed16c49228e4d GIT binary patch literal 21542 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
  • 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 X>RPIpSbu(jeR~_q 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%0DNJD4JD8bZEgThWin1Lkctri_rRAlS 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 literal 0 HcmV?d00001 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..6751326 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,54 @@ +[build-system] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.dynamic] +version = {attr = "tranzlate.__version__"} + +[project] +name = "tranzlate" +dynamic = ["version"] +authors = [ + { name="ti-oluwa", email="tioluwa.dev@gmail.com" }, +] +maintainers = [ + { name="ti-oluwa", email="tioluwa.dev@gmail.com" }, +] +description = "Multilingual translation of text, files, markup and BeautifulSoup objects." +keywords = [ + "translate", + "translation", + "google translate", + "bing translate", + "yandex translate", + "translate text", + "translate files", + "translate markup", + "translate html", + "translate xml", + "translate BeautifulSoup", + "detect language", +] +readme = "README.md" +requires-python = ">=3.7" +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Operating System :: OS Independent", + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Utilities", + "Natural Language :: English", + "Typing :: Typed", +] +dependencies = [ + "translators==5.8.9", + "beautifulsoup4==4.12.2", + "simple_file_handler>=0.0.1", +] + +[project.urls] +"Homepage" = "https://github.com/ti-oluwa/tranzlate" +"Bug Tracker" = "https://github.com/ti-oluwa/tranzlate/issues" +"Repository" = "https://github.com/ti-oluwa/tranzlate" diff --git a/requirements.txt b/requirements.txt index b7f7ae2..0b01b27 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -translators -bs4 -bs4_web_scraper +translators==5.8.9 +beautifulsoup4==4.12.2 +simple_file_handler>=0.0.1 diff --git a/tests/fixtures/test_file.txt b/tests/fixtures/test_file.txt index cdc96a1..559db19 100644 --- a/tests/fixtures/test_file.txt +++ b/tests/fixtures/test_file.txt @@ -1 +1 @@ -Awọn ohun elo ti o wa ni ti o wa ni ti o ti o ti o ti o ti o ti o ti o ba ti o ba ti o ba ti o ba nífẹẹẹ si ipa yìí, jọwọwò béèrè fun àgbéyẹwò lẹyìn. \ No newline at end of file +Awọn ohun elo ti o wa ni ti o wa ni ti o ti o ti o ti o ti o ti o ti o ti o ti o ba ti o ba ti o ba ti o ba ti o ba ti o ba fẹ baẹẹ si ipa yìí, jọwọ béèrè fun àgbégbégbé lẹyìn. \ No newline at end of file diff --git a/tests/test_translator.py b/tests/test_translator.py index 0092bae..dfd33fc 100644 --- a/tests/test_translator.py +++ b/tests/test_translator.py @@ -136,4 +136,4 @@ def test_translate_soup(self): if "__name__" == "__main__": unittest.main() -# RUN WITH 'python -m unittest discover tests "test_*.py"' from project directory +# RUN WITH 'python -m unittest discover tests "test_*.py"' from project's root directory diff --git a/tranzlate/__init__.py b/tranzlate/__init__.py index 870d93b..403eea6 100644 --- a/tranzlate/__init__.py +++ b/tranzlate/__init__.py @@ -6,9 +6,8 @@ @Author: Daniel T. Afolayan (ti-oluwa.github.io) """ -__version__ = "0.0.1" -__author__ = "Daniel T. Afolayan" - from .translator import Translator __all__ = ["Translator"] +__version__ = "0.0.1" +__author__ = "Daniel T. Afolayan" diff --git a/tranzlate/translator.py b/tranzlate/translator.py index 5ece29f..83e73f7 100644 --- a/tranzlate/translator.py +++ b/tranzlate/translator.py @@ -1,10 +1,9 @@ """ Translate text, markup content, BeautifulSoup objects and files using the `translators` package. """ - import functools import sys -from typing import Callable, Dict, List, Tuple +from typing import Callable, Dict, List, Tuple, IO from array import array import time import copy @@ -13,8 +12,8 @@ from bs4.element import Tag from concurrent.futures import ThreadPoolExecutor from translators.server import TranslatorsServer, tss, Tse +import simple_file_handler as sfh -from bs4_web_scraper.file_handler import FileHandler from .exceptions import TranslationError, UnsupportedLanguageError @@ -86,7 +85,7 @@ def __init__(self, engine: str = "bing"): @property - def server(self): + def server(self) -> TranslatorsServer: """The translation server used by the Translator instance""" if not isinstance(self._server, TranslatorsServer): raise TypeError("Invalid type for `_server`") @@ -122,7 +121,7 @@ def language_map(self) -> Dict: return {} @property - def supported_languages(self): + def supported_languages(self) -> List: """ Returns a list of language codes for source languages supported by the translator's engine. @@ -131,12 +130,12 @@ def supported_languages(self): @classmethod - def engines(cls): + def engines(cls) -> List[str]: """Returns a list of supported translation engines""" return cls._server.translators_pool - def is_supported_language(self, lang_code: str): + def is_supported_language(self, lang_code: str) -> bool: ''' Check if the source language with the specified language code is supported by the translator's engine. @@ -252,8 +251,9 @@ def translate( src_lang: str = "auto", target_lang: str = "en", is_markup: bool = False, + encoding: str = "utf-8", **kwargs - ): + ) -> str | bytes | BeautifulSoup: ''' Translate content from source language to target language. @@ -262,6 +262,7 @@ def translate( It is advisable to provide a source language to get more accurate translations. :param target_lang (str, optional): Target language. Defaults to "en". :param is_markup (bool, optional): Whether `content` is markup. Defaults to False. + :param encoding (str, optional): The encoding of the content (for bytes content only). Defaults to "utf-8". :param **kwargs: Keyword arguments to be passed to required translation method. :return: Translated content. @@ -276,11 +277,13 @@ def translate( # Output: "Yorùbá jẹ́ èdè tí ó ń ṣe àwọn èdè ní ìlà oòrùn Áfríkà, tí ó wà ní orílẹ̀-èdè Gúúsù Áfríkà." ''' + is_bytes = isinstance(content, bytes) if is_markup: return self.translate_markup( markup=content, src_lang=src_lang, - target_lang=target_lang, + target_lang=target_lang, + encoding=encoding, **kwargs ) elif isinstance(content, BeautifulSoup): @@ -290,12 +293,14 @@ def translate( target_lang=target_lang, **kwargs ) - return self.translate_text( - text=content, + + translation = self.translate_text( + text=content.decode(encoding) if is_bytes else content, src_lang=src_lang, target_lang=target_lang, **kwargs ) + return translation.encode(encoding) if is_bytes else translation # @functools.cache @@ -305,7 +310,7 @@ def translate_text( src_lang: str="auto", target_lang: str="en", **kwargs - ) -> str | Dict: + ) -> str: ''' Translate text from `src_lang` to `target_lang`. @@ -337,6 +342,7 @@ def translate_text( self._check_lang_codes(src_lang, target_lang) kwargs_ = {'if_ignore_empty_query': True} + kwargs.pop('is_detail_result', None) kwargs_.update(kwargs) def _translate(text: str): @@ -363,7 +369,7 @@ def translate_file( src_lang: str="auto", target_lang: str="en", **kwargs - ): + ) -> IO: ''' Translates file from `src_lang` to `target_lang`. @@ -392,27 +398,25 @@ def translate_file( self._check_lang_codes(src_lang, target_lang) kwargs_ = {'if_ignore_empty_query': True} kwargs.pop('is_detail_result', None) - kwargs_.update(kwargs) - try: - file_handler = FileHandler(filepath, exists_ok=True, not_found_ok=False) - except Exception as exc: - raise TranslationError(f"Could not translate file") from exc - - if not file_handler.file_content: - return file_handler.file - - try: - if file_handler.filetype in ['xhtml', 'htm', 'shtml', 'html', 'xml']: - translated_content = self.translate_markup(file_handler.file_content, src_lang, target_lang, **kwargs_) - else: - translated_content = self.translate_text(file_handler.file_content, src_lang, target_lang, **kwargs_) - file_handler.write_to_file(translated_content, write_mode='w+') - file_handler.close_file() - return file_handler.file + try: + with sfh.FileHandler(filepath, exists_ok=True, not_found_ok=False) as file_handler: + content = file_handler.file_content + if not content: + return file_handler.file + + if file_handler.filetype in ['xhtml', 'htm', 'shtml', 'html', 'xml']: + translation = self.translate_markup(content, src_lang, target_lang, **kwargs_) + else: + translation = self.translate_text(content, src_lang, target_lang, **kwargs_) + + file_handler.write_to_file(translation, write_mode='w+') + return file_handler.file except Exception as exc: - raise TranslationError(f"File cannot be translated. {exc}") + raise TranslationError( + "File cannot be translated." + ) from exc def _translate_soup_tag( @@ -464,7 +468,7 @@ def _translate_soup_tag( # try again _ct += 1 # prevents the translation engine from blocking our IP address - time.sleep(random.random(2, 5) * _ct) + time.sleep(random.random(2, 4) * _ct) if _ct <= 3: return self._translate_soup_tag(tag, src_lang, target_lang, _ct, **kwargs) finally: @@ -479,7 +483,7 @@ def translate_soup( target_lang: str = "en", thread: bool = True, **kwargs - ): + ) -> BeautifulSoup: ''' Translates the text of a BeautifulSoup object. @@ -512,17 +516,21 @@ def translate_soup( def translate_markup( self, markup: str | bytes, - src_lang: str="auto", - target_lang: str="en", + src_lang: str = "auto", + target_lang: str = "en", + markup_parser: str = "lxml", + encoding: str = "utf-8", **kwargs - ): + ) -> str | bytes: ''' - Translates markup. + Translates markup (html, xml, etc.) :param markup (str | bytes): markup content to be translated :param src_lang (str, optional): Source language. Defaults to "auto". It is advisable to provide a source language to get more accurate translations. :param target_lang (str, optional): Target language. Defaults to "en". + :param markup_parser (str, optional): The (beautifulsoup) markup parser to use. Defaults to "lxml". + :param encoding (str, optional): The encoding of the markup (for bytes markup only). Defaults to "utf-8". :param **kwargs: Keyword arguments to be passed to the `translate_soup` method. :kwarg thread: bool, default True. :kwarg professional_field: str, support baidu(), caiyun(), alibaba() only. @@ -542,12 +550,9 @@ def translate_markup( ''' if not isinstance(markup, (str, bytes)): raise TypeError("Invalid type for `markup`") + is_bytes = isinstance(markup, bytes) kwargs.pop('is_detail_result', None) - soup = BeautifulSoup(markup, 'lxml') + soup = BeautifulSoup(markup, markup_parser, from_encoding=encoding if is_bytes else None) translated_markup = self.translate_soup(soup, src_lang, target_lang, **kwargs).prettify() - - # re-encode the markup if the initial markup was in bytes - if is_bytes: - translated_markup = translated_markup.encode('utf-8') - return translated_markup + return translated_markup.encode('utf-8') if is_bytes else translated_markup