Skip to content

Commit 4107220

Browse files
daniel-jones-devJanEbbing
authored andcommitted
feat: Add DeepLClient class for write implementation
1 parent 43120f1 commit 4107220

File tree

4 files changed

+159
-2
lines changed

4 files changed

+159
-2
lines changed

deepl/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
__author__ = "DeepL SE <python-api@deepl.com>"
88

9+
from .deepl_client import DeepLClient
10+
911
from .exceptions import ( # noqa
1012
AuthorizationException,
1113
ConnectionException,
@@ -42,6 +44,7 @@
4244
__all__ = [
4345
"__version__",
4446
"__author__",
47+
"DeepLClient",
4548
"DocumentHandle",
4649
"DocumentStatus",
4750
"Formality",

deepl/__main__.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,19 @@ def action_text(
113113
print(output.text)
114114

115115

116+
def action_rephrase(
117+
translator: deepl.Translator,
118+
**kwargs,
119+
):
120+
"""Action function for the rephrase command."""
121+
improvement = translator.rephrase_text(**kwargs)
122+
output_list = (
123+
improvement if isinstance(improvement, List) else [improvement]
124+
)
125+
for output in output_list:
126+
print(output.text)
127+
128+
116129
def action_glossary(
117130
translator: deepl.Translator,
118131
subcommand: str,
@@ -311,7 +324,10 @@ def add_common_arguments(subparser: argparse.ArgumentParser):
311324

312325
# create the parser for the "text" command
313326
parser_text = subparsers.add_parser(
314-
"text", help="translate text(s)", description="translate text(s)"
327+
"text",
328+
help="translate text(s)",
329+
description="translate text(s)",
330+
aliases=["translate"],
315331
)
316332
add_common_arguments(parser_text)
317333
parser_text.add_argument(
@@ -410,6 +426,31 @@ def add_common_arguments(subparser: argparse.ArgumentParser):
410426
help="specify tags containing text that should not be translated",
411427
)
412428

429+
# create the parser for the "rephrase" command
430+
parser_rephrase = subparsers.add_parser(
431+
"rephrase", help="rephrase text(s)", description="rephrase text(s)"
432+
)
433+
parser_rephrase.add_argument(
434+
"--to",
435+
"--target-lang",
436+
dest="target_lang",
437+
required=True,
438+
help="language into which the text should be rewritten",
439+
)
440+
parser_rephrase.add_argument(
441+
"text",
442+
nargs="+",
443+
type=str,
444+
help="text to be rewritten. Wrap text in quotes to prevent the shell "
445+
'from splitting sentences into words. Alternatively, use "-" to read '
446+
"from standard-input.",
447+
)
448+
parser_rephrase.add_argument(
449+
"--show-detected-source",
450+
action="store_true",
451+
help="print detected source language for each text",
452+
)
453+
413454
# create the parser for the "document" command
414455
parser_document = subparsers.add_parser(
415456
"document",
@@ -608,7 +649,7 @@ def main(args=None, prog_name=None):
608649
send_platform_info=not args.noplatforminfo,
609650
)
610651

611-
if args.command == "text":
652+
if args.command in ["text", "translate", "rephrase"]:
612653
if len(args.text) == 1 and args.text[0] == "-":
613654
args.text = [sys.stdin.read()]
614655

deepl/api_data.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,20 @@ def __str__(self):
2828
return self.text
2929

3030

31+
class WriteResult:
32+
"""Holds the result of a text improvement request."""
33+
34+
def __init__(
35+
self, text: str, detected_source_language: str, target_language: str
36+
):
37+
self.text = text
38+
self.detected_source_language = detected_source_language
39+
self.target_language = target_language
40+
41+
def __str__(self):
42+
return self.text
43+
44+
3145
class DocumentHandle:
3246
"""Handle to an in-progress document translation.
3347

deepl/deepl_client.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Copyright 2025 DeepL SE (https://www.deepl.com)
2+
# Use of this source code is governed by an MIT
3+
# license that can be found in the LICENSE file.
4+
5+
from deepl.api_data import (
6+
Language,
7+
WriteResult,
8+
)
9+
from deepl.translator import Translator
10+
from typing import (
11+
Dict,
12+
Iterable,
13+
List,
14+
Optional,
15+
Union,
16+
)
17+
18+
19+
class DeepLClient(Translator):
20+
def __init__(
21+
self,
22+
auth_key: str,
23+
*,
24+
server_url: Optional[str] = None,
25+
proxy: Union[Dict, str, None] = None,
26+
send_platform_info: bool = True,
27+
verify_ssl: Union[bool, str, None] = None,
28+
skip_language_check: bool = False,
29+
):
30+
super().__init__(
31+
auth_key,
32+
server_url=server_url,
33+
proxy=proxy,
34+
send_platform_info=send_platform_info,
35+
verify_ssl=verify_ssl,
36+
skip_language_check=skip_language_check,
37+
)
38+
39+
def rephrase_text(
40+
self,
41+
text: Union[str, Iterable[str]],
42+
*,
43+
target_lang: Union[str, Language],
44+
) -> Union[WriteResult, List[WriteResult]]:
45+
"""Improve the text(s) and optionally convert them to the variant of
46+
the `target_lang` (requires source lang to match target_lang, excluding
47+
variants).
48+
49+
:param text: Text to improve.
50+
:type text: UTF-8 :class:`str`; string sequence (list, tuple, iterator,
51+
generator)
52+
:param target_lang: language code the final text should be in, for
53+
example "DE", "EN-US", "FR".
54+
:return: List of WriteResult objects containing results, unless input
55+
text was one string, then a single WriteResult object is returned.
56+
"""
57+
58+
if isinstance(text, str):
59+
if len(text) == 0:
60+
raise ValueError("text must not be empty")
61+
text = [text]
62+
multi_input = False
63+
elif hasattr(text, "__iter__"):
64+
multi_input = True
65+
text = list(text)
66+
else:
67+
raise TypeError(
68+
"text parameter must be a string or an iterable of strings"
69+
)
70+
71+
request_data = {"target_lang": target_lang, "text": text}
72+
73+
status, content, json = self._api_call(
74+
"v2/write/rephrase", json=request_data
75+
)
76+
77+
self._raise_for_status(status, content, json)
78+
79+
improvements = (
80+
json.get("improvements", [])
81+
if (json and isinstance(json, dict))
82+
else []
83+
)
84+
output = []
85+
for improvement in improvements:
86+
text = improvement.get("text", "") if improvement else ""
87+
detected_source_language = (
88+
improvement.get("detected_source_language", "")
89+
if improvement
90+
else ""
91+
)
92+
target_language = (
93+
improvement.get("target_language", "") if improvement else ""
94+
)
95+
output.append(
96+
WriteResult(text, detected_source_language, target_language)
97+
)
98+
99+
return output if multi_input else output[0]

0 commit comments

Comments
 (0)