Movatterモバイル変換


[0]ホーム

URL:


homepage

Issue39485

This issue trackerhas been migrated toGitHub, and is currentlyread-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title:Bug in mock running on PyPy3
Type:Stage:resolved
Components:Versions:
process
Status:closedResolution:fixed
Dependencies:Superseder:
Assigned To: cjw296Nosy List: Carl.Friedrich.Bolz, cjw296
Priority:normalKeywords:patch

Created on2020-01-29 13:49 byCarl.Friedrich.Bolz, last changed2022-04-11 14:59 byadmin. This issue is nowclosed.

Pull Requests
URLStatusLinkedEdit
PR 18252mergedCarl.Friedrich.Bolz,2020-01-29 14:09
PR 18255mergedmiss-islington,2020-01-29 15:44
PR 18256mergedmiss-islington,2020-01-29 15:44
Messages (5)
msg360961 -(view)Author: Carl Friedrich Bolz-Tereick (Carl.Friedrich.Bolz)*Date: 2020-01-29 13:49
One of the new-in-3.8 tests for unittest.mock, test_spec_has_descriptor_returning_function, is failing on PyPy. This exposes a bug in unittest.mock. The bug is most noticeable on PyPy, where it can be triggered by simply writing a slightly weird descriptor (CrazyDescriptor in the test). Getting it to trigger on CPython would be possible too, by implementing the same descriptor in C, but I did not actually do that.The relevant part of the test looks like this:from unittest.mock import create_autospecclass CrazyDescriptor(object):    def __get__(self, obj, type_):        if obj is None:            return lambda x: Noneclass MyClass(object):    some_attr = CrazyDescriptor()mock = create_autospec(MyClass)mock.some_attr(1)On CPython this just works, on PyPy it fails with:Traceback (most recent call last):  File "x.py", line 13, in <module>    mock.some_attr(1)  File "/home/cfbolz/bin/.pyenv/versions/pypy3.6-7.2.0/lib-python/3/unittest/mock.py", line 938, in __call__    _mock_self._mock_check_sig(*args, **kwargs)  File "/home/cfbolz/bin/.pyenv/versions/pypy3.6-7.2.0/lib-python/3/unittest/mock.py", line 101, in checksig    sig.bind(*args, **kwargs)  File "/home/cfbolz/bin/.pyenv/versions/pypy3.6-7.2.0/lib-python/3/inspect.py", line 3034, in bind    return args[0]._bind(args[1:], kwargs)  File "/home/cfbolz/bin/.pyenv/versions/pypy3.6-7.2.0/lib-python/3/inspect.py", line 2955, in _bind    raise TypeError('too many positional arguments') from NoneTypeError: too many positional argumentsThe reason for this problem is that mock deduced that MyClass.some_attr is a method on PyPy. Since mock thinks the lambda returned by the descriptor is a method, it adds self as an argument, which leads to the TypeError.Checking whether something is a method is done by _must_skip in mock.py. The relevant condition is this one:        elif isinstance(getattr(result, '__get__', None), MethodWrapperTypes):            # Normal method => skip if looked up on type            # (if looked up on instance, self is already skipped)            return is_type        else:            return FalseMethodWrapperTypes is defined as:MethodWrapperTypes = (    type(ANY.__eq__.__get__),)which is just types.MethodType on PyPy, because there is no such thing as a method wrapper (the builtin types look pretty much like python-defined types in PyPy).On PyPy the condition isinstance(getattr...) is thus True for all descriptors! so as soon as result has a __get__, it counts as a method, even in the above case where it's a custom descriptor.Now even on CPython the condition makes no sense to me. It would be True for a C-defined version of CrazyDescriptor, it's just not a good way to check whether result is a method.I would propose to replace the condition with the much more straightforward check:        elif isinstance(result, FunctionTypes):            ...something is a method if it's a function on the class. Doing that change makes the test pass on PyPy, and doesn't introduce any test failures on CPython either.Will open a pull request.
msg360968 -(view)Author: Chris Withers (cjw296)*(Python committer)Date: 2020-01-29 15:43
New changeseta327677905956ae0b239ff430a1346dfe265709e by Carl Friedrich Bolz-Tereick in branch 'master':bpo-39485: fix corner-case in method-detection of mock (GH-18252)https://github.com/python/cpython/commit/a327677905956ae0b239ff430a1346dfe265709e
msg360969 -(view)Author: Chris Withers (cjw296)*(Python committer)Date: 2020-01-29 16:10
New changesetcf0645a17acbc0c4dbbf82434e37637965748bbb by Miss Islington (bot) in branch '3.7':bpo-39485: fix corner-case in method-detection of mock (GH-18256)https://github.com/python/cpython/commit/cf0645a17acbc0c4dbbf82434e37637965748bbb
msg360970 -(view)Author: Chris Withers (cjw296)*(Python committer)Date: 2020-01-29 16:15
New changeset696d2324cf2a54e20e8d6a6739fa97ba815a8be9 by Miss Islington (bot) in branch '3.8':bpo-39485: fix corner-case in method-detection of mock (GH-18255)https://github.com/python/cpython/commit/696d2324cf2a54e20e8d6a6739fa97ba815a8be9
msg360971 -(view)Author: Chris Withers (cjw296)*(Python committer)Date: 2020-01-29 16:20
Thank you very much for this, that was a really good catch!
History
DateUserActionArgs
2022-04-11 14:59:26adminsetgithub: 83666
2020-01-29 16:20:19cjw296setstatus: open -> closed
resolution: fixed
messages: +msg360971

stage: patch review -> resolved
2020-01-29 16:15:39cjw296setmessages: +msg360970
2020-01-29 16:10:31cjw296setmessages: +msg360969
2020-01-29 15:44:36miss-islingtonsetpull_requests: +pull_request17633
2020-01-29 15:44:19miss-islingtonsetpull_requests: +pull_request17632
2020-01-29 15:43:54cjw296setmessages: +msg360968
2020-01-29 15:37:56cjw296setassignee:cjw296
2020-01-29 14:09:08Carl.Friedrich.Bolzsetkeywords: +patch
stage: patch review
pull_requests: +pull_request17629
2020-01-29 13:49:55Carl.Friedrich.Bolzcreate
Supported byThe Python Software Foundation,
Powered byRoundup
Copyright © 1990-2022,Python Software Foundation
Legal Statements

[8]ページ先頭

©2009-2026 Movatter.jp