Skip to content

patch.dict(x, y) interpreted as invoking __call__, not __init__ #5118

Closed

Description

@rbtcollins

Note: if you are reporting a wrong signature of a function or a class in
the standard library, then the typeshed tracker is better suited
for this report: https://github.com/python/typeshed/issues

I think this is a mypy bug, happy to be sent to typeshed though.

I'm using mypy 0.6, and have the following code:

from unittest import TestCase
from unittest.mock import patch

class A(TestCase):

    @patch.dict("os.environ", {"PATH": os.path.expanduser("~/.local/bin")})
    @patch.object(moduleA, "a")
    @patch("subprocess.check_output")
    def test_missing(self, check_output, a):
        pass

This errors like so:
error: Too many arguments for "__call__" of "_patch_dict"

The typeshed stub for this is

    class _patch_dict:
...
        def __init__(self, in_dict: Any, values: Any = ..., clear: Any = ..., **kwargs: Any) -> None: ...
        def __call__(self, f: Any) -> Any: ...
...

    class _patcher:
        TEST_PREFIX = ...  # type: str
        dict = ...  # type: _patch_dict
...
    patch = ...  # type: _patcher

So mypy should be able to tell that this is instantiating an instance of _patch_dict with __init__ and then that instance is being called with one argument - the curried patcher next inwards in the stack.

Activity

  1. changed the title [-]patch.dict interpreted as __call__ not __init__[/-] [+]patch.dict(x, y) interpreted as invoking __call__, not __init__[/+] on May 29, 2018
  2. li-dan commented on May 29, 2018

    @li-dan
    Contributor

    I think this is a bug in the stubs. patch.dict is the _patch_dict class itself, not an instance of _patch_dict, so the annotation should be # type: Type[_patch_dict], not # type: _patch_dict.

  3. gvanrossum commented on May 29, 2018

    @gvanrossum
    Member

    Can one of you submit a PR to typeshed?

  4. rbtcollins commented on May 29, 2018

    @rbtcollins
    MemberAuthor

    Let me give it a spin

  5. rbtcollins commented on May 29, 2018

    @rbtcollins
    MemberAuthor

    Should we also wrap dict in ClassVar ?

  6. JelleZijlstra commented on May 29, 2018

    @JelleZijlstra
    Member

    I think you can just do dict = _patch_dict; haven't tested though.

  7. rbtcollins commented on May 29, 2018

    @rbtcollins
    MemberAuthor
  8. rbtcollins commented on May 30, 2018

    @rbtcollins
    MemberAuthor

    @JelleZijlstra you can in Python 3; for some reason that fails on Python 2 (see the typeshed CI job).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions