diff --git a/_pytest/monkeypatch.py b/_pytest/monkeypatch.py index 5f9720f1f..97aa67c6c 100644 --- a/_pytest/monkeypatch.py +++ b/_pytest/monkeypatch.py @@ -5,7 +5,6 @@ import re from py.builtin import _basestring - RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$") @@ -32,7 +31,6 @@ def pytest_funcarg__monkeypatch(request): return mpatch - def derive_importpath(import_path, raising): import pytest if not isinstance(import_path, _basestring) or "." not in import_path: @@ -79,15 +77,17 @@ def derive_importpath(import_path, raising): return attr, obj - class Notset: def __repr__(self): return "" + notset = Notset() + class monkeypatch: """ Object keeping a record of setattr/item/env/syspath changes. """ + def __init__(self): self._setattr = [] self._setitem = [] @@ -114,14 +114,14 @@ class monkeypatch: if value is notset: if not isinstance(target, _basestring): raise TypeError("use setattr(target, name, value) or " - "setattr(target, value) with target being a dotted " - "import string") + "setattr(target, value) with target being a dotted " + "import string") value = name name, target = derive_importpath(target, raising) oldval = getattr(target, name, notset) if raising and oldval is notset: - raise AttributeError("%r has no attribute %r" %(target, name)) + raise AttributeError("%r has no attribute %r" % (target, name)) # avoid class descriptors like staticmethod/classmethod if inspect.isclass(target): @@ -233,7 +233,7 @@ class monkeypatch: try: del dictionary[name] except KeyError: - pass # was already deleted, so we have the desired state + pass # was already deleted, so we have the desired state else: dictionary[name] = value self._setitem[:] = [] diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 49db0bada..99437fe68 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -1,9 +1,11 @@ -import os, sys +import os +import sys import textwrap import pytest from _pytest.monkeypatch import monkeypatch as MonkeyPatch + def pytest_funcarg__mp(request): cwd = os.getcwd() sys_path = list(sys.path) @@ -15,9 +17,11 @@ def pytest_funcarg__mp(request): request.addfinalizer(cleanup) return MonkeyPatch() + def test_setattr(): class A: x = 1 + monkeypatch = MonkeyPatch() pytest.raises(AttributeError, "monkeypatch.setattr(A, 'notexists', 2)") monkeypatch.setattr(A, 'y', 2, raising=False) @@ -34,9 +38,10 @@ def test_setattr(): assert A.x == 1 A.x = 5 - monkeypatch.undo() # double-undo makes no modification + monkeypatch.undo() # double-undo makes no modification assert A.x == 5 + class TestSetattrWithImportPath: def test_string_expression(self, monkeypatch): monkeypatch.setattr("os.path.abspath", lambda x: "hello2") @@ -75,9 +80,11 @@ class TestSetattrWithImportPath: monkeypatch.undo() assert os.path.abspath + def test_delattr(): class A: x = 1 + monkeypatch = MonkeyPatch() monkeypatch.delattr(A, 'x') assert not hasattr(A, 'x') @@ -93,6 +100,7 @@ def test_delattr(): monkeypatch.undo() assert A.x == 1 + def test_setitem(): d = {'x': 1} monkeypatch = MonkeyPatch() @@ -110,6 +118,7 @@ def test_setitem(): monkeypatch.undo() assert d['x'] == 5 + def test_setitem_deleted_meanwhile(): d = {} monkeypatch = MonkeyPatch() @@ -118,6 +127,7 @@ def test_setitem_deleted_meanwhile(): monkeypatch.undo() assert not d + @pytest.mark.parametrize("before", [True, False]) def test_setenv_deleted_meanwhile(before): key = "qwpeoip123" @@ -133,6 +143,7 @@ def test_setenv_deleted_meanwhile(before): else: assert key not in os.environ + def test_delitem(): d = {'x': 1} monkeypatch = MonkeyPatch() @@ -149,6 +160,7 @@ def test_delitem(): monkeypatch.undo() assert d == {'hello': 'world', 'x': 1} + def test_setenv(): monkeypatch = MonkeyPatch() monkeypatch.setenv('XYZ123', 2) @@ -157,6 +169,7 @@ def test_setenv(): monkeypatch.undo() assert 'XYZ123' not in os.environ + def test_delenv(): name = 'xyz1234' assert name not in os.environ @@ -177,6 +190,7 @@ def test_delenv(): if name in os.environ: del os.environ[name] + def test_setenv_prepend(): import os monkeypatch = MonkeyPatch() @@ -187,6 +201,7 @@ def test_setenv_prepend(): monkeypatch.undo() assert 'XYZ123' not in os.environ + def test_monkeypatch_plugin(testdir): reprec = testdir.inline_runsource(""" def test_method(monkeypatch): @@ -195,6 +210,7 @@ def test_monkeypatch_plugin(testdir): res = reprec.countoutcomes() assert tuple(res) == (1, 0, 0), res + def test_syspath_prepend(mp): old = list(sys.path) mp.syspath_prepend('world') @@ -206,6 +222,7 @@ def test_syspath_prepend(mp): mp.undo() assert sys.path == old + def test_syspath_prepend_double_undo(mp): mp.syspath_prepend('hello world') mp.undo() @@ -213,20 +230,24 @@ def test_syspath_prepend_double_undo(mp): mp.undo() assert sys.path[-1] == 'more hello world' + def test_chdir_with_path_local(mp, tmpdir): mp.chdir(tmpdir) assert os.getcwd() == tmpdir.strpath + def test_chdir_with_str(mp, tmpdir): mp.chdir(tmpdir.strpath) assert os.getcwd() == tmpdir.strpath + def test_chdir_undo(mp, tmpdir): cwd = os.getcwd() mp.chdir(tmpdir) mp.undo() assert os.getcwd() == cwd + def test_chdir_double_undo(mp, tmpdir): mp.chdir(tmpdir.strpath) mp.undo() @@ -234,6 +255,7 @@ def test_chdir_double_undo(mp, tmpdir): mp.undo() assert os.getcwd() == tmpdir.strpath + def test_issue185_time_breaks(testdir): testdir.makepyfile(""" import time @@ -247,6 +269,7 @@ def test_issue185_time_breaks(testdir): *1 passed* """) + def test_importerror(testdir): p = testdir.mkpydir("package") p.join("a.py").write(textwrap.dedent("""\ @@ -275,11 +298,12 @@ class SampleNewInherit(SampleNew): class SampleOld: - #oldstyle on python2 + # oldstyle on python2 @staticmethod def hello(): return True + class SampleOldInherit(SampleOld): pass @@ -296,5 +320,3 @@ def test_issue156_undo_staticmethod(Sample): monkeypatch.undo() assert Sample.hello() - -