Handle arg=<sentinel value> in stubgen - #22019
edgarrmondragon wants to merge 8 commits into
Conversation
9afa235 to
45e6b87
Compare
Incomplete
JelleZijlstra
left a comment
There was a problem hiding this comment.
This is only stubgenc, should we do something similar for regular stubgen?
It seems that it's handled by stubgenc in the Lines 1811 to 1820 in dc8858f I've added both a |
|
@JukkaL @p-sawicki It looks like |
| import typing_extensions | ||
| from _typeshed import Incomplete | ||
|
|
||
| _MISSING: typing_extensions.sentinel |
There was a problem hiding this comment.
This should be emitted as _MISSING = typing_extensions.sentinel("_MISSING"). Type checkers are not expected to understand this form as a sentinel declaration.
There was a problem hiding this comment.
Yeah, let me get this back to draft.
There was a problem hiding this comment.
Ready for another review. The sentinel object is now assigned instead of annotated. The only edge case where I wasn't able to do it is when the sentinel used a default value is created with a __name__ that is not a valid identifier. For example
MY_SENTINEL = sentinel('not an identifier')I might be able to do it with vars(...) on the __module__ attribute, but I think that's thinking it too hard for a way to declare sentinels that I believe would be discouraged anyway.
c0d704b to
4adf0b0
Compare
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez-Mondragón <edgarrm358@gmail.com>
Signed-off-by: Edgar Ramírez-Mondragón <edgarrm358@gmail.com>
1bb8e19 to
786dc62
Compare
Signed-off-by: Edgar Ramírez-Mondragón <edgarrm358@gmail.com>
4613f18 to
d87772b
Compare
There was a problem hiding this comment.
Thanks! I had Astra take a look and got these review findings:
-
[P2] Sentinel names aren’t necessarily usable type references — lines 570–571 For
MISSING = sentinel("missing"), the stub declaresMISSINGbut annotates defaults withIncomplete | missing, producing an undefined-name error. Class-attribute sentinels also produce invalid type references because their declarations remainClassVar[sentinel]. Verify that the reference resolves to a generated sentinel declaration, or fall back toIncomplete. -
[P2] Aliases become distinct sentinel types — line 953. Given
MISSING = sentinel("MISSING"); ALIAS = MISSING, both names get independentsentinel(...)declarations. Consequently, mypy rejectsvalue: MISSING = ALIAS, although they are the same runtime object. Preserve aliases by tracking sentinel identity. -
[P2] Keyword names crash generation — line 570.
"in".isidentifier()returns true, so a default created withsentinel("in")produces an annotation that raises an uncaughtSyntaxError. Reject keywords as well as non-identifiers.
I think these are all pretty marginal, and fixing them would likely be complex. I'm OK shipping this version and making further enhancements later as necessary.
Yeah,
Similar to the above, but much easier to address: edgarrmondragon#1.
Also easy to address: edgarrmondragon#1.
Doable, but I think it'd require stubgen to keep track of all sentinel declarations (by hash maybe?) |
Incomplete
mypy was generating stubs like
def test(self, arg0: sentinel = ...) -> None: ..., where thesentinelannotation isn't really helpful.Related:
sentineldefaults, but notobject()markers #22013 (comment)