-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Fix mock patch.dict stub and add mock stub #2173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
stdlib/3/unittest/mock.pyi
Outdated
@@ -1,4 +1,5 @@ | |||
# Stubs for unittest.mock | |||
# Please sync with third_party/2and3/mock.pyi when changing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can put this in typeshed/tests/check_consistent.py
(you'll have to make sure the files are byte-for-byte identical).
d7c5ff3
to
a0ab2e4
Compare
The dict stub was referring to an instance, not the type, leading to __call__ being considered when using as a decorator, rather than __init__. mock is a backport of the stdlib module and should be defined the same.
@JelleZijlstra is anything else needed from me for this to merge? |
Thanks for fixing this. |
@rbtcollins @JelleZijlstra This just broke a bunch of our type checks: from mock import MagicMock, call, mock_open, patch Results in:
|
import sys | ||
from typing import Any, Optional, Type | ||
8000 |
||
if sys.version_info >= (3, 3): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This appears to be the problem - for Python 2 this is left as an empty module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops you're right. We should make it so that everything gets unconditionally exported. (We don't care about 3.2 anyway.)
Can you make a PR making that change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Submitted #2201
@rbtcollins @JelleZijlstra @rowillia |
Hm, that is indeed unfortunate. But doesn't Mock still inherit from Any in this PR? |
It does. And in a toy example it seems to be acceptable; I get no errors here: class M(Any): pass
class A: pass
def f(a: A): pass
f(M()) I'll have to look over our code more carefully to see what scenario triggered those errors. |
Oh, it's the other way around. Example: class M(Any): pass # type: ignore
class A: pass
def foo(a: M): pass
foo(A()) # error: Argument 1 to "foo" has incompatible type "A"; expected "M" This pattern happens a lot in our code (though typically it's a variable initialized with a Mock and later assigned something non-Mock). |
So you have functions that are annotated as taking If it's common though, I'd be OK with making Mock just be an alias for Any. |
I did find functions annotated as taking Mocks... I am not complaining about those, I changed them to Any. More common was instance variables initialized from a Mock and later assigned from a non-Mock (clearly an instance the class that the Mock was mocking). The initialization causes an implicit declaration. Sort of like class Account:
...
def get_account(username):
# type: (str) -> Account
...
class C:
def __init__(self):
# type: () -> None
self.account = Mock() # implies type: Mock
def switch_account(self, username):
# type: (str) -> None
self.account = get_account(username) # error here |
Could the solution be to just give explicit annotation, like self.account: Account = Mock() Also, the current behavior of classes with an |
Oh thanks, that makes more sense! I think even in this case though, mypy found a real type problem. The code works correctly if you do |
Upstream bug: python/typeshed#2173
The dict stub was referring to an instance, not the type, leading to __call__ being considered when using as a decorator, rather than __init__. mock is a backport of the stdlib module and should be defined the same.
The dict stub was referring to an instance, not the type, leading to
call being considered when using as a decorator, rather than
init.
mock is a backport of the stdlib module and should be defined the same.