unittest.mock._patch_dict.__call__ is typed as def __call__(self, f: Any) -> Any: ..., so using @patch.dict(...) as a decorator erases the wrapped function's signature (return type Any). Note _patch.__call__ (plain @patch(...)) has overloads that keep the wrapped callable's signature (via _TT / Callable[_P, _R]).
This makes type checkers that flag signature-erasing decorators (ex: ty's dynamic-function-decorator-return) warn on @patch.dict(...)-decorated test functions.
from unittest.mock import patch
@patch.dict("os.environ", {"FOO": "bar"})
def test_something() -> None: ...
{
"environment": {
"python-version": "3.14"
},
"rules": {
"all": "error"
}
}
See output at https://play.ty.dev/0e61be9c-810a-4266-985b-8daf6377f986
Suggested fix:
diff --git a/stdlib/unittest/mock.pyi b/stdlib/unittest/mock.pyi
index 1b6ab756d..4fc5ea120 100644
--- a/stdlib/unittest/mock.pyi
+++ b/stdlib/unittest/mock.pyi
@@ -301,7 +301,12 @@ class _patch_dict:
values: Any
clear: Any
def __init__(self, in_dict: Any, values: Any = (), clear: Any = False, **kwargs: Any) -> None: ...
- def __call__(self, f: Any) -> Any: ...
+ @overload
+ def __call__(self, f: _TT) -> _TT: ...
+ @overload
+ def __call__(self, f: _AF) -> _AF: ...
+ @overload
+ def __call__(self, f: _F) -> _F: ...
def __enter__(self) -> Any: ...
def __exit__(self, *args: object) -> Any: ...
def decorate_callable(self, f: _F) -> _F: ...
unittest.mock._patch_dict.__call__is typed asdef __call__(self, f: Any) -> Any: ..., so using@patch.dict(...)as a decorator erases the wrapped function's signature (return typeAny). Note_patch.__call__(plain@patch(...)) has overloads that keep the wrapped callable's signature (via_TT/Callable[_P, _R]).This makes type checkers that flag signature-erasing decorators (ex: ty's
dynamic-function-decorator-return) warn on@patch.dict(...)-decorated test functions.{ "environment": { "python-version": "3.14" }, "rules": { "all": "error" } }See output at https://play.ty.dev/0e61be9c-810a-4266-985b-8daf6377f986
Suggested fix: