Skip to content

Commit

Permalink
fix: packaging and configure typed marker
Browse files Browse the repository at this point in the history
  • Loading branch information
eggplants committed Mar 3, 2022
1 parent 2926cd6 commit 7178c15
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 126 deletions.
1 change: 0 additions & 1 deletion .python-version

This file was deleted.

2 changes: 1 addition & 1 deletion deepl/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.0.18'
__version__ = "0.0.18"
150 changes: 94 additions & 56 deletions deepl/deepl.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
from urllib.parse import quote
from urllib.request import urlopen

from pyppeteer.browser import Browser # type: ignore
from pyppeteer.errors import TimeoutError # type: ignore
from pyppeteer.launcher import launch # type: ignore
from pyppeteer.page import Page # type: ignore
from pyppeteer.browser import Browser # type: ignore[import]
from pyppeteer.errors import TimeoutError # type: ignore[import]
from pyppeteer.launcher import launch # type: ignore[import]
from pyppeteer.page import Page # type: ignore[import]


class DeepLCLIArgCheckingError(Exception):
Expand All @@ -20,7 +20,6 @@ class DeepLCLIPageLoadError(Exception):


class DeepLCLI:

def __init__(self, langs: Optional[Tuple[str, str]] = None) -> None:
if langs:
self.fr_lang, self.to_lang = self._chk_lang(langs)
Expand All @@ -29,7 +28,9 @@ def __init__(self, langs: Optional[Tuple[str, str]] = None) -> None:
def usage(self) -> None:
"""Print usage."""

print(dedent('''\
print(
dedent(
"""\
$ deepl
SYNTAX:
$ ... | deepl <from:lang>:<to:lang>
Expand All @@ -51,26 +52,28 @@ def usage(self) -> None:
de hu fi fr bg pl pt lv lt ro ru en zh ja}
<to:lang>: {it et nl el sv es sk sl cs da
de hu fi fr bg pl pt lv lt ro ru en zh ja}
'''))
"""
)
)

def internet_on(self) -> bool:
"""Check an internet connection."""
try:
urlopen('http://www.google.com/', timeout=10)
urlopen("http://www.google.com/", timeout=10)
return True
except IOError:
return False

def _chk_stdin(self) -> None:
"""Check if stdin is entered."""
if (sys.stdin.isatty() and len(sys.argv) == 1) or '-h' in sys.argv:
if (sys.stdin.isatty() and len(sys.argv) == 1) or "-h" in sys.argv:
# if `$ deepl` or `$ deepl -h`
self.usage()
sys.tracebacklimit = 0
raise DeepLCLIArgCheckingError('show help.')
raise DeepLCLIArgCheckingError("show help.")
elif sys.stdin.isatty():
# raise err if stdin is empty
raise DeepLCLIArgCheckingError('stdin seems to be empty.')
raise DeepLCLIArgCheckingError("stdin seems to be empty.")

# def _chk_auth(self) -> None:
# """Check if login is required."""
Expand All @@ -82,28 +85,54 @@ def _chk_argnum(self, args: List[str]) -> None:
if num_opt != 1:
# raise err if arity != 1
raise DeepLCLIArgCheckingError(
'num of option is wrong(given %d, expected 1 or 2).' % num_opt)
"num of option is wrong(given %d, expected 1 or 2)." % num_opt
)

def _chk_lang(self, in_lang: Tuple[str, str]) -> Tuple[str, str]:
"""Check if language options are valid."""
fr_langs = {'auto', 'it', 'et', 'nl', 'el',
'sv', 'es', 'sk', 'sl', 'cs',
'da', 'de', 'hu', 'fi', 'fr',
'bg', 'pl', 'pt', 'lv', 'lt',
'ro', 'ru', 'en', 'zh', 'ja', ''}
to_langs = fr_langs - {'', 'auto'}

if len(in_lang) != 2 or in_lang[0] not in fr_langs \
or in_lang[1] not in to_langs:
fr_langs = {
"auto",
"it",
"et",
"nl",
"el",
"sv",
"es",
"sk",
"sl",
"cs",
"da",
"de",
"hu",
"fi",
"fr",
"bg",
"pl",
"pt",
"lv",
"lt",
"ro",
"ru",
"en",
"zh",
"ja",
"",
}
to_langs = fr_langs - {"", "auto"}

if (
len(in_lang) != 2
or in_lang[0] not in fr_langs
or in_lang[1] not in to_langs
):
# raise err if specify 2 langs is empty
raise DeepLCLIArgCheckingError('correct your lang format.')
raise DeepLCLIArgCheckingError("correct your lang format.")

if in_lang[0] == in_lang[1]:
# raise err if <fr:lang> == <to:lang>
raise DeepLCLIArgCheckingError('two languages cannot be same.')
raise DeepLCLIArgCheckingError("two languages cannot be same.")

fr = ('auto' if in_lang[0] == ''
else in_lang[0])
fr = "auto" if in_lang[0] == "" else in_lang[0]
to = in_lang[1]

return (fr, to)
Expand All @@ -122,64 +151,73 @@ def _chk_script(self, script: str) -> str:
if self.max_length is not None and len(script) > self.max_length:
# raise err if stdin > self.max_length chr
raise DeepLCLIArgCheckingError(
'limit of script is less than {} chars(Now: {} chars).'.format(
self.max_length, len(script)))
"limit of script is less than {} chars(Now: {} chars).".format(
self.max_length, len(script)
)
)
if len(script) <= 0:
# raise err if stdin <= 0 chr
raise DeepLCLIArgCheckingError('script seems to be empty.')
raise DeepLCLIArgCheckingError("script seems to be empty.")

return script

def translate(self, script: str) -> str:
if not self.internet_on():
raise DeepLCLIPageLoadError('Your network seem to be offline.')
self.fr_lang, self.to_lang = self._chk_lang(
(self.fr_lang, self.to_lang))
raise DeepLCLIPageLoadError("Your network seem to be offline.")
self.fr_lang, self.to_lang = self._chk_lang((self.fr_lang, self.to_lang))
self._chk_script(script)
script = quote(script, safe='')
return asyncio.get_event_loop().run_until_complete(
self._translate(script))
script = quote(script, safe="")
return asyncio.get_event_loop().run_until_complete(self._translate(script))

async def _translate(self, script: str) -> str:
"""Throw a request."""
browser: Browser = await launch(
headless=True,
args=[
'--no-sandbox',
'--single-process',
'--disable-dev-shm-usage',
'--disable-gpu',
'--no-zygote'

])
"--no-sandbox",
"--single-process",
"--disable-dev-shm-usage",
"--disable-gpu",
"--no-zygote",
],
)
page: Page = await browser.newPage()
userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6)'\
'AppleWebKit/537.36 (KHTML, like Gecko) '\
'Chrome/77.0.3864.0 Safari/537.36'
userAgent = (
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6)"
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/77.0.3864.0 Safari/537.36"
)
await page.setUserAgent(userAgent)
await page.goto(
'https://www.deepl.com/translator#{}/{}/{}'.format(
self.fr_lang, self.to_lang, script))
"https://www.deepl.com/translator#{}/{}/{}".format(
self.fr_lang, self.to_lang, script
)
)
try:
page.waitForSelector(
'#dl_translator > div.lmt__text', timeout=15000)
page.waitForSelector("#dl_translator > div.lmt__text", timeout=15000)
except TimeoutError:
raise DeepLCLIPageLoadError

try:
await page.waitForFunction('''
await page.waitForFunction(
"""
() => document.querySelector(
'textarea[dl-test=translator-target-input]').value !== ""
''')
await page.waitForFunction('''
"""
)
await page.waitForFunction(
"""
() => !document.querySelector(
'textarea[dl-test=translator-target-input]').value.includes("[...]")
''')
"""
)
except TimeoutError:
raise DeepLCLIPageLoadError

output_area = await page.J(
'textarea[dl-test="translator-target-input"]')
res = await page.evaluate('elm => elm.value', output_area)
output_area = await page.J('textarea[dl-test="translator-target-input"]')
res = await page.evaluate("elm => elm.value", output_area)
await browser.close()
return res.rstrip('\n')
if type(res) is str:
return res.rstrip("\n")
else:
raise ValueError("invalid response.")
8 changes: 4 additions & 4 deletions deepl/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
def main() -> None:
t = deepl.DeepLCLI()
t.chk_cmdargs()
t.fr_lang, t.to_lang = sys.argv[1].split(':')
t.fr_lang, t.to_lang = sys.argv[1].split(":")
script = sys.stdin.read()
print('Translating...', end='', file=sys.stderr, flush=True)
print("Translating...", end="", file=sys.stderr, flush=True)
result = t.translate(script)
print('\033[1K\033[G', end='', file=sys.stderr, flush=True)
print("\033[1K\033[G", end="", file=sys.stderr, flush=True)
print(result)


if __name__ == '__main__':
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
Expand Down
24 changes: 0 additions & 24 deletions mypy.ini

This file was deleted.

50 changes: 50 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[metadata]
name = deepl-cli
version = attr: deepl.__version__
description = DeepL Translator CLI using Selenium
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/eggplants/deepl-cli
license = MIT
author = eggplants
author_email = [email protected]
classifiers =
Development Status :: 3 - Alpha
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10

[options]
packages = find:
install_requires =
pyppeteer>=1.0.2
packages_data =
deepl = py.typed
python_requires = >= 3.7

[options.entry_points]
console_scripts =
deepl = deepl.main:main

[options.extras_require]
dev =
black
flake8
mypy
setuptools>=46.4.0
types-setuptools

[isort]
profile = black

[flake8]
indent-size = 4
max-line-length = 88
extend-ignore = W605

[mypy]
python_version = 3.9
show_error_codes = True
pretty = True
strict = True
25 changes: 2 additions & 23 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
from setuptools import find_packages, setup # type: ignore
from setuptools import setup

from deepl import __version__

setup(
name='deepl-cli',
version=__version__,
description='DeepL Translator CLI using Selenium',
description_content_type='',
long_description=open('README.md').read(),
long_description_content_type='text/markdown',
url='https://github.com/eggplants/deepl-cli',
author='eggplants',
packages=find_packages(),
python_requires='>=3.5, <3.10',
include_package_data=True,
license='MIT',
install_requires=['pyppeteer'],
entry_points={
'console_scripts': [
'deepl=deepl.main:main'
]
}
)
setup()
Loading

0 comments on commit 7178c15

Please sign in to comment.