diff --git a/pyrightconfig.json b/pyrightconfig.json index 3d35f28a7250..8bcc7aa96657 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -2,7 +2,8 @@ "typeshedPath": ".", "include": [ "stdlib", - "stubs" + "stubs", + "test_cases" ], "exclude": [ "**/@python2" diff --git a/pyrightconfig.stricter.json b/pyrightconfig.stricter.json index 55eea79bf374..2f41cc1deedc 100644 --- a/pyrightconfig.stricter.json +++ b/pyrightconfig.stricter.json @@ -3,7 +3,8 @@ "typeshedPath": ".", "include": [ "stdlib", - "stubs" + "stubs", + "test_cases" ], "exclude": [ "**/@python2", diff --git a/test_cases/README.md b/test_cases/README.md new file mode 100644 index 000000000000..070262fd5f23 --- /dev/null +++ b/test_cases/README.md @@ -0,0 +1,24 @@ +## Regression tests for typeshed + +This directory contains regression tests for the stubs found elsewhere in the +typeshed repo. Each file contains a number of test cases, all of which should +pass a type checker without error. + +**This directory should *only* contain tests for functions and classes which +are known to have caused problems in the past, where the stubs are difficult to +get right.** 100% test coverage for typeshed is neither necessary nor +desirable, as it would lead to code duplication. Moreover, typeshed has +multiple other mechanisms for spotting errors in the stubs. + +Unlike the rest of typeshed, this directory largely contains `.py` files. This +is because the purpose of this folder is to test the implications of typeshed +changes for end users. + +Another difference to the rest of typeshed is that the test cases in this +directory cannot always use modern syntax for type hints. For example, PEP 604 +syntax (unions with a pipe `|` operator) is new in Python 3.10. While this +syntax can be used on older Python versions in a `.pyi` file, code using this +syntax will fail at runtime on Python <=3.9. Since the test cases all use `.py` +extensions, and since the tests need to pass on all Python versions >=3.6, PEP +604 syntax cannot be used in a test case. Use `typing.Union` and +`typing.Optional` instead. diff --git a/test_cases/stdlib/builtins/test_object.py b/test_cases/stdlib/builtins/test_object.py new file mode 100644 index 000000000000..f2b56e4e4569 --- /dev/null +++ b/test_cases/stdlib/builtins/test_object.py @@ -0,0 +1,11 @@ +from typing import Any, Tuple, Union + + +# The following should pass without error (see #6661): +class Diagnostic: + def __reduce__(self) -> Union[str, Tuple[Any, ...]]: + res = super().__reduce__() + if isinstance(res, tuple) and len(res) >= 3: + res[2]["_info"] = 42 + + return res diff --git a/test_cases/stdlib/builtins/test_pow.py b/test_cases/stdlib/builtins/test_pow.py new file mode 100644 index 000000000000..c20ab76d70b7 --- /dev/null +++ b/test_cases/stdlib/builtins/test_pow.py @@ -0,0 +1,40 @@ +from decimal import Decimal +from fractions import Fraction +from typing import Any, NoReturn +from typing_extensions import Literal, assert_type + +assert_type(pow(1, 0), Literal[1]) # See #7163 +assert_type(pow(1, 0, None), Literal[1]) # See #7163 +assert_type(pow(2, 4, 0), NoReturn) +assert_type(pow(2, 4), int) +assert_type(pow(4, 6, None), int) +assert_type(pow(5, -7), float) +assert_type(pow(2, 4, 5), int) # pow(, , ) +assert_type(pow(2, 35, 3), int) # pow(, , ) +assert_type(pow(4.6, 8), float) +assert_type(pow(5.1, 4, None), float) +assert_type(pow(complex(6), 6.2), complex) +assert_type(pow(complex(9), 7.3, None), complex) +assert_type(pow(Fraction(), 4, None), Fraction) +assert_type(pow(Fraction(3, 7), complex(1, 8)), complex) +assert_type(pow(complex(4, -8), Fraction(2, 3)), complex) +assert_type(pow(Decimal("1.0"), Decimal("1.6")), Decimal) +assert_type(pow(Decimal("1.0"), Decimal("1.0"), Decimal("1.0")), Decimal) +assert_type(pow(Decimal("4.6"), 7, None), Decimal) + +# These would ideally be more precise, but `Any` is acceptable +# They have to be `Any` due to the fact that type-checkers can't distinguish between positive and negative numbers for the second argument to `pow()` +# +# int for positive 2nd-arg, float otherwise +assert_type(pow(4, 65), Any) +assert_type(pow(2, -45), Any) +assert_type(pow(3, 57, None), Any) +# pow(, ) -> float +# pow(, ) -> complex +assert_type(pow(4.7, 7.4), Any) +assert_type(pow(-9.8, 8.3), Any) +assert_type(pow(-9.3, -88.2), Any) +assert_type(pow(8.2, -9.8), Any) +assert_type(pow(4.7, 9.2, None), Any) +# See #7046 -- float for a positive 1st arg, complex otherwise +assert_type((-2) ** 0.5, Any)