Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Support narrowing unions that include type[None].#16315

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
hauntsaninja merged 7 commits intopython:masterfromtyralla:fix/narrow_nonetype
Jan 14, 2024

Conversation

@tyralla
Copy link
Collaborator

Fixes#16279

See my comment in the referenced issue.

@github-actions

This comment has been minimized.

@tyralla
Copy link
CollaboratorAuthor

The primer's results show that the proposed changes also have other benefits. However, I have no idea what the failed mypyc runtime test is about. (I have no experience with Mypyc, so any hint is welcome.)

@JelleZijlstra
Copy link
Member

The mypyc failure is likely spurious; it's been failing randomly for some time. I retriggered the job.

@tyralla
Copy link
CollaboratorAuthor

Yes, you were right, thanks!

NoneType_ = type(None)

def f(cls: Type[Union[None, int]]) -> None:
if issubclass(cls, NoneType_):

Choose a reason for hiding this comment

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

One case is still broken, I believe: (python3.10+)

if issubclass(cls, types.Nonetype)

Copy link
CollaboratorAuthor

Choose a reason for hiding this comment

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

You are right. The definition in types.pyi is not helpful. I assumed something similar to mentioned test:

NoneType=type(None)

But it is:

@finalclassNoneType:def__bool__(self)->Literal[False]: ...

My suggestion is to letExpressionChecker.analyze_ref_expr directly returnTypeType(NoneType()) when it encounters the full name "types.NoneType". (already pushed)

@github-actions

This comment has been minimized.

@tyralla
Copy link
CollaboratorAuthor

The new unreachable error for clinic.py also seems correct because neitherbool norNoneType is an acceptable base type.

@AlexWaygood
Copy link
Member

AlexWaygood commentedOct 25, 2023
edited
Loading

The new unreachable error for clinic.py also seems correct because neitherbool norNoneType is an acceptable base type.

The clinic code in question is here:https://github.com/python/cpython/blob/1262e41842957c3b402fc0cf0a6eb2ea230c828f/Tools/clinic/clinic.py#L5828-L5831

I agree that theclinic error is fine, but for a different reason to the one you gave ;)

It looks to me like there's a bug in the annotations forclinic.py. If I apply this diff toclinic.py:

diff --git a/Tools/clinic/clinic.py b/Tools/clinic/clinic.pyindex 5dd7900851..51964fb38e 100755--- a/Tools/clinic/clinic.py+++ b/Tools/clinic/clinic.py@@ -5840,6 +5840,7 @@ def bad_node(self, node: ast.AST) -> None:                         value = unknown                 else:                     value = ast.literal_eval(expr)+                    reveal_type(value)                     py_default = repr(value)                     if isinstance(value, (bool, NoneType)):                         c_default = "Py_" + py_default

And then runmypy --config-file Tools/clinic/mypy.ini, mypy reports (both using mypy 1.6 and using your PR branch):

Tools\clinic\clinic.py:5843: note: Revealed type is "Union[clinic.Sentinels, clinic.Null]"

That's because of an incorrect type declaration inclinic.py here:https://github.com/python/cpython/blob/1262e41842957c3b402fc0cf0a6eb2ea230c828f/Tools/clinic/clinic.py#L5719. The type for that variable should probably be declared asobject orAny, notSentinels | Null. So your PR is improving things there: mypyshould be reporting an error on that line for unreachable code with mypy 1.6, but isn't.

@tyralla
Copy link
CollaboratorAuthor

I agree that theclinic error is fine, but for a different reason to the one you gave ;)

Thanks for checking and confirming the error report is "true positive". But I see no contradiction between your and mine opinion (except that I definitely should have used more words; sorry for that).

Hm, I just wrote the following example to explain my thinking (the note and error messages are generated by Mypy 1.6):

fromtypingimportfinalclassNull: ...@finalclassNoneType1: ...classNoneType2: ...classImpossible(Null,NoneType1): ...# error: Cannot inherit from final class "NoneType"  [misc]  (right)classPossible(Null,NoneType2): ...x:Nullifisinstance(x,NoneType1):reveal_type(x)# note: Revealed type is "temp.<subclass of "Null" and "NoneType1">"  (wrong)ifisinstance(x,NoneType2):reveal_type(x)# note: Revealed type is "temp.<subclass of "Null" and "NoneType2">"  (right)

I intended to show that the unreachable warning is only correct for final types. (I somehow definedNoneType to be final in my pull request by setting aupper_bound attribute to False somewhere.) But now I see that Mypy understands that combiningNull andNoneType1 is impossible due toNoneType1 being final, but still assumes such an impossible subtype can exist when doing type narrowing.

So, either I am confused, or this example reveals another Mypy limitation (that could possibly be easily fixed in this pull request as well).

@tyralla
Copy link
CollaboratorAuthor

So, either I am confused, or this example reveals another Mypy limitation (that could possibly be easily fixed in this pull request as well).

already reported here:#15148

AlexWaygood reacted with thumbs up emoji

@tyralla
Copy link
CollaboratorAuthor

So, either I am confused, or this example reveals another Mypy limitation (that could possibly be easily fixed in this pull request as well).

I decided to open#16330. So, in my opinion, the pull request here is ready.

AlexWaygood reacted with thumbs up emoji

@AlexWaygood
Copy link
Member

I decided to open#16330. So, in my opinion, the pull request here is ready.

Yeah, wise to defer that to another PR, imo!

