Skip to content

Commit 2fd1ac5

Browse files
srittaunicoddemus
authored andcommitted
Type improvements
Annotate MockerFixture.patch(). Without an explicit annotations, mypy and other type checkers can't determine the proper type and assume Any. MockerFixture.patch() can return an arbitrary type if either new or new_callable is provided. Add overloads to handle these cases.
1 parent 7c307ea commit 2fd1ac5

File tree

2 files changed

+71
-4
lines changed

2 files changed

+71
-4
lines changed

CHANGELOG.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010

1111
Note however that this is just a stop gap measure, and new code should use ``MockerFixture`` for type annotations.
1212

13+
* Improved typing for ``MockerFixture.patch`` (`#201`_). Thanks `@srittau`_ for the PR.
14+
15+
.. _@srittau: https://github.com/srittau
16+
.. _#201: https://github.com/pytest-dev/pytest-mock/pull/201
17+
18+
1319
3.3.0 (2020-08-21)
1420
------------------
1521

src/pytest_mock/plugin.py

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import builtins
22
import unittest.mock
3-
from typing import cast, Generator, Mapping, Iterable, Tuple
3+
from typing import cast, overload, Generator, Mapping, Iterable, Tuple, TypeVar
44
from typing import Any
55
from typing import Callable
66
from typing import Dict
@@ -17,6 +17,8 @@
1717

1818
import pytest
1919

20+
_T = TypeVar("_T")
21+
2022

2123
def _get_mock_module(config):
2224
"""
@@ -50,7 +52,9 @@ def __init__(self, config: Any) -> None:
5052
self._patches = [] # type: List[Any]
5153
self._mocks = [] # type: List[Any]
5254
self.mock_module = mock_module = _get_mock_module(config)
53-
self.patch = self._Patcher(self._patches, self._mocks, mock_module)
55+
self.patch = self._Patcher(
56+
self._patches, self._mocks, mock_module
57+
) # type: MockerFixture._Patcher
5458
# aliases for convenience
5559
self.Mock = mock_module.Mock
5660
self.MagicMock = mock_module.MagicMock
@@ -254,6 +258,63 @@ def dict(
254258
**kwargs
255259
)
256260

261+
@overload
262+
def __call__(
263+
self,
264+
target: str,
265+
new: None = ...,
266+
spec: Optional[builtins.object] = ...,
267+
create: bool = ...,
268+
spec_set: Optional[builtins.object] = ...,
269+
autospec: Optional[builtins.object] = ...,
270+
new_callable: None = ...,
271+
**kwargs: Any
272+
) -> unittest.mock.MagicMock:
273+
...
274+
275+
@overload
276+
def __call__(
277+
self,
278+
target: str,
279+
new: _T,
280+
spec: Optional[builtins.object] = ...,
281+
create: bool = ...,
282+
spec_set: Optional[builtins.object] = ...,
283+
autospec: Optional[builtins.object] = ...,
284+
new_callable: None = ...,
285+
**kwargs: Any
286+
) -> _T:
287+
...
288+
289+
@overload
290+
def __call__(
291+
self,
292+
target: str,
293+
new: None,
294+
spec: Optional[builtins.object],
295+
create: bool,
296+
spec_set: Optional[builtins.object],
297+
autospec: Optional[builtins.object],
298+
new_callable: Callable[[], _T],
299+
**kwargs: Any
300+
) -> _T:
301+
...
302+
303+
@overload
304+
def __call__(
305+
self,
306+
target: str,
307+
new: None = ...,
308+
spec: Optional[builtins.object] = ...,
309+
create: bool = ...,
310+
spec_set: Optional[builtins.object] = ...,
311+
autospec: Optional[builtins.object] = ...,
312+
*,
313+
new_callable: Callable[[], _T],
314+
**kwargs: Any
315+
) -> _T:
316+
...
317+
257318
def __call__(
258319
self,
259320
target: str,
@@ -262,9 +323,9 @@ def __call__(
262323
create: bool = False,
263324
spec_set: Optional[builtins.object] = None,
264325
autospec: Optional[builtins.object] = None,
265-
new_callable: Optional[builtins.object] = None,
326+
new_callable: Optional[Callable[[], Any]] = None,
266327
**kwargs: Any
267-
) -> unittest.mock.MagicMock:
328+
) -> Any:
268329
"""API to mock.patch"""
269330
if new is self.DEFAULT:
270331
new = self.mock_module.DEFAULT

0 commit comments

Comments
 (0)