Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.Sign up
Running ipytest.main multiple times triggers rewrite warnings for plugins #5432
pip install pytest pytest_asyncio
import pytest pytest.main() pytest.main()
My real use case is: I'm using ipytest (I'm also the author) to run tests inside jupyter notebooks with pytest. Internally,
changed the title
Running `ipytest.main` multiple times triggers rewrite warnings for plugins
Jun 10, 2019
This usage pattern is at least not recommend which probably puts this into not supported / wontfix territory?
Tracing this, what happens is as follows:
The only way I could think of "fixing" this would be to attach some information to the actual modules themselves to identify that pytest rewrote them. It seems there's ~kind of this information already in the
this gets it closer:
diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index ce698f368..38b0b43de 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -260,6 +260,10 @@ class AssertionRewritingHook: from _pytest.warning_types import PytestAssertRewriteWarning from _pytest.warnings import _issue_warning_captured + # we already imported this (multiple invocations of pytest.main()?) + if isinstance(sys.modules[name].__loader__, type(self)): + return + _issue_warning_captured( PytestAssertRewriteWarning( "Module already imported so cannot be rewritten: %s" % name
but it seems that pytest currently doesn't know how to rewrite "packages" (by packages, I mean directories containing
$ python t.py t2.py ============================= test session starts ============================== platform linux -- Python 3.6.7, pytest-4.6.1.dev84+g40c5a9d9f, py-1.8.0, pluggy-0.12.0 rootdir: /tmp/t plugins: asyncio-0.10.0 collected 1 item t2.py . [100%] =========================== 1 passed in 0.01 seconds =========================== ============================= test session starts ============================== platform linux -- Python 3.6.7, pytest-4.6.1.dev84+g40c5a9d9f, py-1.8.0, pluggy-0.12.0 rootdir: /tmp/t plugins: asyncio-0.10.0 collected 1 item t2.py . [100%] =============================== warnings summary =============================== pytest/src/_pytest/config/__init__.py:768 pytest/src/_pytest/config/__init__.py:768 /tmp/t/pytest/src/_pytest/config/__init__.py:768: PytestAssertRewriteWarning: Module already imported so cannot be rewritten: pytest_asyncio self._mark_plugins_for_rewrite(hook) -- Docs: https://docs.pytest.org/en/latest/warnings.html ===================== 1 passed, 2 warnings in 0.01 seconds =====================
Thanks a lot for the detailed analysis. I figured / feared that this issue would maybe fall into the won't fix category. In that case, I will investigate how to either supress the warnings (however #4439 seems to be a blocker) or how to re-expose the information of the previous assert rewrite hook between calls.
I just wanted to confirm this is expected behavior, before I go down that route. So either way, I'm good, whatever the official position is.
Quick update: thanks to your detailed trace of what happens, I figure out one solution: by monkey patching
I will for now implement a quick fix on my side. Please just close this issue, if this is a wont-fix for you.
import sys from _pytest import assertion from _pytest.assertion import rewrite, AssertionState def custom_install_importhook(config): """Try to install the rewrite hook, raise SystemError if it fails.""" config._assertstate = AssertionState(config, "rewrite") installed = any( isinstance(hook, rewrite.AssertionRewritingHook) for hook in sys.meta_path ) if not installed: config._assertstate.hook = hook = rewrite.AssertionRewritingHook(config) sys.meta_path.insert(0, hook) config._assertstate.trace("installed rewrite import hook") else: hook, = [hook for hook in sys.meta_path if isinstance(hook, rewrite.AssertionRewritingHook)] config._assertstate.hook = hook return hook assertion.install_importhook = custom_install_importhook