From 7b02272fce6ebe23a82e621433dfba954bb8183e Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Tue, 13 Jun 2017 19:08:16 +0300 Subject: [PATCH] PY-23707 Fixed: False positives for __new__ arguments of some builtin classes Add `__new__` to `str` and `int` stubs in both Pythons. Update default values to `...` in `__init__` and `__new__` in `int` and `str`. Add `__new__` to `enum.IntEnum` to override inherited `__new__`. --- .../helpers/typeshed/stdlib/2/__builtin__.pyi | 13 +++++-- python/helpers/typeshed/stdlib/3.4/enum.pyi | 5 ++- python/helpers/typeshed/stdlib/3/builtins.pyi | 21 ++++++++-- .../helpers/typeshed/third_party/2/enum.pyi | 7 ++-- .../typeshed/stdlib/2/builtins_test.py | 36 ++++++++++++++++++ .../typeshed/stdlib/3/builtins_test.py | 38 +++++++++++++++++++ 6 files changed, 108 insertions(+), 12 deletions(-) diff --git a/python/helpers/typeshed/stdlib/2/__builtin__.pyi b/python/helpers/typeshed/stdlib/2/__builtin__.pyi index 3a79fcb1662d..c006cecac75a 100644 --- a/python/helpers/typeshed/stdlib/2/__builtin__.pyi +++ b/python/helpers/typeshed/stdlib/2/__builtin__.pyi @@ -88,11 +88,15 @@ class type(object): class int(SupportsInt, SupportsFloat, SupportsAbs[int]): @overload - def __init__(self) -> None: ... + def __init__(self, x: SupportsInt = ...) -> None: ... @overload - def __init__(self, x: SupportsInt) -> None: ... + def __init__(self, x: Union[str, unicode, bytearray], base: int = ...) -> None: ... + @overload - def __init__(self, x: Union[str, unicode, bytearray], base: int = 10) -> None: ... + def __new__(cls: Type[_T1], x: SupportsInt = ...) -> _T1: ... + @overload + def __new__(cls: Type[_T1], x: Union[str, unicode, bytearray], base: int = ...) -> _T1: ... + def bit_length(self) -> int: ... def __add__(self, x: int) -> int: ... @@ -309,7 +313,8 @@ class unicode(basestring, Sequence[unicode]): def __hash__(self) -> int: ... class str(basestring, Sequence[str]): - def __init__(self, object: object='') -> None: ... + def __init__(self, object: object = ...) -> None: ... + def __new__(cls: Type[_T1], object: object = ...) -> _T1: ... def capitalize(self) -> str: ... def center(self, width: int, fillchar: str = ...) -> str: ... def count(self, x: unicode, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... diff --git a/python/helpers/typeshed/stdlib/3.4/enum.pyi b/python/helpers/typeshed/stdlib/3.4/enum.pyi index 3b97e1be8337..5eb09b2b4019 100644 --- a/python/helpers/typeshed/stdlib/3.4/enum.pyi +++ b/python/helpers/typeshed/stdlib/3.4/enum.pyi @@ -17,8 +17,11 @@ class Enum: name = ... # type: str value = ... # type: Any -class IntEnum(int, Enum): +_T1 = TypeVar('_T1') + +class IntEnum(int, Enum): # type: ignore value = ... # type: int + def __new__(cls: Type[_T1], value: Any) -> _T1: ... _T = TypeVar('_T') diff --git a/python/helpers/typeshed/stdlib/3/builtins.pyi b/python/helpers/typeshed/stdlib/3/builtins.pyi index a9d31f5e1b41..7c46b8986c36 100644 --- a/python/helpers/typeshed/stdlib/3/builtins.pyi +++ b/python/helpers/typeshed/stdlib/3/builtins.pyi @@ -103,7 +103,16 @@ class super: def __init__(self) -> None: ... class int(SupportsInt, SupportsFloat, SupportsAbs[int]): - def __init__(self, x: Union[SupportsInt, str, bytes] = ..., base: int = ...) -> None: ... + @overload + def __init__(self, x: SupportsInt = ...) -> None: ... + @overload + def __init__(self, x: Union[str, bytes], base: int = ...) -> None: ... + + @overload + def __new__(cls: Type[_T1], x: SupportsInt = ...) -> _T1: ... + @overload + def __new__(cls: Type[_T1], x: Union[str, bytes], base: int = ...) -> _T1: ... + def bit_length(self) -> int: ... def to_bytes(self, length: int, byteorder: str, *, signed: bool = ...) -> bytes: ... @classmethod @@ -227,11 +236,15 @@ class complex(SupportsAbs[float]): class str(Sequence[str]): @overload - def __init__(self) -> None: ... + def __init__(self, o: object = ...) -> None: ... @overload - def __init__(self, o: object) -> None: ... + def __init__(self, o: bytes, encoding: str = ..., errors: str = ...) -> None: ... + @overload - def __init__(self, o: bytes, encoding: str = ..., errors: str = 'strict') -> None: ... + def __new__(cls: Type[_T1], o: object = ...) -> _T1: ... + @overload + def __new__(cls: Type[_T1], o: bytes, encoding: str = ..., errors: str = ...) -> _T1: ... + def capitalize(self) -> str: ... def center(self, width: int, fillchar: str = ' ') -> str: ... def count(self, x: str, __start: Optional[int] = ..., __end: Optional[int] = ...) -> int: ... diff --git a/python/helpers/typeshed/third_party/2/enum.pyi b/python/helpers/typeshed/third_party/2/enum.pyi index 4032e818b80c..47f89900f8a9 100644 --- a/python/helpers/typeshed/third_party/2/enum.pyi +++ b/python/helpers/typeshed/third_party/2/enum.pyi @@ -1,4 +1,4 @@ -from typing import List, Any, TypeVar +from typing import List, Any, TypeVar, Type class Enum: def __new__(cls, value: Any) -> None: ... @@ -12,8 +12,9 @@ class Enum: name = ... # type: str value = ... # type: Any -class IntEnum(int, Enum): ... - _T = TypeVar('_T') +class IntEnum(int, Enum): # type: ignore + def __new__(cls: Type[_T], value: Any) -> _T: ... + def unique(enumeration: _T) -> _T: ... diff --git a/python/testData/typeshed/stdlib/2/builtins_test.py b/python/testData/typeshed/stdlib/2/builtins_test.py index d1b446d5418c..7aab7b32c1a8 100644 --- a/python/testData/typeshed/stdlib/2/builtins_test.py +++ b/python/testData/typeshed/stdlib/2/builtins_test.py @@ -162,6 +162,42 @@ def test_staticmethod(): assert set(staticmethod.__dict__.keys()) == {'__init__', '__new__', '__func__', '__get__', '__getattribute__', '__doc__'} +def test_str_init_new(): + class A: + def __str__(self): + return "A" + + assert str.__new__(str) is not None + assert str.__new__(str, A()) is not None + assert str.__new__(str, b"foo") is not None + assert str.__new__(str, u"foo") is not None + + assert str() is not None + assert str(A()) is not None + assert str(b"foo") is not None + assert str(u"foo") is not None + + +def test_int_init_new(): + class A: + def __int__(self): + return 5 + + assert int.__new__(int) is not None + assert int.__new__(int, A()) is not None + assert int.__new__(int, u"100") is not None + assert int.__new__(int, b"100") is not None + assert int.__new__(int, u"100", 2) is not None + assert int.__new__(int, b"100", 2) is not None + + assert int() is not None + assert int(A()) is not None + assert int(u"100") is not None + assert int(b"100") is not None + assert int(u"100", 2) is not None + assert int(b"100", 2) is not None + + def test_dict_update(): d = {} d.update({"k1": 1, "v1": 1}) diff --git a/python/testData/typeshed/stdlib/3/builtins_test.py b/python/testData/typeshed/stdlib/3/builtins_test.py index bf830ab7a72c..70c2b36a0305 100644 --- a/python/testData/typeshed/stdlib/3/builtins_test.py +++ b/python/testData/typeshed/stdlib/3/builtins_test.py @@ -179,6 +179,44 @@ def test_staticmethod(): '__dict__', '__doc__'} +def test_str_init_new(): + class A: + def __str__(self): + return "A" + + assert str.__new__(str) is not None + assert str.__new__(str, A()) is not None + assert str.__new__(str, b"foo") is not None + assert str.__new__(str, b"foo", "utf-8") is not None + assert str.__new__(str, b"foo", "utf-8", "strict") is not None + + assert str() is not None + assert str(A()) is not None + assert str(b"foo") is not None + assert str(b"foo", "utf-8") is not None + assert str(b"foo", "utf-8", "strict") is not None + + +def test_int_init_new(): + class A: + def __int__(self): + return 5 + + assert int.__new__(int) is not None + assert int.__new__(int, A()) is not None + assert int.__new__(int, u"100") is not None + assert int.__new__(int, b"100") is not None + assert int.__new__(int, u"100", 2) is not None + assert int.__new__(int, b"100", 2) is not None + + assert int() is not None + assert int(A()) is not None + assert int(u"100") is not None + assert int(b"100") is not None + assert int(u"100", 2) is not None + assert int(b"100", 2) is not None + + def test_dict_update(): d = {} d.update({"k1": 1, "v1": 1})