Files
RustPython/extra_tests/snippets/stdlib_typing.py
youknowdot 44858012f4 Preserve missing caller modules in eager type aliases (#9073)
Only lazy aliases may obtain their module from the evaluation function. Eager aliases without a caller __name__ must not inspect their stored value.

Assisted-by: OpenAI Codex:model identifier unavailable
2026-10-10 21:05:21 +00:00

87 lines
2.2 KiB
Python

from collections.abc import Awaitable, Callable
from typing import TypeVar
import _typing
from testutils import assert_raises
T = TypeVar("T")
def abort_signal_handler(
fn: Callable[[], Awaitable[T]], on_abort: Callable[[], None] | None = None
) -> T:
pass
# Ensure PEP 604 unions work with typing.Callable aliases.
TracebackFilter = bool | Callable[[int], int]
# Test that Union/Optional in function parameter annotations work correctly.
# This tests that annotation scopes can access global implicit symbols (like Union)
# that are imported at module level but not explicitly bound in the function scope.
# Regression test for: rich
from typing import Optional, Union
def function_with_union_param(x: Optional[Union[int, str]] = None) -> None:
pass
class ClassWithUnionParams:
def __init__(
self,
color: Optional[Union[str, int]] = None,
bold: Optional[bool] = None,
) -> None:
pass
def method(self, value: Union[int, float]) -> Union[str, bytes]:
return str(value)
# _idfunc takes exactly one argument, checked before the argument is read.
assert _typing._idfunc(1) == 1
with assert_raises(TypeError):
_typing._idfunc()
# ParamSpecArgs shows a non-ParamSpec origin by its repr, which is where the
# recursion guard lives; nesting them deeply must not walk the native stack.
from typing import ParamSpec, ParamSpecArgs
spec = ParamSpec("spec")
assert repr(spec.args) == "spec.args"
assert repr(spec.kwargs) == "spec.kwargs"
nested = object()
for _ in range(2000):
nested = ParamSpecArgs(nested)
try:
repr(nested)
except RecursionError:
pass
# Eager aliases without a caller module never inspect their aliased value.
alias_module_lookups = []
class AliasModuleValue:
@property
def __module__(self):
alias_module_lookups.append(True)
return "unexpected_value_module"
for alias_value in (int, AliasModuleValue()):
alias_namespace = {"value": alias_value}
exec(
"from typing import TypeAliasType; alias = TypeAliasType('Alias', value)",
alias_namespace,
)
assert alias_namespace["alias"].__module__ is None
assert alias_module_lookups == []