Bug Report
Sentinel loses type information when reassigned.
To Reproduce
# mre1.py (fails)
from typing_extensions import Sentinel
MISSING = Sentinel("MISSING")
ALIAS = MISSING
x: ALIAS | int = ALIAS
https://mypy-play.net/?mypy=master&python=3.12&gist=6d4045b697ab57c41bfeecb59233db76
$ mypy mre1.py
mre1.py:6: error: Variable "mre1.ALIAS" is not valid as a type [valid-type]
mre1.py:6: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
Found 1 error in 1 file (checked 1 source file)
This call was made in #21647 (comment).
Expected Behavior
mre1.py should type-check the same way mre2.py does. ALIAS is assigned directly from MISSING, so it should be recognized as the same sentinel.
Actual Behavior
$ mypy mre1.py
mre1.py:6: error: Variable "mre1.ALIAS" is not valid as a type [valid-type]
mre1.py:6: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
Found 1 error in 1 file (checked 1 source file)
Your Environment
- Mypy version used: mypy 2.4.0+dev (master)
- Mypy command-line flags: (none)
- Mypy configuration options from
mypy.ini (and other config files): (none)
- Python version used: 3.15
Additional Context
This came up because Pydantic 2.14.0b2 re-exports its MISSING sentinel from pydantic_core as pydantic.MISSING:
# pydantic/__init__.py
MISSING = pydantic_core.MISSING
https://github.com/pydantic/pydantic/blob/ba830dc07550dd7a11f167cbf8b8b707712cd88e/pydantic/__init__.py#L66
Then this fails:
from pydantic import MISSING
x: MISSING | int = MISSING
$ mypy mre1.py
mre1.py:3: error: Variable "pydantic.MISSING" is not valid as a type [valid-type]
mre1.py:3: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
Found 1 error in 1 file (checked 1 source file)
pydantic_core.MISSING doesn't have this problem, since it's where MISSING is originally defined via Sentinel(...):
from pydantic_core import MISSING
x: MISSING | int = MISSING
$ mypy mre2.py
Success: no issues found in 1 source file
FWIW pydantic.MISSING is identified as a valid type if Pydantic is to re-export the sentinel variable via import, i.e.
# pydantic/__init__.py
from pydantic_core import MISSING # instead of MISSING = pydantic_core.MISSING
but I don't think Pydantic is at fault here and other type checkers don't have the same complaint. What do y'all think?
Related
cc @JelleZijlstra
Bug Report
Sentinel loses type information when reassigned.
To Reproduce
https://mypy-play.net/?mypy=master&python=3.12&gist=6d4045b697ab57c41bfeecb59233db76
This call was made in #21647 (comment).
Expected Behavior
mre1.pyshould type-check the same waymre2.pydoes.ALIASis assigned directly fromMISSING, so it should be recognized as the same sentinel.Actual Behavior
Your Environment
mypy.ini(and other config files): (none)Additional Context
This came up because Pydantic 2.14.0b2 re-exports its
MISSINGsentinel frompydantic_coreaspydantic.MISSING:https://github.com/pydantic/pydantic/blob/ba830dc07550dd7a11f167cbf8b8b707712cd88e/pydantic/__init__.py#L66
Then this fails:
pydantic_core.MISSINGdoesn't have this problem, since it's whereMISSINGis originally defined viaSentinel(...):FWIW
pydantic.MISSINGis identified as a valid type if Pydantic is to re-export the sentinel variable viaimport, i.e.but I don't think Pydantic is at fault here and other type checkers don't have the same complaint. What do y'all think?
Related
cc @JelleZijlstra