From 7e794534c05153f9a4494a9879c9e9767024fcaf Mon Sep 17 00:00:00 2001 From: Seth Yastrov Date: Wed, 13 Nov 2019 07:47:45 +0100 Subject: [PATCH 1/2] Better type for force_text using overloads/Literal - If a str is passed in, it returns a str. - If strings_only = True and a "protected type" is passed in, returns that type. - Default if it doesn't match the overloads: return a str --- django-stubs/utils/encoding.pyi | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/django-stubs/utils/encoding.pyi b/django-stubs/utils/encoding.pyi index 5e44ae0..b1d0eab 100644 --- a/django-stubs/utils/encoding.pyi +++ b/django-stubs/utils/encoding.pyi @@ -1,4 +1,6 @@ -from typing import Any, Optional +from typing import Any, Optional, TypeVar, Union, Literal, overload +from decimal import Decimal +import datetime class DjangoUnicodeDecodeError(UnicodeDecodeError): obj: bytes = ... @@ -8,7 +10,18 @@ python_2_unicode_compatible: Any def smart_text(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> str: ... def is_protected_type(obj: Any) -> bool: ... -def force_text(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> Optional[str]: ... + +_ProtectedType = TypeVar( + "_ProtectedType", Union[None, int, float, Decimal, datetime.datetime, datetime.date, datetime.time] +) +@overload +def force_text(s: str, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> str: ... +@overload +def force_text( + s: _ProtectedType, encoding: str = ..., strings_only: Literal[True] = ..., errors: str = ..., +) -> _ProtectedType: ... +@overload +def force_text(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> str: ... def smart_bytes(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> bytes: ... def force_bytes(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> bytes: ... From f7e2109e06f1c21b0046ed66d4de76cb5f2783dc Mon Sep 17 00:00:00 2001 From: Maxim Kurnikov Date: Tue, 10 Dec 2019 23:07:44 +0300 Subject: [PATCH 2/2] add @overload clauses to smart_text, smart_bytes, force_bytes --- django-stubs/utils/encoding.pyi | 53 +++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/django-stubs/utils/encoding.pyi b/django-stubs/utils/encoding.pyi index b1d0eab..3d5c6d6 100644 --- a/django-stubs/utils/encoding.pyi +++ b/django-stubs/utils/encoding.pyi @@ -1,38 +1,59 @@ -from typing import Any, Optional, TypeVar, Union, Literal, overload -from decimal import Decimal import datetime +from decimal import Decimal +from typing import Any, TypeVar, overload, Union + +from django.utils.functional import Promise +from typing_extensions import Literal class DjangoUnicodeDecodeError(UnicodeDecodeError): obj: bytes = ... def __init__(self, obj: bytes, *args: Any) -> None: ... -python_2_unicode_compatible: Any - +_P = TypeVar("_P", bound=Promise) +_S = TypeVar("_S", bound=str) +_PT = TypeVar("_PT", None, int, float, Decimal, datetime.datetime, datetime.date, datetime.time) +@overload +def smart_text(s: _P, encoding: str = ..., strings_only: bool = ..., errors: str = ...,) -> _P: ... +@overload +def smart_text(s: _PT, encoding: str = ..., strings_only: Literal[True] = ..., errors: str = ...,) -> _PT: ... +@overload +def smart_text(s: _S, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> _S: ... +@overload def smart_text(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> str: ... def is_protected_type(obj: Any) -> bool: ... - -_ProtectedType = TypeVar( - "_ProtectedType", Union[None, int, float, Decimal, datetime.datetime, datetime.date, datetime.time] -) @overload -def force_text(s: str, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> str: ... +def force_text(s: _PT, encoding: str = ..., strings_only: Literal[True] = ..., errors: str = ...,) -> _PT: ... @overload -def force_text( - s: _ProtectedType, encoding: str = ..., strings_only: Literal[True] = ..., errors: str = ..., -) -> _ProtectedType: ... +def force_text(s: _S, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> _S: ... @overload def force_text(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> str: ... +@overload +def smart_bytes(s: _P, encoding: str = ..., strings_only: bool = ..., errors: str = ...,) -> _P: ... +@overload +def smart_bytes(s: _PT, encoding: str = ..., strings_only: Literal[True] = ..., errors: str = ...,) -> _PT: ... +@overload def smart_bytes(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> bytes: ... +@overload +def force_bytes(s: _PT, encoding: str = ..., strings_only: Literal[True] = ..., errors: str = ...,) -> _PT: ... +@overload def force_bytes(s: Any, encoding: str = ..., strings_only: bool = ..., errors: str = ...) -> bytes: ... smart_str = smart_text force_str = force_text - -def iri_to_uri(iri: Optional[str]) -> Optional[str]: ... -def uri_to_iri(uri: Optional[str]) -> Optional[str]: ... +@overload +def iri_to_uri(iri: None) -> None: ... +@overload +def iri_to_uri(iri: Union[str, Promise]) -> str: ... +@overload +def uri_to_iri(iri: None) -> None: ... +@overload +def uri_to_iri(iri: str) -> str: ... def escape_uri_path(path: str) -> str: ... def repercent_broken_unicode(path: bytes) -> bytes: ... -def filepath_to_uri(path: Optional[str]) -> Optional[str]: ... +@overload +def filepath_to_uri(path: None) -> None: ... +@overload +def filepath_to_uri(path: str) -> str: ... def get_system_encoding() -> str: ... DEFAULT_LOCALE_ENCODING: Any