Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
simplify
  • Loading branch information
JelleZijlstra committed May 10, 2026
commit 4d00721893f73aac635b20d76ef8920a218183f9
6 changes: 1 addition & 5 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -3423,11 +3423,7 @@ def sentinel_type_for_var(self, var: Var, rvalue: Expression) -> Instance | None
assert isinstance(rvalue, CallExpr)
callee = rvalue.callee
assert isinstance(callee, RefExpr)
if callee.fullname == "typing_extensions.sentinel":
fallback_fullname = "typing_extensions.Sentinel"
else:
fallback_fullname = callee.fullname
typ = self.named_type_or_none(fallback_fullname)
typ = self.named_type_or_none(callee.fullname)
if typ is None:
return None
name = f"{self.type.name}.{var.name}" if self.type is not None else var.name
Expand Down
2 changes: 2 additions & 0 deletions test-data/unit/check-sentinels.test
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ MISSING = Sentinel("MISSING")
SPECIAL = Sentinel("SPECIAL")

def func(x: int | MISSING | SPECIAL) -> None:
# We could reasonably do narrowing here, but currently we're pretty conservative
# about narrowing on ==.
if x == MISSING:
Comment thread
JelleZijlstra marked this conversation as resolved.
assert_type(x, int | MISSING | SPECIAL)
else:
Expand Down
49 changes: 5 additions & 44 deletions test-data/unit/fixtures/sentinel.pyi
Original file line number Diff line number Diff line change
@@ -1,60 +1,21 @@
# Builtins stub used in sentinel-related test cases.

import _typeshed
import types
from typing import Iterable, Iterator, TypeVar, Generic, Sequence, Optional, overload, Tuple, Type, Self

_T = TypeVar("_T")
_Tco = TypeVar('_Tco', covariant=True)
from typing import Self

class object:
def __init__(self) -> None: pass
def __new__(cls) -> Self: ...

class type:
def __init__(self, *a: object) -> None: pass
def __call__(self, *a: object) -> object: pass
class tuple(Sequence[_Tco], Generic[_Tco]):
def __hash__(self) -> int: ...
def __new__(cls: Type[_T], iterable: Iterable[_Tco] = ...) -> _T: ...
def __iter__(self) -> Iterator[_Tco]: pass
def __contains__(self, item: object) -> bool: pass
@overload
def __getitem__(self, x: int) -> _Tco: pass
@overload
def __getitem__(self, x: slice) -> Tuple[_Tco, ...]: ...
def __mul__(self, n: int) -> Tuple[_Tco, ...]: pass
def __rmul__(self, n: int) -> Tuple[_Tco, ...]: pass
def __add__(self, x: Tuple[_Tco, ...]) -> Tuple[_Tco, ...]: pass
def count(self, obj: object) -> int: pass
class type: pass
class function:
__name__: str
class ellipsis: pass
class classmethod: pass

# We need int and slice for indexing tuples.
class int:
def __neg__(self) -> 'int': pass
def __pos__(self) -> 'int': pass
class float: pass
class slice: pass
class int: pass
class bool(int): pass
class str: pass # For convenience
class str: pass

class sentinel:
def __init__(self, name: str, /) -> None: ...
class bytes: pass
class bytearray: pass

class list(Sequence[_T], Generic[_T]):
@overload
def __getitem__(self, i: int) -> _T: ...
@overload
def __getitem__(self, s: slice) -> list[_T]: ...
def __contains__(self, item: object) -> bool: ...
def __iter__(self) -> Iterator[_T]: ...

def isinstance(x: object, t: type) -> bool: pass

class BaseException: pass

class dict: pass
2 changes: 1 addition & 1 deletion test-data/unit/lib-stub/typing_extensions.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Never: _SpecialForm
class Sentinel:
def __init__(self, name: str, repr: str | None = None) -> None: ...
def __eq__(self, other: object) -> bool: ...
def sentinel(name: str, repr: str | None = None) -> Sentinel: ...
sentinel = Sentinel

TypeVarTuple: _SpecialForm
Unpack: _SpecialForm
Expand Down
Loading