Skip to content
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

unittest.mock.patch: Double patching instance method: AttributeError: Mock object has no attribute '__name__' #70891

Closed
asottile mannequin opened this issue Apr 6, 2016 · 9 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@asottile
Copy link
Mannequin

asottile mannequin commented Apr 6, 2016

BPO 26704
Nosy @cjw296, @voidspace, @asottile, @tirkarthi
PRs
  • bpo-26704: Add test for double patching instance methods #11085
  • [3.7] bpo-26704 - Add test for double patching instance methods (GH-11085) #11126
  • Files
  • patch
  • patch2
  • 2.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2018-12-12.09:01:53.837>
    created_at = <Date 2016-04-06.20:01:26.286>
    labels = ['type-bug', 'library']
    title = "unittest.mock.patch: Double patching instance method: AttributeError: Mock object has no attribute '__name__'"
    updated_at = <Date 2018-12-12.09:01:53.837>
    user = 'https://bugs.python.org/asottile'

    bugs.python.org fields:

    activity = <Date 2018-12-12.09:01:53.837>
    actor = 'cjw296'
    assignee = 'none'
    closed = True
    closed_date = <Date 2018-12-12.09:01:53.837>
    closer = 'cjw296'
    components = ['Library (Lib)']
    creation = <Date 2016-04-06.20:01:26.286>
    creator = 'asottile'
    dependencies = []
    files = ['42384', '42387', '42675']
    hgrepos = []
    issue_num = 26704
    keywords = ['patch']
    message_count = 9.0
    messages = ['262960', '262966', '262972', '264611', '331430', '331536', '331579', '331588', '331590']
    nosy_count = 5.0
    nosy_names = ['cjw296', 'michael.foord', 'asottile', 'Anthony Sottile', 'xtreak']
    pr_nums = ['11085', '11126']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue26704'
    versions = ['Python 3.5', 'Python 3.6']

    @asottile
    Copy link
    Mannequin Author

    asottile mannequin commented Apr 6, 2016

    Originally from testing-cabal/mock#350

    ## Example

    from unittest import mock
    
    class C(object):
        def f(self):
            pass
    
    c = C()
    
    with mock.patch.object(c, 'f', autospec=True):
        with mock.patch.object(c, 'f', autospec=True):
            pass

    ## Python3.3

    $ test.py
    $
    

    ## Python3.4 / 3.5 / 3.6 (From gitbhub.com/python/cpython@fa3fc6d7)

    Traceback (most recent call last):
      File "test.py", line 10, in <module>
        with mock.patch.object(c, 'f', autospec=True):
      File "/home/asottile/workspace/cpython/Lib/unittest/mock.py", line 1320, in __enter__
        _name=self.attribute, **kwargs)
      File "/home/asottile/workspace/cpython/Lib/unittest/mock.py", line 2220, in create_autospec
        _check_signature(original, new, skipfirst=skipfirst)
      File "/home/asottile/workspace/cpython/Lib/unittest/mock.py", line 112, in _check_signature
        _copy_func_details(func, checksig)
      File "/home/asottile/workspace/cpython/Lib/unittest/mock.py", line 117, in _copy_func_details
        funcopy.__name__ = func.__name__
      File "/home/asottile/workspace/cpython/Lib/unittest/mock.py", line 578, in __getattr__
        raise AttributeError("Mock object has no attribute %r" % name)
    AttributeError: Mock object has no attribute '__name__'
    

    @asottile asottile mannequin added type-crash A hard crash of the interpreter, possibly with a core dump stdlib Python modules in the Lib dir labels Apr 6, 2016
    @asottile
    Copy link
    Mannequin Author

    asottile mannequin commented Apr 6, 2016

    The root cause seems to be that autospecced functions return a function object (not a Mock instance) which a '.mock' attribute which is a MagicMock ( assigned here:

    funcopy.mock = mock
    )

    I took a first stab at a patch (attached)

    @asottile
    Copy link
    Mannequin Author

    asottile mannequin commented Apr 6, 2016

    Here's an improved patch which:

    • passes the tests
    • puts the test in the correct place

    I'm not entirely happy with the approach -- open to suggestions :)

    @SilentGhost SilentGhost mannequin added type-bug An unexpected behavior, bug, or error and removed type-crash A hard crash of the interpreter, possibly with a core dump labels Apr 7, 2016
    @asottile
    Copy link
    Mannequin Author

    asottile mannequin commented May 1, 2016

    Seems I've named the patchfile incorrectly -- Hopefully this is correct this time?

    @tirkarthi
    Copy link
    Member

    Thanks @asottile for the patch. I think the original AttributeError is resolved with bpo-28919 where they were silenced. It seems similar to bpo-32153 though the exception occurs from mock instead of partial object as in bpo-32153. The fix was applied to 3.7+ and hence 3.6 was not fixed which enters security fix only mode shortly. The attached tests also pass on master and I think it will it be a good unittest addition to Lib/unittest/test/testmock/testwith.py (similar to bpo-32153) that has a couple of nested with statements for the same attribute. Adding cjw296 to the list.

    @asottile
    Copy link
    Mannequin Author

    asottile mannequin commented Dec 10, 2018

    I've opened a PR with the test included: #11085

    @cjw296
    Copy link
    Contributor

    cjw296 commented Dec 11, 2018

    Before we get too far: what's the use case for this double patching?

    @asottile
    Copy link
    Mannequin Author

    asottile mannequin commented Dec 11, 2018

    to be honest, I don't recall exactly given it's been 2 and a half years since the original report with no activity.

    if I recall correctly, this was encountered while upgrading the mock backport in yelp's monolithic repository.

    I want to say the reason this was hard to "fix" properly was due to some blanket patches being applied in a base test case and then other test cases re-patching those methods to add more specific behaviour. This worked fine in python2.7 and all the way until python3.3 but then was broken by changes in python3.4

    Fortunately, they've been fixed in python3.7. I guess I've been encouraged to write a patch with a test so it does not regress in the future

    @cjw296
    Copy link
    Contributor

    cjw296 commented Dec 11, 2018

    Ah, yeah, I can see the blanket patch and a more local patch in a monorepo being a thing, cool, let's have a look!

    @cjw296 cjw296 closed this as completed Dec 12, 2018
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants