testing-cabal / mock

The Python mock library

Home Page:https://docs.python.org/dev/library/unittest.mock.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

mock throws ValueError when spec_arg is an ndarray

valeriupredoi opened this issue · comments

What versions are you using?

  • Python: 3.9
  • Mock: 3.3.1; installed from PyPi
  • Operating System: Linux
  • import: from unittest import mock

What happened?

Hey guys, not sure this is the right place to report this (I tried upstream in GitHub/unittest but they turned off their Issues).
The latest version of mock.py has these at lines 411-412:

            if spec_arg and _is_async_obj(spec_arg):
                bases = (AsyncMockMixin, cls)

which throws an exception if spec_arg is an ndarray:

_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
esmvalcore/preprocessor/_regrid_esmpy.py:88: in get_grid
    grid = ESMF.Grid(np.array(esmpy_lat.shape),
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'tests.unit.preprocessor._regrid_esmpy.test_regrid_esmpy.MockGrid'>, args = (array([4, 4]),)
kw = {'num_peri_dims': 0, 'staggerloc': [sentinel.sl_center]}
bases = (<class 'tests.unit.preprocessor._regrid_esmpy.test_regrid_esmpy.MockGrid'>,)
bound_args = {'kwargs': {'num_peri_dims': 0, 'staggerloc': [sentinel.sl_center]}, 'self': <class 'tests.unit.preprocessor._regrid_esmpy.test_regrid_esmpy.MockGrid'>, 'spec': array([4, 4])}
spec_arg = array([4, 4])

    def __new__(cls, /, *args, **kw):
        # every instance has its own class
        # so we can create magic methods on the
        # class without stomping on other mocks
        bases = (cls,)
        if not issubclass(cls, AsyncMockMixin):
            # Check if spec is an async object or function
            bound_args = _MOCK_SIG.bind_partial(cls, *args, **kw).arguments
            spec_arg = bound_args.get('spec_set', bound_args.get('spec'))
>           if spec_arg and _is_async_obj(spec_arg):
E           ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

in a previous older version, spec_arg was constructed as a list so things were going well. Is this a bug or an intended feature? Cheers muchly for your help 🍺

Can you please test this with unittest.mock from python 3.9? Mock is a backport of the changes made in stdlib. Most probably it's an issue upstream that needs to be fixed and backported here.

@tirkarthi cheers for your reply! this is the Python 3.9 unittest mock, that's why I added the way we import it in the test, the exception is raised like this:

>           if spec_arg and _is_async_obj(spec_arg):
E           ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

../miniconda3/envs/esmvalcore39-3/lib/python3.9/unittest/mock.py:409: ValueError

and a bit more info:

(esmvalcore39-3) valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ conda list mock
# packages in environment at /home/valeriu/miniconda3/envs/esmvalcore39-3:
#
# Name                    Version                   Build  Channel
pytest-mock               3.3.1                    pypi_0    pypi

installing an using the actual package mock:

(esmvalcore39-3) valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ conda list mock
# packages in environment at /home/valeriu/miniconda3/envs/esmvalcore39-3:
#
# Name                    Version                   Build  Channel
mock                      4.0.2                    pypi_0    pypi
pytest-mock               3.3.1                    pypi_0    pypi

and changing to using it rather than the unittest.mock results in the same error:

spec_arg = array([4, 4])

    def __new__(cls, *args, **kw):
        # every instance has its own class
        # so we can create magic methods on the
        # class without stomping on other mocks
        bases = (cls,)
        if not issubclass(cls, AsyncMockMixin):
            # Check if spec is an async object or function
            bound_args = _MOCK_SIG.bind_partial(cls, *args, **kw).arguments
            spec_arg = bound_args.get('spec_set', bound_args.get('spec'))
>           if spec_arg and _is_async_obj(spec_arg):
E           ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

../miniconda3/envs/esmvalcore39-3/lib/python3.9/site-packages/mock/mock.py:411: ValueError

Please let me know what else should I try, cheers for your assistance 🍺

This package is a rolling backport of unittest.mock.
As such, any problems you encounter most likely need to be fixed upstream.

Please can you try and reproduce the problem on the latest release of Python 3, including alphas, and replace any import from mock with ones from unittest.mock.

If the issue still occurs, then please report upstream through https://bugs.python.org/ as it will need to be fixed there so that it can be backported here and released to you.

If not, reply with what you find out and we can re-open this issue.

Please can you try and reproduce the problem on the latest release of Python 3, including alphas, and replace any import from mock with ones from unittest.mock.

Cheers @cjw296 - we did just that, hence my posts above, mate! I will report upstream, cheers for your assistance - note however that the issue tracker for the package points here https://pypi.org/project/mock/ so you guys might want to add a descriptor note there saying that any issue should probably be first tested with unittest.mock and reported upstream - I find it a bit confusing if issues reported here get closed and bug reports need to be communicated upstream. Cheers, V 🍻