From fe8f001130440550da886ca4bc9810bdd0ac9e4c Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Fri, 21 May 2021 16:48:31 -0700 Subject: [PATCH 1/2] builtins: add an overload for bool 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 | 4 ++++ stdlib/@python2/builtins.pyi | 4 ++++ stdlib/builtins.pyi | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/stdlib/@python2/__builtin__.pyi b/stdlib/@python2/__builtin__.pyi index b7b68bbb7844..0476e4707370 100644 --- a/stdlib/@python2/__builtin__.pyi +++ b/stdlib/@python2/__builtin__.pyi @@ -863,9 +863,13 @@ 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 b7b68bbb7844..0476e4707370 100644 --- a/stdlib/@python2/builtins.pyi +++ b/stdlib/@python2/builtins.pyi @@ -863,9 +863,13 @@ 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 865c6e9a12d7..26c27944ca9f 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -1021,9 +1021,13 @@ 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: ... From 64397aae8c245dd4adda2cd4eb59cbadb67402f6 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Fri, 21 May 2021 16:55:57 -0700 Subject: [PATCH 2/2] blacken --- stdlib/@python2/__builtin__.pyi | 1 + stdlib/@python2/builtins.pyi | 1 + stdlib/builtins.pyi | 1 + 3 files changed, 3 insertions(+) diff --git a/stdlib/@python2/__builtin__.pyi b/stdlib/@python2/__builtin__.pyi index 0476e4707370..0b2c89e8d80c 100644 --- a/stdlib/@python2/__builtin__.pyi +++ b/stdlib/@python2/__builtin__.pyi @@ -863,6 +863,7 @@ 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 diff --git a/stdlib/@python2/builtins.pyi b/stdlib/@python2/builtins.pyi index 0476e4707370..0b2c89e8d80c 100644 --- a/stdlib/@python2/builtins.pyi +++ b/stdlib/@python2/builtins.pyi @@ -863,6 +863,7 @@ 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 diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 26c27944ca9f..8b45df95a266 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -1021,6 +1021,7 @@ 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