KEMBAR78
Implement TypeIs (PEP 742) by JelleZijlstra · Pull Request #16898 · python/mypy · GitHub
Skip to content

Conversation

JelleZijlstra
Copy link
Member

Cross-ref python/peps#3649.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@JelleZijlstra JelleZijlstra marked this pull request as ready for review February 11, 2024 04:40
return {expr: TypeGuardedType(node.callee.type_guard)}, {}
else:
assert node.callee.type_is is not None
return conditional_types_to_typemaps(
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the crucial part of the change, which implements the new type narrowing behavior. It's the same as isinstance(), a little way up in the same method.

@github-actions

This comment has been minimized.

Copy link
Collaborator

@cdce8p cdce8p left a comment

Choose a reason for hiding this comment

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

Just a small disclaimer, this is the first bigger mypy PR I reviewed 😅

Overall it looks solid. Left a few minor comments.

Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
@JelleZijlstra
Copy link
Member Author

Thanks for the review! I applied the suggestions, and will deal with the larger issues in the next few days.

@github-actions

This comment has been minimized.

@cdce8p
Copy link
Collaborator

cdce8p commented Feb 23, 2024

Missed commenting on the PR title earlier. Could you update it to mention TypeIs instead?

@JelleZijlstra JelleZijlstra changed the title Implement TypeNarrower (PEP 742) Implement TypeIs (PEP 742) Feb 23, 2024
@github-actions

This comment has been minimized.

Copy link
Member

@sobolevn sobolevn left a comment

Choose a reason for hiding this comment

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

Very impressive work, thank you! 👏

)

TYPE_NARROWER_NOT_SUBTYPE: Final[ErrorCode] = ErrorCode(
"type-is-not-subtype",
Copy link
Member

Choose a reason for hiding this comment

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

I propose type-narrower-not-subtype, right now this error code can be misleading for readers: type is not a subtype?

It would be consistent with:

TYPE_NARROWER_NOT_SUBTYPE: Final = ErrorMessage(
    "Narrowed type {} is not a subtype of input type {}", codes.TYPE_NARROWER_NOT_SUBTYPE
)

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe narrowed-type-not-subtype? Your suggestion sounds like TypeNarrower, which was a rejected name for teh feature.

g(reveal_type(x)) # N: Revealed type is "Union[builtins.list[builtins.str], __main__.<subclass of "list" and "A">]"
[builtins fixtures/tuple.pyi]

[case testTypeIsMultipleCondition-xfail]
Copy link
Member

Choose a reason for hiding this comment

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

Can you please add a comment on why this is marked as xfail?

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 copied this from the TypeGuard test. Seems like the xfail is just because we generate a name with an extra 1 at the end, which looks like a typo:

Expected:
  main:16: note: Revealed type is "__main__.<subclass of "Foo" and "Bar">"
  main:21: note: Revealed type is "__main__.<subclass of "Foo" and "Bar">" (diff)
Actual:
  main:16: note: Revealed type is "__main__.<subclass of "Foo" and "Bar">"
  main:21: note: Revealed type is "__main__.<subclass of "Foo" and "Bar">1" (diff)

I will remove the xfail and make it pass.

from typing import Callable, List, TypeVar
from typing_extensions import TypeIs

A = Callable[[object], TypeIs[List[T]]]
Copy link
Member

Choose a reason for hiding this comment

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

T is not defined, why does this test pass?

Choose a reason for hiding this comment

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

This is a general issue with test cases that I've seen in other tests as well. I'm not sure if T is coming from the builtins stubs or whatever else. If you are really interested I could quickly try and search where this has happened.

Obviously still good to point it out and change it here.

Choose a reason for hiding this comment

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

I think the root cause of this is that a normal builtins.pyi in typeshed defined _T (which does not get exported) wheres the test fixtures (like dict.pyi) typically use stuff like T (which does get exported).

It would probably be a good idea to change all fixtures, but that might be quite a bit of work.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added an explicit definition of T in this test. Agree that ideally we should fix this throughout the test suite.

@sobolevn
Copy link
Member

And don't forget to add a new code to https://github.com/python/mypy/blob/master/test-data/unit/check-errorcodes.test

@JelleZijlstra
Copy link
Member Author

Thanks @sobolevn! I have pushed some changes to address your review.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 1, 2024

Diff from mypy_primer, showing the effect of this PR on open source code:

graphql-core (https://github.com/graphql-python/graphql-core)
+ src/graphql/execution/execute.py:638: error: Unused "type: ignore" comment  [unused-ignore]


template_ret_type, cactual_ret_type = template.ret_type, cactual.ret_type
if template.type_guard is not None:
if template.type_guard is not None and cactual.type_guard is not None:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice, thanks! I think this should fix a thing I ran into while testing #16939

Copy link
Member

@sobolevn sobolevn left a comment

Choose a reason for hiding this comment

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

Thanks again, one last suggestion: we can add a test case to check-incremental to ensure that cache works correctly for type narrowing. Especially, because TypeGuard is also missing from there: https://github.com/python/mypy/blob/master/test-data/unit/check-incremental.test

@JelleZijlstra
Copy link
Member Author

Thanks! I'll work on a separate PR with incremental tests for both TypeGuard and TypeIs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants