diff --git a/_pytest/assertion/__init__.py b/_pytest/assertion/__init__.py index fdc279387..c6039a0ec 100644 --- a/_pytest/assertion/__init__.py +++ b/_pytest/assertion/__init__.py @@ -60,7 +60,7 @@ def pytest_configure(config): def pytest_unconfigure(config): hook = config._assertstate.hook - if hook is not None: + if hook is not None and hook in sys.meta_path: sys.meta_path.remove(hook) def pytest_collection(session): diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 121121fb8..4bd7f30b9 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -482,6 +482,22 @@ def test_rewritten(): assert "@py_builtins" in globals()""".replace("\n", "\r\n"), "wb") assert testdir.runpytest().ret == 0 + def test_sys_meta_path_munged(self, testdir): + # In some versions, if any code messed with sys.meta_path and removed + # the assertionrewrite import hook (one example is CaptureMock), it + # would cause an error on py.test exit: + # + # File "/Users/marca/dev/hg-repos/pytest/_pytest/assertion/__init__.py", line 64, in pytest_unconfigure + # sys.meta_path.remove(hook) + # ValueError: list.remove(x): x not in list + # + testdir.tmpdir.join("test_meta_path.py").write("""#!/usr/bin/env python +def test_meta_path(): + import sys + sys.meta_path = [] + assert True""".replace("\n", "\r\n"), "wb") + assert testdir.runpytest().ret == 0 + def test_write_pyc(self, testdir, tmpdir, monkeypatch): from _pytest.assertion.rewrite import _write_pyc from _pytest.assertion import AssertionState