Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add regression tests for builtins.pow and object.__reduce__ #7663

Merged
merged 17 commits into from
Apr 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion pyrightconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"typeshedPath": ".",
"include": [
"stdlib",
"stubs"
"stubs",
"test_cases"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Do we really want this to be in both pyrightconfigs?
  • Does mypy support assert_type() yet? If it does, we could instead point mypy_primer at typeshed's test_cases. That way we would know if a PR to mypy breaks the tests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I don't really understand how the two pyrightconfigs work with each other ¯\_(ツ)_/¯. Happy to have it in only one if that's better.
  • No, mypy doesn't support assert_type yet. The PR was recently merged, and might make it into 0.950, but also might not. See Release 0.950 planning mypy#12579 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mypy supports assert_type() on master (I added it last week). I am hoping to convince Jukka to put it in the upcoming 0.950 release. We should make mypy run on this directory too as soon as 0.950 is released, or use master if we're feeling brave.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: assert_type has been cherry-picked onto the 0.950 branch, so we should be able to point mypy_primer at this directory as soon as 0.950 is released.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully we can just run mypy regularly, no need to use mypy-primer.

],
"exclude": [
"**/@python2"
Expand Down
3 changes: 2 additions & 1 deletion pyrightconfig.stricter.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"typeshedPath": ".",
"include": [
"stdlib",
"stubs"
"stubs",
"test_cases"
],
"exclude": [
"**/@python2",
Expand Down
24 changes: 24 additions & 0 deletions test_cases/README.md
Original file line number Diff line number Diff line change
@@ -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.
Comment on lines +3 to +5
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the long term we should probably also allow test that fail a type checker to be able to test the negative case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. Once we're running mypy on this directory, we can do that by # type: ignoring (with specific error codes) lines that we want to fail and running mypy with --warn-unused-ignores. We can't use that flag globally when running mypy on typeshed, but we should be able to use it for this directory.


**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.
11 changes: 11 additions & 0 deletions test_cases/stdlib/builtins/test_object.py
Original file line number Diff line number Diff line change
@@ -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
40 changes: 40 additions & 0 deletions test_cases/stdlib/builtins/test_pow.py
Original file line number Diff line number Diff line change
@@ -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(<smallint>, <smallint>, <smallint>)
assert_type(pow(2, 35, 3), int) # pow(<smallint>, <bigint>, <smallint>)
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(<pos-float>, <pos-or-neg-float>) -> float
# pow(<neg-float>, <pos-or-neg-float>) -> 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)