Closed rtaft closed 4 years ago
Why 4.0.0 rather than 4.0.2? What happens if you try and latest Python 3 release rather than 3.6?
(Trying to find out where the change was introduced, rather than telling you to use either of these things for ever...)
I started at the latest and moved back to 4.0.0 trying to track down when it was introduced. It also happens on python 3.8.0. For this setup I used pyenv to install python 3.8
$ ~/pyenv/shims/python3.8 -m venv p3venv
$ . ./p3venv/bin/activate
$ python --version
Python 3.8.0
$ pip install mock pytest flask
... install output ...
$ pytest temp_test.py
============================================================================================================ test session starts =============================================================================================================
platform linux -- Python 3.8.0, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: /home/rtaft/testpath, inifile: pytest.ini
collected 1 item
temp_test.py F [100%]
================================================================================================================== FAILURES ==================================================================================================================
_____________________________________________________________________________________________________________ test_some_function _____________________________________________________________________________________________________________
args = (), keywargs = {}
@wraps(func)
def patched(*args, **keywargs):
> with self.decoration_helper(patched,
args,
keywargs) as (newargs, newkeywargs):
p3venv/lib/python3.8/site-packages/mock/mock.py:1366:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../../../pyenv/versions/3.8.0/lib/python3.8/contextlib.py:113: in __enter__
return next(self.gen)
p3venv/lib/python3.8/site-packages/mock/mock.py:1334: in decoration_helper
arg = patching.__enter__()
p3venv/lib/python3.8/site-packages/mock/mock.py:1460: in __enter__
if spec is None and _is_async_obj(original):
p3venv/lib/python3.8/site-packages/mock/mock.py:52: in _is_async_obj
if hasattr(obj, '__func__'):
p3venv/lib/python3.8/site-packages/werkzeug/local.py:347: in __getattr__
return getattr(self._get_current_object(), name)
p3venv/lib/python3.8/site-packages/werkzeug/local.py:306: in _get_current_object
return self.__local()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
name = 'g'
def _lookup_app_object(name):
top = _app_ctx_stack.top
if top is None:
> raise RuntimeError(_app_ctx_err_msg)
E RuntimeError: Working outside of application context.
E
E This typically means that you attempted to use functionality that needed
E to interface with the current application object in some way. To solve
E this, set up an application context with app.app_context(). See the
E documentation for more information.
p3venv/lib/python3.8/site-packages/flask/globals.py:45: RuntimeError
========================================================================================================== short test summary info ===========================================================================================================
FAILED temp_test.py::test_some_function - RuntimeError: Working outside of application context.
============================================================================================================= 1 failed in 0.28s ==============================================================================================================
Okay, this looks like an upstream bug, please can you file on https://bugs.python.org/? (A link to this issue may well suffice!) I'll close this issue, but if you can ping a link to the bugs.python.org issue on here once submitted, it may help others.
Once it's fixed upstream, I can roll another backport release to get you the fix.
@cjw296 Why do you believe this is an upstream bug? They pushed back and said it is not. Replacing mock with the upstream unittest.mock works without issues.
I'm afraid @terryjreedy's comment wasn't very helpful, please see my followup.
But, also, you need to replace mock
with unittest.mock
in your imports if you're asked to try and reproduce against upstream.
Why do I believe this is an upstream bug? Because this repo us a rolling backport of cpython's unittest.mock, so bugs, unless specifically in backporting changes, are going to be in the upstream cpython repo and need to be fixed there, not here.
I was able to reproduce this with python 3.8.3 and 3.9-dev with just unittest.mock
. I only tested 3.6 before.
The issue is that in 3.8 support was added for mocking async code. This is done by checking if the thing to mock has a __func__
attribute:
/usr/lib/python3.8/unittest/mock.py:51: in _is_async_obj
if hasattr(obj, '__func__'):
This triggers flask code since flask overrides __getattr__
. The fix is probably that flask need to ignore __getattr__
calls for __func__
and return an Error instead of trying to start flask magic..
As a workaround set the spec
attribute while patching (anything will probably work but using the correct value is best)
@patch('flask.g', spec={})
def test_some_function(mock_flask_global):
assert some_function()
After upgrading from mock 3.0.5 to 4.0.0, I am no longer able to patch
flask.g
This raises the error: