blob: 7a85cda95e81adf95680419e5dd771af6be269e7 [file]
[case testSentinelTypeExpressionsAndNarrowing]
from typing_extensions import Sentinel, assert_type, sentinel
MISSING = Sentinel("<MISSING>", repr="missing")
SPECIAL = sentinel("SPECIAL")
class Cls:
IN_CLASS = Sentinel("Cls.IN_CLASS")
def func2(x: int | MISSING | SPECIAL = MISSING) -> None:
if x is MISSING:
assert_type(x, MISSING)
else:
assert_type(x, int | SPECIAL)
def func3(x: int | Cls.IN_CLASS = Cls.IN_CLASS) -> None:
if x is Cls.IN_CLASS:
assert_type(x, Cls.IN_CLASS)
else:
assert_type(x, int)
func2(1)
func2(MISSING)
func2(SPECIAL)
func2(Cls.IN_CLASS) # E: Argument 1 to "func2" has incompatible type "Cls.IN_CLASS"; expected "int | MISSING | SPECIAL"
func3(1)
func3(MISSING) # E: Argument 1 to "func3" has incompatible type "MISSING"; expected "int | Cls.IN_CLASS"
func3(Cls.IN_CLASS)
[builtins fixtures/tuple.pyi]
[case testSentinelEqualityNarrowingCurrentBehavior]
from typing_extensions import Sentinel, assert_type
MISSING = Sentinel("MISSING")
SPECIAL = Sentinel("SPECIAL")
def func(x: int | MISSING | SPECIAL) -> None:
if x == MISSING:
assert_type(x, MISSING)
else:
assert_type(x, int | SPECIAL)
[builtins fixtures/ops.pyi]
[case testSentinelNarrowingInSequence]
from typing_extensions import assert_type, Sentinel
MISSING = Sentinel("MISSING")
def func(var: str | MISSING | None) -> None:
if var in (MISSING, None):
assert_type(var, MISSING | None)
else:
assert_type(var, str)
[builtins fixtures/tuple.pyi]
[case testSentinelSameReprDistinctTypes]
from typing_extensions import Sentinel
FIRST = Sentinel("DUPLICATE")
SECOND = Sentinel("DUPLICATE")
def takes_first(x: FIRST) -> None: ...
takes_first(FIRST)
takes_first(SECOND) # E: Argument 1 to "takes_first" has incompatible type "SECOND"; expected "FIRST"
[builtins fixtures/tuple.pyi]
[case testSentinelFunctionLocalNotTypeExpression]
from typing_extensions import Sentinel
def outer() -> None:
LOCAL = Sentinel("LOCAL")
def inner(x: LOCAL) -> None: ... # E: Variable "LOCAL" is not valid as a type \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
[builtins fixtures/tuple.pyi]
[case testSentinelClassNestedInFunctionNotTypeExpression]
from typing_extensions import Sentinel
def outer() -> None:
class C:
MISSING = Sentinel("MISSING")
def inner(x: C.MISSING) -> None: ... # E: Variable "__main__.C@4.MISSING" is not valid as a type \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
[builtins fixtures/tuple.pyi]
[case testSentinelImplicitlyFinal]
from typing_extensions import Sentinel
MISSING = Sentinel("MISSING")
MISSING = Sentinel("OTHER") # E: Cannot redefine an existing name as final
[builtins fixtures/tuple.pyi]
[case testSentinelImplicitlyFinalWithLaterReference]
from typing_extensions import Sentinel
_SENTINEL = Sentinel("_SENTINEL")
def func(x: int | _SENTINEL = _SENTINEL) -> int:
if x is _SENTINEL:
return 0
return x
[builtins fixtures/tuple.pyi]
[case testBuiltinsSentinelTypeExpression]
# flags: --python-version 3.15
from typing import assert_type
MISSING = sentinel("MISSING")
def func(x: int | MISSING = MISSING) -> None:
if x is not MISSING:
assert_type(x, int)
else:
assert_type(x, MISSING)
[builtins fixtures/sentinel.pyi]
[case testPrivateSentinelNameCanBeReusedAcrossModules]
from typing_extensions import Sentinel
_SENTINEL = Sentinel("_SENTINEL")
[file other.py]
from typing_extensions import Sentinel
_SENTINEL = Sentinel("_SENTINEL")
[builtins fixtures/tuple.pyi]
[case testPrivateSentinelNameCanBeReusedAfterStarImport]
from other import *
from typing_extensions import Sentinel
_SENTINEL = Sentinel("_SENTINEL")
[file other.py]
from typing_extensions import Sentinel
_SENTINEL = Sentinel("_SENTINEL")
[builtins fixtures/tuple.pyi]
[case testPrivateSentinelNameCanBeReusedAfterStarImportWithAll]
from other import *
from typing_extensions import Sentinel
_SENTINEL = Sentinel("_SENTINEL")
[file other.py]
from typing_extensions import Sentinel
_SENTINEL = Sentinel("_SENTINEL")
__all__ = ("public",)
public = 1
[builtins fixtures/tuple.pyi]
[case testIsinstanceSentinel]
# flags: --python-version 3.15
from typing import assert_type
from typing_extensions import Sentinel
BUILTIN = sentinel("BUILTIN")
TYPEXT = Sentinel("TYPEXT")
def func(x: int | BUILTIN | TYPEXT) -> None:
if isinstance(x, sentinel):
assert_type(x, BUILTIN)
else:
assert_type(x, int | TYPEXT)
if isinstance(x, Sentinel):
assert_type(x, TYPEXT)
else:
assert_type(x, int)
[builtins fixtures/sentinel.pyi]
[case testSentinelReassignmentIsNotTypeAlias]
from typing_extensions import sentinel, assert_type
MISSING = sentinel("MISSING")
ALIAS = MISSING
# The value still identifies as the same sentinel...
assert_type(ALIAS, MISSING)
def func(x: int | MISSING = MISSING) -> None:
pass
func(MISSING)
func(ALIAS)
# ...but the reassignment does not make ALIAS usable as a type alias.
def uses_alias_as_type(x: ALIAS) -> None: # E: Variable "__main__.ALIAS" is not valid as a type \
# N: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
pass
[builtins fixtures/tuple.pyi]
[case testSentinelPreservedThroughGenericSubstitution]
from typing import assert_type
from typing_extensions import sentinel
Unknown = sentinel("Unknown")
def func(d: dict[str, str]) -> None:
var = d.get("key", Unknown)
assert_type(var, str | Unknown)
[builtins fixtures/dict-full.pyi]
[case testSentinelPreservedInErrorMessages]
from typing_extensions import sentinel
Unknown = sentinel("Unknown")
def func(d: dict[str, str]) -> None:
var = d.get("key", Unknown)
x: int = var # E: Incompatible types in assignment (expression has type "str | Unknown", variable has type "int")
[builtins fixtures/dict-full.pyi]
[case testAssignSentinel]
from typing_extensions import sentinel
X = sentinel("X")
def inspect_sentinel(arg: sentinel) -> None: ...
reveal_type(X) # N: Revealed type is "X"
reveal_type(inspect_sentinel) # N: Revealed type is "def (arg: typing_extensions.Sentinel)"
inspect_sentinel(arg=X)
[builtins fixtures/tuple.pyi]