classification
Title: Importing call from unittest.mock directly causes ValueError
Type: behavior Stage: patch review
Components: Tests Versions: Python 3.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Thomas Hisch, pablogsal, splbio, toonarmycaptain, xtreak
Priority: normal Keywords: patch

Created on 2019-01-16 20:17 by toonarmycaptain, last changed 2020-10-26 03:03 by splbio.

Pull Requests
URL Status Linked Edit
PR 22834 open splbio, 2020-10-20 20:27
PR 22981 open splbio, 2020-10-26 03:03
Messages (11)
msg333786 - (view) Author: David Antonini (toonarmycaptain) * Date: 2019-01-16 20:17
Ok so that's a pretty odd bug. I already had from unittest.mock import patch, mock_open so I simply modified that to from  instead of doing mock.call in my test. Changing this to from unittest import mock and then mock.call fixed the error.

from unittest.mock import patch, mock_open, call

mocked_print.assert_has_calls([
    call("first print"),
    call("second print"),
    ])

I get: 

C:\Program Files (x86)\Python37-64\lib\doctest.py:932: in find
    self._find(tests, obj, name, module, source_lines, globs, {})
C:\Program Files (x86)\Python37-64\lib\doctest.py:991: in _find
    if ((inspect.isroutine(inspect.unwrap(val))
C:\Program Files (x86)\Python37-64\lib\inspect.py:515: in unwrap
    raise ValueError('wrapper loop when unwrapping {!r}'.format(f))
E   ValueError: wrapper loop when unwrapping call
collected 1 item / 1 errors

But when I don't import call directly my test runs as expected:

from unittest.mock import patch, mock_open

import unittest.mock

mocked_print.assert_has_calls([
    mock.call(),
    mock.call(),
    ])

I have the same issue when using:

assert mocked_print.call_args_list == [call("first print"), call("second print")] <- ValueError
assert mocked_print.call_args_list == [mock.call("first print"), mock.call("second print")] <- Works as expected.
msg333787 - (view) Author: David Antonini (toonarmycaptain) * Date: 2019-01-16 20:19
I'm having a problem with mock.call when I import it directly from unittest.mock.

When I do:

from unittest.mock import patch, mock_open, call

mocked_print.assert_has_calls([
    call("first print"),
    call("second print"),
    ])

I get: 

C:\Program Files (x86)\Python37-64\lib\doctest.py:932: in find
    self._find(tests, obj, name, module, source_lines, globs, {})
C:\Program Files (x86)\Python37-64\lib\doctest.py:991: in _find
    if ((inspect.isroutine(inspect.unwrap(val))
C:\Program Files (x86)\Python37-64\lib\inspect.py:515: in unwrap
    raise ValueError('wrapper loop when unwrapping {!r}'.format(f))
E   ValueError: wrapper loop when unwrapping call
collected 1 item / 1 errors

But when I don't import call directly my test runs as expected:

from unittest.mock import patch, mock_open

import unittest.mock

mocked_print.assert_has_calls([
    mock.call(),
    mock.call(),
    ])

I have the same issue when using:

assert mocked_print.call_args_list == [call("first print"), call("second print")] <- ValueError
assert mocked_print.call_args_list == [mock.call("first print"), mock.call("second print")] <- Works as expected.
msg333788 - (view) Author: David Antonini (toonarmycaptain) * Date: 2019-01-16 20:21
Apologies for initial malformed message, I hit submit prematurely.
msg333789 - (view) Author: Pablo Galindo Salgado (pablogsal) * (Python committer) Date: 2019-01-16 20:32
Hi David,

Can you provide a full reproducer? In your example, mocked_print is undefined. Please, provide a self-contained script that can be executed to test the behaviour.
msg333790 - (view) Author: (ppperry) Date: 2019-01-16 20:48
According to the error message, this is a duplicate of https://bugs.python.org/issue25532
msg333791 - (view) Author: Pablo Galindo Salgado (pablogsal) * (Python committer) Date: 2019-01-16 21:27
Indeed, closed as duplicate of https://bugs.python.org/issue25532
msg333797 - (view) Author: (ppperry) Date: 2019-01-16 22:18
Sorry, looks like I was wrong about it being a duplicate. The actual bug appears to be "doctest can't run on a module that contains un-unwrappable objects", which there probably is an issue for but I don't know what it is.
msg343335 - (view) Author: Thomas Hisch (Thomas Hisch) Date: 2019-05-24 01:12
I think this tickt needs to be reopened, because

> The actual bug appears to be "doctest can't run on a module that contains un-unwrappable objects"

@ppperry Or do you already know where this issue is tracked?
msg343339 - (view) Author: (ppperry) Date: 2019-05-24 03:09
Indeed, you are right that this should be reopened.
msg343573 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python committer) Date: 2019-05-26 17:54
> The actual bug appears to be "doctest can't run on a module that contains un-unwrappable objects"

Is it the below example scenario being discussed in the issue? Since call is imported it's also present in obj.__dict__ and hence trying to unwrap it [0] could cause error.

This is also mentioned in https://bugs.python.org/issue25532#msg253885 against which this issue was closed. 

> This can occur when you use doctest.DocTestSuite to load doc tests from a module where unittest.mock.call has been imported.

# bpo35753.py
from unittest.mock import call

./python.exe -m doctest bpo35753.py
Traceback (most recent call last):
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/runpy.py", line 192, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 2785, in <module>
    sys.exit(_test())
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 2775, in _test
    failures, _ = testmod(m, verbose=verbose, optionflags=options)
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 1947, in testmod
    for test in finder.find(m, name, globs=globs, extraglobs=extraglobs):
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 932, in find
    self._find(tests, obj, name, module, source_lines, globs, {})
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/doctest.py", line 991, in _find
    if ((inspect.isroutine(inspect.unwrap(val))
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/inspect.py", line 524, in unwrap
    raise ValueError('wrapper loop when unwrapping {!r}'.format(f))
ValueError: wrapper loop when unwrapping call


[0] https://github.com/python/cpython/blob/aaf47caf35984e614d93bd8bea5227df55e0e3e6/Lib/doctest.py#L991
msg379177 - (view) Author: David Antonini (toonarmycaptain) * Date: 2020-10-21 01:00
Somehow I missed the follow up here until now. I don't remember the original code, but I'm fairly confident that mocked_print is the patched print function eg 
with patch('dionysus_app.class_functions.print') as mocked_print:

Probably solved in this commit dated the same day as the bug report:
https://github.com/toonarmycaptain/dionysus/commit/4f0eb7ca32b891d99106441b92a6c1accd0bb96d
History
Date User Action Args
2020-10-26 03:03:22splbiosetpull_requests: + pull_request21898
2020-10-21 01:00:20toonarmycaptainsetmessages: + msg379177
2020-10-20 20:27:53splbiosetkeywords: + patch
nosy: + splbio

pull_requests: + pull_request21788
stage: resolved -> patch review
2019-05-26 21:15:04ppperrysetnosy: - ppperry
2019-05-26 17:54:02xtreaksetmessages: + msg343573
2019-05-26 17:26:18pablogsalsetstatus: closed -> open
resolution: duplicate ->
2019-05-24 03:28:35xtreaksetnosy: + xtreak
2019-05-24 03:09:23ppperrysetmessages: + msg343339
2019-05-24 01:12:07Thomas Hischsetnosy: + Thomas Hisch
messages: + msg343335
2019-01-16 22:18:14ppperrysetmessages: + msg333797
2019-01-16 21:27:39pablogsalsetstatus: open -> closed
resolution: duplicate
messages: + msg333791

stage: resolved
2019-01-16 20:48:34ppperrysetnosy: + ppperry
messages: + msg333790
2019-01-16 20:32:54pablogsalsetnosy: + pablogsal
messages: + msg333789
2019-01-16 20:21:29toonarmycaptainsetmessages: + msg333788
2019-01-16 20:19:08toonarmycaptainsetmessages: + msg333787
2019-01-16 20:17:24toonarmycaptaincreate