From 04fb7ceb3ce919ed541a5b7b675359f09a104e16 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Sat, 29 May 2021 07:09:38 -0700 Subject: [PATCH] builtins: add a getattr overload for bool (#5518) As brought up in https://github.com/python/typeshed/pull/5516 Alternatives include: - Use another type var that has a value restriction - Doing something fancy with Protocols that have a __bool__ that returns a Literal (which may not work) - Doing nothing --- stdlib/@python2/__builtin__.pyi | 5 +++++ stdlib/@python2/builtins.pyi | 5 +++++ stdlib/builtins.pyi | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/stdlib/@python2/__builtin__.pyi b/stdlib/@python2/__builtin__.pyi index b7b68bbb7..0b2c89e8d 100644 --- a/stdlib/@python2/__builtin__.pyi +++ b/stdlib/@python2/__builtin__.pyi @@ -863,9 +863,14 @@ def filter(__function: Callable[[_T], Any], __iterable: Iterable[_T]) -> List[_T def format(__value: object, __format_spec: str = ...) -> str: ... # TODO unicode @overload def getattr(__o: Any, name: Text) -> Any: ... + +# While technically covered by the last overload, spelling out the types for None and bool +# help mypy out in some tricky situations involving type context (aka bidirectional inference) @overload def getattr(__o: Any, name: Text, __default: None) -> Optional[Any]: ... @overload +def getattr(__o: Any, name: Text, __default: bool) -> Union[Any, bool]: ... +@overload def getattr(__o: Any, name: Text, __default: _T) -> Union[Any, _T]: ... def globals() -> Dict[str, Any]: ... def hasattr(__obj: Any, __name: Text) -> bool: ... diff --git a/stdlib/@python2/builtins.pyi b/stdlib/@python2/builtins.pyi index b7b68bbb7..0b2c89e8d 100644 --- a/stdlib/@python2/builtins.pyi +++ b/stdlib/@python2/builtins.pyi @@ -863,9 +863,14 @@ def filter(__function: Callable[[_T], Any], __iterable: Iterable[_T]) -> List[_T def format(__value: object, __format_spec: str = ...) -> str: ... # TODO unicode @overload def getattr(__o: Any, name: Text) -> Any: ... + +# While technically covered by the last overload, spelling out the types for None and bool +# help mypy out in some tricky situations involving type context (aka bidirectional inference) @overload def getattr(__o: Any, name: Text, __default: None) -> Optional[Any]: ... @overload +def getattr(__o: Any, name: Text, __default: bool) -> Union[Any, bool]: ... +@overload def getattr(__o: Any, name: Text, __default: _T) -> Union[Any, _T]: ... def globals() -> Dict[str, Any]: ... def hasattr(__obj: Any, __name: Text) -> bool: ... diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 752755d2b..761307956 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -1021,9 +1021,14 @@ class filter(Iterator[_T], Generic[_T]): def format(__value: object, __format_spec: str = ...) -> str: ... # TODO unicode @overload def getattr(__o: Any, name: str) -> Any: ... + +# While technically covered by the last overload, spelling out the types for None and bool +# help mypy out in some tricky situations involving type context (aka bidirectional inference) @overload def getattr(__o: Any, name: str, __default: None) -> Optional[Any]: ... @overload +def getattr(__o: Any, name: str, __default: bool) -> Union[Any, bool]: ... +@overload def getattr(__o: Any, name: str, __default: _T) -> Union[Any, _T]: ... def globals() -> Dict[str, Any]: ... def hasattr(__obj: Any, __name: str) -> bool: ...