From 6008b9dbb14bd947e219f655c66a36a63a91c42e Mon Sep 17 00:00:00 2001 From: Roy Williams Date: Wed, 11 Jan 2017 15:36:32 -0800 Subject: [PATCH] Overload signature of `get` to return an Optional value and to allow default to take any type to match runtime behavior. This chage more closely matches the behavior of `get` at runtime. Users can pass whatever they want in to the default parameter and it will be returned if the key is absent. Additionally, `get` should return an `Optional` if called with only one parameter. ```python z = {'a': 22} reveal_type(z.get('b')) reveal_type(z.get('b', 22)) reveal_type(z.get('b', 'hello')) ``` Before: ```shell test_get_default.py:2: error: Revealed type is 'builtins.int*' test_get_default.py:3: error: Revealed type is 'builtins.int*' test_get_default.py:4: error: Revealed type is 'builtins.int*' test_get_default.py:4: error: Argument 2 to "get" of "dict" has incompatible type "str"; expected "int" ``` After: ```shell test_get_default.py:2: error: Revealed type is 'Union[builtins.int*, builtins.None]' test_get_default.py:3: error: Revealed type is 'builtins.int' test_get_default.py:4: error: Revealed type is 'Union[builtins.int, builtins.str*]' ``` --- stdlib/2/__builtin__.pyi | 5 ++++- stdlib/2/typing.pyi | 8 +++++--- stdlib/3/builtins.pyi | 5 ++++- stdlib/3/typing.pyi | 6 ++++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/stdlib/2/__builtin__.pyi b/stdlib/2/__builtin__.pyi index e8d4ae079be9..d0e3ef6b0cb5 100644 --- a/stdlib/2/__builtin__.pyi +++ b/stdlib/2/__builtin__.pyi @@ -538,7 +538,10 @@ class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): def has_key(self, k: _KT) -> bool: ... def clear(self) -> None: ... def copy(self) -> Dict[_KT, _VT]: ... - def get(self, k: _KT, default: _VT = None) -> _VT: ... + @overload + def get(self, k: _KT) -> Optional[_VT]: ... + @overload + def get(self, k: _KT, default: _T) -> Union[_VT, _T]: ... def pop(self, k: _KT, default: _VT = ...) -> _VT: ... def popitem(self) -> Tuple[_KT, _VT]: ... def setdefault(self, k: _KT, default: _VT = ...) -> _VT: ... diff --git a/stdlib/2/typing.pyi b/stdlib/2/typing.pyi index 035f36eae5b8..f7a14d39043a 100644 --- a/stdlib/2/typing.pyi +++ b/stdlib/2/typing.pyi @@ -174,15 +174,17 @@ class ValuesView(MappingView, Iterable[_VT_co], Generic[_VT_co]): def __contains__(self, o: object) -> bool: ... def __iter__(self) -> Iterator[_VT_co]: ... -class Mapping(Sized, Iterable[_KT], Container[_KT], Generic[_KT, _VT_co]): +class Mapping(Iterable[_KT], Container[_KT], Sized, Generic[_KT, _VT_co]): # TODO: We wish the key type could also be covariant, but that doesn't work, # see discussion in https: //github.com/python/typing/pull/273. @abstractmethod def __getitem__(self, k: _KT) -> _VT_co: ... # Mixin methods - def get(self, k: _KT, default: _VT_co = ...) -> _VT_co: # type: ignore - ... + @overload # type: ignore + def get(self, k: _KT) -> Optional[_VT_co]: ... + @overload # type: ignore + def get(self, k: _KT, default: _T) -> Union[_VT_co, _T]: ... def keys(self) -> list[_KT]: ... def values(self) -> list[_VT_co]: ... def items(self) -> list[Tuple[_KT, _VT_co]]: ... diff --git a/stdlib/3/builtins.pyi b/stdlib/3/builtins.pyi index 7000ad5f7c98..87828bf52bf4 100644 --- a/stdlib/3/builtins.pyi +++ b/stdlib/3/builtins.pyi @@ -556,7 +556,10 @@ class dict(MutableMapping[_KT, _VT], Generic[_KT, _VT]): def __init__(self, iterable: Iterable[Tuple[_KT, _VT]], **kwargs: _VT) -> None: ... def clear(self) -> None: ... def copy(self) -> Dict[_KT, _VT]: ... - def get(self, k: _KT, default: _VT = None) -> _VT: ... + @overload + def get(self, k: _KT) -> Optional[_VT]: ... + @overload + def get(self, k: _KT, default: _T) -> Union[_VT, _T]: ... def pop(self, k: _KT, default: _VT = None) -> _VT: ... def popitem(self) -> Tuple[_KT, _VT]: ... def setdefault(self, k: _KT, default: _VT = None) -> _VT: ... diff --git a/stdlib/3/typing.pyi b/stdlib/3/typing.pyi index 099f92595b72..554852669f2d 100644 --- a/stdlib/3/typing.pyi +++ b/stdlib/3/typing.pyi @@ -250,8 +250,10 @@ class Mapping(Iterable[_KT], Container[_KT], Sized, Generic[_KT, _VT_co]): def __getitem__(self, k: _KT) -> _VT_co: ... # Mixin methods - def get(self, k: _KT, default: _VT_co = ...) -> _VT_co: # type: ignore - ... + @overload # type: ignore + def get(self, k: _KT) -> Optional[_VT_co]: ... + @overload # type: ignore + def get(self, k: _KT, default: _T) -> Union[_VT_co, _T]: ... def items(self) -> AbstractSet[Tuple[_KT, _VT_co]]: ... def keys(self) -> AbstractSet[_KT]: ... def values(self) -> ValuesView[_VT_co]: ...