Skip to content

bpo-32153: Add unit test for create_autospec with partial function returned in getattr#10398

Merged
cjw296 merged 3 commits into
python:masterfrom
tirkarthi:bpo32153
Dec 3, 2018
Merged

bpo-32153: Add unit test for create_autospec with partial function returned in getattr#10398
cjw296 merged 3 commits into
python:masterfrom
tirkarthi:bpo32153

Conversation

@tirkarthi

@tirkarthi tirkarthi commented Nov 7, 2018

Copy link
Copy Markdown
Member

This adds an unit test for https://bugs.python.org/issue32153 which was out dated and fixed by https://bugs.python.org/issue28919 . During create_autospec the function attributes are copied and when getattr returns a partial function then it doesn't contain __name__ causing AttributeError . This was fixed in 3.7 suppressing AttributeError but was not backported thus this test can be applied only on 3.7 and master.

Fails on 3.6 branch

   cpython git:(25bd107399)   ./python.exe
Python 3.6.7+ (remotes/upstream/3.6:25bd107399, Nov  8 2018, 00:50:43)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> ^D
   cpython git:(25bd107399)   ./python.exe -m unittest -v unittest.test.testmock.testhelpers.SpecSignatureTest.test_autospec_getattr_partial_function
test_autospec_getattr_partial_function (unittest.test.testmock.testhelpers.SpecSignatureTest) ... ERROR

======================================================================
ERROR: test_autospec_getattr_partial_function (unittest.test.testmock.testhelpers.SpecSignatureTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/test/testmock/testhelpers.py", line 884, in test_autospec_getattr_partial_function
    autospec = create_autospec(proxy)
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", line 2182, in create_autospec
    _check_signature(spec, mock, is_type, instance)
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", line 102, in _check_signature
    _copy_func_details(func, checksig)
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", line 107, in _copy_func_details
    funcopy.__name__ = func.__name__
AttributeError: 'functools.partial' object has no attribute '__name__'

----------------------------------------------------------------------
Ran 1 test in 0.007s

FAILED (errors=1)

Passes on master

   cpython git:(bpo32153) ./python.exe
Python 3.8.0a0 (heads/bpo32153:3e9cd8d982, Nov  8 2018, 00:53:46)
[Clang 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> ^D
   cpython git:(bpo32153) ./python.exe -m unittest -v unittest.test.testmock.testhelpers.SpecSignatureTest.test_autospec_getattr_partial_function
test_autospec_getattr_partial_function (unittest.test.testmock.testhelpers.SpecSignatureTest) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.005s

OK

https://bugs.python.org/issue32513

@tirkarthi tirkarthi changed the title bpo-32513: Add unit test for create_autospec with partial function returned in getattr bpo-32153: Add unit test for create_autospec with partial function returned in getattr Nov 7, 2018
Comment thread Lib/unittest/test/testmock/testhelpers.py Outdated
class Foo(object):

def __getattr__(self, name):
return partial(lambda name: name, name)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is name here? The parameter of __getattr__ or the parameter of the lambda? It is better to use different names for avoiding confusion.

Unconditional return in __getattr__() can cause issues, because internal code can get some special instance attributes and be confused by getting a lambda. Return only for specific name, and raise an AttributeError in other cases.

if name == '...':
    return ...
raise AttributeError

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is name here? The parameter of getattr or the parameter of the lambda? It is better to use different names for avoiding confusion.

I will change them. Thanks.

Unconditional return in getattr() can cause issues, because internal code can get some special instance attributes and be confused by getting a lambda. Return only for specific name, and raise an AttributeError in other cases.

From the original report this is about __getattr__ returning a partial function unconditionally for all attributes and partial functions have no __name__ attribute during copy which occurs at https://github.com/python/cpython/blob/master/Lib/unittest/mock.py#L108. I am slightly confused over why we should have an if clause for this and raise AttributeError that might change the original report that needs to be tested.

def test_autospec_getattr_partial_function(self):
# bpo-32153 : getattr returning partial functions without
# __name__ should not create AttributeError in create_autospec
class Foo(object):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(object) is not needed.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed. Thanks.

@bedevere-bot

Copy link
Copy Markdown

@cjw296: Please replace # with GH- in the commit message next time. Thanks!

@tirkarthi

Copy link
Copy Markdown
Member Author

@cjw296 Thanks for merging the PR. This test can be back ported to 3.7 since it's fixed there. I think @miss-islington will make the back port PR once you add the label "needs backport to 3.7".

@miss-islington

Copy link
Copy Markdown
Contributor

Thanks @tirkarthi for the PR, and @cjw296 for merging it 🌮🎉.. I'm working now to backport this PR to: 3.7.
🐍🍒⛏🤖

@bedevere-bot

Copy link
Copy Markdown

GH-10855 is a backport of this pull request to the 3.7 branch.

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Dec 3, 2018
…turned in getattr (pythonGH-10398)

* Add create_autospec with partial function returned in getattr

* Use self.assertFalse instead of assert

* Use different names and remove object
(cherry picked from commit c667b09)

Co-authored-by: Xtreak <tirkarthi@users.noreply.github.com>
@cjw296

cjw296 commented Dec 3, 2018

Copy link
Copy Markdown
Contributor

@tirkarthi - done, do you know if the fix made it to 3.6 too?

cjw296 pushed a commit that referenced this pull request Dec 3, 2018
…turned in getattr (GH-10398) (#10855)

* Add create_autospec with partial function returned in getattr

* Use self.assertFalse instead of assert

* Use different names and remove object
(cherry picked from commit c667b09)

Co-authored-by: Xtreak <tirkarthi@users.noreply.github.com>
@tirkarthi

Copy link
Copy Markdown
Member Author

@cjw296 No, the issue was not fixed in 3.6 as noted in https://bugs.python.org/issue32153#msg327531 . I also ran the test for confirmation in latest 3.6 branch while opening the PR #10398 (comment) and it fails. So this test should not be back ported to 3.6.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants