deepl-python icon indicating copy to clipboard operation
deepl-python copied to clipboard

translated_text should use method overload to have better typing

Open DanieleIsoni opened this issue 2 years ago • 1 comments

In the typing of the translate_text it would be better to use method overloading, so that the return type is not ambiguous when passing a text variable that is either str or Iterable[str]

So I suggest that here https://github.com/DeepLcom/deepl-python/blob/16108b0b4b196a67e8d5168490098dd96b312efe/deepl/translator.py#L334-L350 the typing should be something like:

@overload
def translate_text(
        self,
        text: str,
        *,
        source_lang: Union[str, Language, None] = None,
        target_lang: Union[str, Language],
        context: Optional[str] = None,
        split_sentences: Union[str, SplitSentences, None] = None,
        preserve_formatting: Optional[bool] = None,
        formality: Union[str, Formality, None] = None,
        glossary: Union[str, GlossaryInfo, None] = None,
        tag_handling: Optional[str] = None,
        outline_detection: Optional[bool] = None,
        non_splitting_tags: Union[str, List[str], None] = None,
        splitting_tags: Union[str, List[str], None] = None,
        ignore_tags: Union[str, List[str], None] = None,
    ) -> TextResult:
    ...

@overload
def translate_text(
        self,
        text: Iterable[str],
        *,
        source_lang: Union[str, Language, None] = None,
        target_lang: Union[str, Language],
        context: Optional[str] = None,
        split_sentences: Union[str, SplitSentences, None] = None,
        preserve_formatting: Optional[bool] = None,
        formality: Union[str, Formality, None] = None,
        glossary: Union[str, GlossaryInfo, None] = None,
        tag_handling: Optional[str] = None,
        outline_detection: Optional[bool] = None,
        non_splitting_tags: Union[str, List[str], None] = None,
        splitting_tags: Union[str, List[str], None] = None,
        ignore_tags: Union[str, List[str], None] = None,
    ) -> List[TextResult]:
    ...

def translate_text(
        self,
        text: Union[str, Iterable[str]],
        *,
        source_lang: Union[str, Language, None] = None,
        target_lang: Union[str, Language],
        context: Optional[str] = None,
        split_sentences: Union[str, SplitSentences, None] = None,
        preserve_formatting: Optional[bool] = None,
        formality: Union[str, Formality, None] = None,
        glossary: Union[str, GlossaryInfo, None] = None,
        tag_handling: Optional[str] = None,
        outline_detection: Optional[bool] = None,
        non_splitting_tags: Union[str, List[str], None] = None,
        splitting_tags: Union[str, List[str], None] = None,
        ignore_tags: Union[str, List[str], None] = None,
    ) -> Union[TextResult, List[TextResult]]:

If typed like this mypy understands that when text is a str the return type is TextResult and when it is an Iterable[str] the return type is List[TextResult], avoiding error messages like when passing an Iterable[str] as text:

<file>:102: error: Item "TextResult" of "TextResult | list[TextResult]" has no attribute "__iter__" (not iterable)  [union-attr]

If you prefer, I'd be glad submit a pull request

DanieleIsoni avatar Nov 20 '23 10:11 DanieleIsoni

This is a great suggestion, if you could up a PR I'll merge it, thanks!

JanEbbing avatar Nov 20 '23 10:11 JanEbbing