diff --git a/_pytest/__init__.py b/_pytest/__init__.py index c6d7f1f94..a5523727c 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '2.0.3.dev3' +__version__ = '2.0.3.dev4' diff --git a/_pytest/assertion.py b/_pytest/assertion.py index e2578242a..d40981c32 100644 --- a/_pytest/assertion.py +++ b/_pytest/assertion.py @@ -16,7 +16,8 @@ def pytest_configure(config): # py._code._assertionnew to detect this plugin was loaded and in # turn call the hooks defined here as part of the # DebugInterpreter. - config._monkeypatch = m = monkeypatch() + m = monkeypatch() + config._cleanup.append(m.undo) warn_about_missing_assertion() if not config.getvalue("noassert") and not config.getvalue("nomagic"): def callbinrepr(op, left, right): @@ -29,9 +30,6 @@ def pytest_configure(config): 'AssertionError', py.code._AssertionError) m.setattr(py.code, '_reprcompare', callbinrepr) -def pytest_unconfigure(config): - config._monkeypatch.undo() - def warn_about_missing_assertion(): try: assert False diff --git a/_pytest/config.py b/_pytest/config.py index 79a26afb4..6e0cfea1a 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -12,6 +12,10 @@ def pytest_cmdline_parse(pluginmanager, args): config.trace.root.setwriter(sys.stderr.write) return config +def pytest_unconfigure(config): + for func in config._cleanup: + func() + class Parser: """ Parser for command line arguments. """ @@ -251,7 +255,8 @@ class Config(object): self._conftest = Conftest(onimport=self._onimportconftest) self.hook = self.pluginmanager.hook self._inicache = {} - + self._cleanup = [] + @classmethod def fromdictargs(cls, option_dict, args): """ constructor useable for subprocesses. """ diff --git a/_pytest/tmpdir.py b/_pytest/tmpdir.py index 2fd9992cc..e46c713eb 100644 --- a/_pytest/tmpdir.py +++ b/_pytest/tmpdir.py @@ -48,15 +48,12 @@ class TempdirHandler: self.trace("finish") def pytest_configure(config): - config._mp = mp = monkeypatch() + mp = monkeypatch() t = TempdirHandler(config) + config._cleanup.extend([mp.undo, t.finish]) mp.setattr(config, '_tmpdirhandler', t, raising=False) mp.setattr(pytest, 'ensuretemp', t.ensuretemp, raising=False) -def pytest_unconfigure(config): - config._tmpdirhandler.finish() - config._mp.undo() - def pytest_funcarg__tmpdir(request): """return a temporary directory path object which is unique to each test function invocation, diff --git a/setup.py b/setup.py index 72cf5f98c..c1071a0d2 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ def main(): name='pytest', description='py.test: simple powerful testing with Python', long_description = long_description, - version='2.0.3.dev3', + version='2.0.3.dev4', url='http://pytest.org', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index f67eb2847..703647087 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -33,6 +33,19 @@ class TestGeneralUsage: '*INTERNALERROR*0 / 0*', ]) + def test_early_hook_configure_error_issue38(self, testdir): + testdir.makeconftest(""" + def pytest_configure(): + 0 / 0 + """) + result = testdir.runpytest(testdir.tmpdir) + assert result.ret != 0 + # here we get it on stderr + result.stderr.fnmatch_lines([ + '*INTERNALERROR*File*conftest.py*line 2*', + '*0 / 0*', + ]) + def test_file_not_found(self, testdir): result = testdir.runpytest("asd") assert result.ret != 0 diff --git a/testing/test_assertion.py b/testing/test_assertion.py index bee3903cf..9fa88d2e0 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -44,7 +44,8 @@ class TestBinReprIntegration: config = testdir.parseconfig() plugin.pytest_configure(config) assert hook != py.code._reprcompare - plugin.pytest_unconfigure(config) + from _pytest.config import pytest_unconfigure + pytest_unconfigure(config) assert hook == py.code._reprcompare def callequal(left, right):