@AlexWaygood
Copy link
Member

@tyralla, looks like there might be some merge conflicts here now — think you'd be able to merge inmaster and fix them? :)

# Conflicts:#test-data/unit/check-narrowing.test
@tyralla
Copy link
CollaboratorAuthor

@AlexWaygood No big deal; just two tests inserted at the same place.

AlexWaygood reacted with heart emoji

@github-actions

This comment has been minimized.

@AlexWaygood
Copy link
Member

CPython (Argument Clinic) (https://github.com/python/cpython)- Tools/clinic/clinic.py:5903: error: Subclass of "Sentinels" and "bool" cannot exist: "bool" is final  [unreachable]- Tools/clinic/clinic.py:5903: error: Subclass of "Sentinels" and "NoneType" cannot exist: "NoneType" is final  [unreachable]- Tools/clinic/clinic.py:5903: error: Subclass of "Null" and "bool" cannot exist: "bool" is final  [unreachable]- Tools/clinic/clinic.py:5903: error: Subclass of "Null" and "NoneType" cannot exist: "NoneType" is final  [unreachable]

Hmm, any idea why these errors are going away? I see mypy still emits anerror: Statement is unreachable [unreachable] error on line 5904 ofclinic.py (following#16330). But the error messages that are going away here are IMO more helpful in figuring out what the actual error is in theclinic.py code

@tyralla
Copy link
CollaboratorAuthor

Yes, something is still missing in this pull request. Smaller repro:

fromtypesimportNoneTypefromtypingimportfinalclassX: ...classY: ...@finalclassZ: ...x:Xifisinstance(x, (Y,Z)):reveal_type(x)# N: note: Revealed type is "__main__.<subclass of "X" and "Y">" (right)ifisinstance(x, (Y,NoneType)):reveal_type(x)# E: Statement is unreachable (wrong)

I will have a look at it later.

…oneType` and modify (fix?) the second algorithm tried in `conditional_types_with_intersection`.
@github-actions

This comment has been minimized.

@github-actions
Copy link
Contributor

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

alerta (https://github.com/alerta/alerta)+ alerta/models/alert.py:38: error: Unused "type: ignore" comment  [unused-ignore]discord.py (https://github.com/Rapptz/discord.py)- discord/app_commands/transformers.py:729: error: Dict entry 0 has incompatible type "AppCommandOptionType": "tuple[type[str], <typing special form>]"; expected "AppCommandOptionType": "tuple[type[Any], ...]"  [dict-item]- discord/app_commands/transformers.py:730: error: Dict entry 1 has incompatible type "AppCommandOptionType": "tuple[type[int], <typing special form>]"; expected "AppCommandOptionType": "tuple[type[Any], ...]"  [dict-item]- discord/app_commands/transformers.py:731: error: Dict entry 2 has incompatible type "AppCommandOptionType": "tuple[type[bool], <typing special form>]"; expected "AppCommandOptionType": "tuple[type[Any], ...]"  [dict-item]- discord/app_commands/transformers.py:732: error: Dict entry 3 has incompatible type "AppCommandOptionType": "tuple[type[float], <typing special form>]"; expected "AppCommandOptionType": "tuple[type[Any], ...]"  [dict-item]- discord/app_commands/transformers.py:739: error: Incompatible default for argument "_none" (default has type "<typing special form>", argument has type "type")  [assignment]- discord/app_commands/commands.py:235: error: Incompatible default for argument "_none" (default has type "<typing special form>", argument has type "type")  [assignment]
AlexWaygood reacted with hooray emoji

@tyralla
Copy link
CollaboratorAuthor

@AlexWaygood This has been ready for a while now. Can you merge it, or is there anything left to do?

@AlexWaygood
Copy link
Member

@AlexWaygood This has been ready for a while now. Can you merge it, or is there anything left to do?

I'm not a maintainer, just a triager, I'm afraid, so I can review but I can't merge :/ I'm also afraid I'm unusually busy at the moment, so I probably won't be able to take another look at this soon :(

@tyralla
Copy link
CollaboratorAuthor

Ah, okay. I didn't know Mypy has triagers (to be honest, I didn't even know that "triager" is an English word...).

So, this means this pull request has to wait until you find time to finish your review and give the maintainers your okay? (No need for a rush; I just wanted to make sure this won't be forgotten.)

AlexWaygood reacted with thumbs up emoji

@AlexWaygood
Copy link
Member

AlexWaygood commentedJan 9, 2024
edited
Loading

So, this means this pull request has to wait until you find time to finish your review and give the maintainers your okay? (No need for a rush; I just wanted to make sure this won't be forgotten.)

Not necessarily; it can be merged as soon as a maintainer approves it. That's maybeslightly more likely to happen if a triager approves it first, but it's very marginal — most PRs at mypy are just reviewed by a maintainer before being merged, as we actually have more maintainers than triagers. But as with most open-source projects, there aren't enough reviewers, so it can unfortunately take some time sometimes :)

Copy link
Collaborator

@hauntsaninjahauntsaninja left a comment

Choose a reason for hiding this comment

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

Nice, thank you for the improvement!

AlexWaygood reacted with heart emoji
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@hauntsaninjahauntsaninjahauntsaninja approved these changes

+1 more reviewer
Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Labels

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

can't narrow a union of type[None]

4 participants

@tyralla@JelleZijlstra@AlexWaygood@hauntsaninja

[8]ページ先頭

©2009-2025 Movatter.jp