Merge remote-tracking branch 'upstream/features' into features
This commit is contained in:
		
						commit
						e44d4e6508
					
				| 
						 | 
					@ -4,6 +4,8 @@ from __future__ import absolute_import, division, print_function
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					from contextlib import contextmanager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import six
 | 
					import six
 | 
				
			||||||
from _pytest.fixtures import fixture
 | 
					from _pytest.fixtures import fixture
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,6 +108,29 @@ class MonkeyPatch(object):
 | 
				
			||||||
        self._cwd = None
 | 
					        self._cwd = None
 | 
				
			||||||
        self._savesyspath = None
 | 
					        self._savesyspath = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @contextmanager
 | 
				
			||||||
 | 
					    def context(self):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        Context manager that returns a new :class:`MonkeyPatch` object which
 | 
				
			||||||
 | 
					        undoes any patching done inside the ``with`` block upon exit:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        .. code-block:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            import functools
 | 
				
			||||||
 | 
					            def test_partial(monkeypatch):
 | 
				
			||||||
 | 
					                with monkeypatch.context() as m:
 | 
				
			||||||
 | 
					                    m.setattr(functools, "partial", 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Useful in situations where it is desired to undo some patches before the test ends,
 | 
				
			||||||
 | 
					        such as mocking ``stdlib`` functions that might break pytest itself if mocked (for examples
 | 
				
			||||||
 | 
					        of this see `#3290 <https://github.com/pytest-dev/pytest/issues/3290>`_.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        m = MonkeyPatch()
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            yield m
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            m.undo()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def setattr(self, target, name, value=notset, raising=True):
 | 
					    def setattr(self, target, name, value=notset, raising=True):
 | 
				
			||||||
        """ Set attribute value on target, memorizing the old value.
 | 
					        """ Set attribute value on target, memorizing the old value.
 | 
				
			||||||
        By default raise AttributeError if the attribute did not exist.
 | 
					        By default raise AttributeError if the attribute did not exist.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					``monkeypatch`` now supports a ``context()`` function which acts as a context manager which undoes all patching done
 | 
				
			||||||
 | 
					within the ``with`` block.
 | 
				
			||||||
| 
						 | 
					@ -61,6 +61,22 @@ so that any attempts within tests to create http requests will fail.
 | 
				
			||||||
    ``compile``, etc., because it might break pytest's internals. If that's
 | 
					    ``compile``, etc., because it might break pytest's internals. If that's
 | 
				
			||||||
    unavoidable, passing ``--tb=native``, ``--assert=plain`` and ``--capture=no`` might 
 | 
					    unavoidable, passing ``--tb=native``, ``--assert=plain`` and ``--capture=no`` might 
 | 
				
			||||||
    help although there's no guarantee.
 | 
					    help although there's no guarantee.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. note::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Mind that patching ``stdlib`` functions and some third-party libraries used by pytest
 | 
				
			||||||
 | 
					    might break pytest itself, therefore in those cases it is recommended to use
 | 
				
			||||||
 | 
					    :meth:`MonkeyPatch.context` to limit the patching to the block you want tested:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .. code-block:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        import functools
 | 
				
			||||||
 | 
					        def test_partial(monkeypatch):
 | 
				
			||||||
 | 
					            with monkeypatch.context() as m:
 | 
				
			||||||
 | 
					                m.setattr(functools, "partial", 3)
 | 
				
			||||||
 | 
					                assert functools.partial == 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    See issue `#3290 <https://github.com/pytest-dev/pytest/issues/3290>`_ for details.
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. currentmodule:: _pytest.monkeypatch
 | 
					.. currentmodule:: _pytest.monkeypatch
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -327,3 +327,15 @@ def test_issue1338_name_resolving():
 | 
				
			||||||
        monkeypatch.delattr('requests.sessions.Session.request')
 | 
					        monkeypatch.delattr('requests.sessions.Session.request')
 | 
				
			||||||
    finally:
 | 
					    finally:
 | 
				
			||||||
        monkeypatch.undo()
 | 
					        monkeypatch.undo()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_context():
 | 
				
			||||||
 | 
					    monkeypatch = MonkeyPatch()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    import functools
 | 
				
			||||||
 | 
					    import inspect
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with monkeypatch.context() as m:
 | 
				
			||||||
 | 
					        m.setattr(functools, "partial", 3)
 | 
				
			||||||
 | 
					        assert not inspect.isclass(functools.partial)
 | 
				
			||||||
 | 
					    assert inspect.isclass(functools.partial)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue