monkeypatch, doc, apiwarn, deprecation fixes
--HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									29d437489d
								
							
						
					
					
						commit
						0f29b503ef
					
				|  | @ -148,7 +148,7 @@ def getrealname(username): | |||
|      | ||||
| 
 | ||||
| class Project: | ||||
|     mydir = py.magic.autopath().dirpath() | ||||
|     mydir = py.path.local(__file__).dirpath() | ||||
|     title = "py lib" | ||||
|     prefix_title = ""  # we have a logo already containing "py lib" | ||||
|     encoding = 'latin1'  | ||||
|  |  | |||
|  | @ -10,7 +10,8 @@ | |||
| using easy_install  | ||||
| =================================================== | ||||
| 
 | ||||
| With a working `setuptools installation`_ you can type:: | ||||
| With a working `setuptools installation`_ or `distribute installation`_  | ||||
| you can type:: | ||||
| 
 | ||||
|     easy_install -U py  | ||||
| 
 | ||||
|  | @ -19,19 +20,11 @@ will trigger an upgrade if you already have an older version installed. | |||
| On Linux systems you may need to execute the command as superuser and | ||||
| on Windows you might need to write down the full path to ``easy_install``.  | ||||
| The py lib and its tools are expected to work well on Linux, | ||||
| Windows and OSX, Python versions 2.3, 2.4, 2.5 and 2.6. | ||||
| 
 | ||||
| **IMPORTANT NOTE**: if you are using Windows and have  | ||||
| 0.8 versions of the py lib on your system, please download  | ||||
| and execute http://codespeak.net/svn/py/build/winpathclean.py | ||||
| This will check that no previous files are getting in the way.  | ||||
| You can find out the py lib version with:: | ||||
| 
 | ||||
|     import py | ||||
|     print py.version | ||||
| 
 | ||||
| Windows and OSX, Python versions 2.4, 2.5, 2.6 through to | ||||
| the Python3 versions 3.0 and 3.1.  | ||||
| 
 | ||||
| .. _mercurial: http://mercurial.selenic.com/wiki/ | ||||
| .. _`distribute installation`: http://pypi.python.org/pypi/distribute | ||||
| .. _checkout: | ||||
| .. _tarball: | ||||
| 
 | ||||
|  |  | |||
|  | @ -74,8 +74,7 @@ per-test capturing.  Here is an example test function: | |||
| 
 | ||||
|     def test_myoutput(capsys): | ||||
|         print ("hello") | ||||
|         sys.stderr.write("world | ||||
| ") | ||||
|         sys.stderr.write("world\n") | ||||
|         out, err = capsys.readouterr() | ||||
|         assert out == "hello\n" | ||||
|         assert err == "world\n" | ||||
|  |  | |||
|  | @ -7,49 +7,54 @@ safely patch object attributes, dicts and environment variables. | |||
| .. contents:: | ||||
|   :local: | ||||
| 
 | ||||
| Usage | ||||
| Usage  | ||||
| ---------------- | ||||
| 
 | ||||
| Use the `monkeypatch funcarg`_ to safely modify or delete environment | ||||
| variables, object attributes or dictionary values.  For example, if you want | ||||
| to set the environment variable ``ENV1`` and patch the | ||||
| ``os.path.abspath`` function to return a particular value during a test | ||||
| function execution you can write it down like this: | ||||
| Use the `monkeypatch funcarg`_ to tweak your global test environment  | ||||
| for running a particular test.  You can safely set/del an attribute,  | ||||
| dictionary item or environment variable by respective methods | ||||
| on the monkeypatch funcarg.  If you want e.g. to set an ENV1 variable  | ||||
| and have os.path.expanduser return a particular directory, you can  | ||||
| write it down like this: | ||||
| 
 | ||||
| .. sourcecode:: python  | ||||
| 
 | ||||
|     def test_mytest(monkeypatch): | ||||
|         monkeypatch.setenv('ENV1', 'myval') | ||||
|         monkeypatch.setattr(os.path, 'abspath', lambda x: '/') | ||||
|         ... # your test code  | ||||
|         monkeypatch.setattr(os.path, 'expanduser', lambda x: '/tmp/xyz') | ||||
|         ... # your test code that uses those patched values implicitely | ||||
| 
 | ||||
| The function argument will do the modifications and memorize the  | ||||
| old state.  After the test function finished execution all  | ||||
| modifications will be reverted.  See the `monkeypatch blog post`_  | ||||
| for an extensive discussion.   | ||||
| After the test function finished all modifications will be undone,  | ||||
| because the ``monkeypatch.undo()`` method is registered as a finalizer.  | ||||
| 
 | ||||
| To add to a possibly existing environment parameter you | ||||
| can use this example:  | ||||
| ``monkeypatch.setattr/delattr/delitem/delenv()`` all  | ||||
| by default raise an Exception if the target does not exist.  | ||||
| Pass ``raising=False`` if you want to skip this check.  | ||||
| 
 | ||||
| prepending to PATH or other environment variables  | ||||
| --------------------------------------------------------- | ||||
| 
 | ||||
| To prepend a value to an already existing environment parameter: | ||||
| 
 | ||||
| .. sourcecode:: python  | ||||
| 
 | ||||
|     def test_mypath_finding(monkeypatch): | ||||
|         monkeypatch.setenv('PATH', 'x/y', prepend=":") | ||||
|         #  x/y will be at the beginning of $PATH  | ||||
|         # in bash language: export PATH=x/y:$PATH  | ||||
| 
 | ||||
| calling "undo" finalization explicitely | ||||
| ----------------------------------------- | ||||
| 
 | ||||
| Usually at the end of function execution py.test will invoke | ||||
| a teardown hook which undoes the changes.  If you cannot wait | ||||
| that long you can also call finalization explicitely:: | ||||
| At the end of function execution py.test invokes | ||||
| a teardown hook which undoes all monkeypatch changes.  | ||||
| If you do not want to wait that long you can call  | ||||
| finalization explicitely:: | ||||
| 
 | ||||
|     monkeypatch.undo()   | ||||
| 
 | ||||
| This will undo previous changes.  This call consumes the | ||||
| undo stack.  Calling it a second time has no effect.  | ||||
| Within a test you can continue to use the monkeypatch  | ||||
| object, however.  | ||||
| undo stack.  Calling it a second time has no effect unless | ||||
| you  start monkeypatching after the undo call.  | ||||
| 
 | ||||
| .. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/ | ||||
| 
 | ||||
|  | @ -62,7 +67,7 @@ the 'monkeypatch' test function argument | |||
| The returned ``monkeypatch`` funcarg provides these  | ||||
| helper methods to modify objects, dictionaries or os.environ:: | ||||
| 
 | ||||
|     monkeypatch.setattr(obj, name, value)   | ||||
|     monkeypatch.setattr(obj, name, value, raising=True)   | ||||
|     monkeypatch.delattr(obj, name, raising=True) | ||||
|     monkeypatch.setitem(mapping, name, value)  | ||||
|     monkeypatch.delitem(obj, name, raising=True) | ||||
|  |  | |||
|  | @ -10,11 +10,11 @@ class Warning(DeprecationWarning): | |||
|     def __str__(self): | ||||
|         return self.msg  | ||||
| 
 | ||||
| def _apiwarn(startversion, msg, stacklevel=1, function=None): | ||||
| def _apiwarn(startversion, msg, stacklevel=2, function=None): | ||||
|     # below is mostly COPIED from python2.4/warnings.py's def warn() | ||||
|     # Get context information | ||||
|     if stacklevel == "initpkg": | ||||
|         frame = sys._getframe(1) | ||||
|         frame = sys._getframe(stacklevel == "initpkg" and 1 or stacklevel) | ||||
|         level = 2 | ||||
|         while frame: | ||||
|             co = frame.f_code | ||||
|  |  | |||
|  | @ -68,7 +68,7 @@ per-test capturing.  Here is an example test function: | |||
| 
 | ||||
|     def test_myoutput(capsys): | ||||
|         print ("hello") | ||||
|         sys.stderr.write("world\n") | ||||
|         sys.stderr.write("world\\n") | ||||
|         out, err = capsys.readouterr() | ||||
|         assert out == "hello\\n" | ||||
|         assert err == "world\\n" | ||||
|  |  | |||
|  | @ -1,49 +1,54 @@ | |||
| """ | ||||
| safely patch object attributes, dicts and environment variables.  | ||||
| 
 | ||||
| Usage | ||||
| Usage  | ||||
| ---------------- | ||||
| 
 | ||||
| Use the `monkeypatch funcarg`_ to safely modify or delete environment | ||||
| variables, object attributes or dictionary values.  For example, if you want | ||||
| to set the environment variable ``ENV1`` and patch the | ||||
| ``os.path.abspath`` function to return a particular value during a test | ||||
| function execution you can write it down like this: | ||||
| Use the `monkeypatch funcarg`_ to tweak your global test environment  | ||||
| for running a particular test.  You can safely set/del an attribute,  | ||||
| dictionary item or environment variable by respective methods | ||||
| on the monkeypatch funcarg.  If you want e.g. to set an ENV1 variable  | ||||
| and have os.path.expanduser return a particular directory, you can  | ||||
| write it down like this: | ||||
| 
 | ||||
| .. sourcecode:: python  | ||||
| 
 | ||||
|     def test_mytest(monkeypatch): | ||||
|         monkeypatch.setenv('ENV1', 'myval') | ||||
|         monkeypatch.setattr(os.path, 'abspath', lambda x: '/') | ||||
|         ... # your test code  | ||||
|         monkeypatch.setattr(os.path, 'expanduser', lambda x: '/tmp/xyz') | ||||
|         ... # your test code that uses those patched values implicitely | ||||
| 
 | ||||
| The function argument will do the modifications and memorize the  | ||||
| old state.  After the test function finished execution all  | ||||
| modifications will be reverted.  See the `monkeypatch blog post`_  | ||||
| for an extensive discussion.   | ||||
| After the test function finished all modifications will be undone,  | ||||
| because the ``monkeypatch.undo()`` method is registered as a finalizer.  | ||||
| 
 | ||||
| To add to a possibly existing environment parameter you | ||||
| can use this example:  | ||||
| ``monkeypatch.setattr/delattr/delitem/delenv()`` all  | ||||
| by default raise an Exception if the target does not exist.  | ||||
| Pass ``raising=False`` if you want to skip this check.  | ||||
| 
 | ||||
| prepending to PATH or other environment variables  | ||||
| --------------------------------------------------------- | ||||
| 
 | ||||
| To prepend a value to an already existing environment parameter: | ||||
| 
 | ||||
| .. sourcecode:: python  | ||||
| 
 | ||||
|     def test_mypath_finding(monkeypatch): | ||||
|         monkeypatch.setenv('PATH', 'x/y', prepend=":") | ||||
|         #  x/y will be at the beginning of $PATH  | ||||
|         # in bash language: export PATH=x/y:$PATH  | ||||
| 
 | ||||
| calling "undo" finalization explicitely | ||||
| ----------------------------------------- | ||||
| 
 | ||||
| Usually at the end of function execution py.test will invoke | ||||
| a teardown hook which undoes the changes.  If you cannot wait | ||||
| that long you can also call finalization explicitely:: | ||||
| At the end of function execution py.test invokes | ||||
| a teardown hook which undoes all monkeypatch changes.  | ||||
| If you do not want to wait that long you can call  | ||||
| finalization explicitely:: | ||||
| 
 | ||||
|     monkeypatch.undo()   | ||||
| 
 | ||||
| This will undo previous changes.  This call consumes the | ||||
| undo stack.  Calling it a second time has no effect.  | ||||
| Within a test you can continue to use the monkeypatch  | ||||
| object, however.  | ||||
| undo stack.  Calling it a second time has no effect unless | ||||
| you  start monkeypatching after the undo call.  | ||||
| 
 | ||||
| .. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/ | ||||
| """ | ||||
|  | @ -54,7 +59,7 @@ def pytest_funcarg__monkeypatch(request): | |||
|     """The returned ``monkeypatch`` funcarg provides these  | ||||
|     helper methods to modify objects, dictionaries or os.environ:: | ||||
| 
 | ||||
|         monkeypatch.setattr(obj, name, value)   | ||||
|         monkeypatch.setattr(obj, name, value, raising=True)   | ||||
|         monkeypatch.delattr(obj, name, raising=True) | ||||
|         monkeypatch.setitem(mapping, name, value)  | ||||
|         monkeypatch.delitem(obj, name, raising=True) | ||||
|  | @ -79,8 +84,11 @@ class MonkeyPatch: | |||
|         self._setattr = [] | ||||
|         self._setitem = [] | ||||
| 
 | ||||
|     def setattr(self, obj, name, value): | ||||
|         self._setattr.insert(0, (obj, name, getattr(obj, name, notset))) | ||||
|     def setattr(self, obj, name, value, raising=True): | ||||
|         oldval = getattr(obj, name, notset) | ||||
|         if raising and oldval is notset: | ||||
|             raise AttributeError("%r has no attribute %r" %(obj, name)) | ||||
|         self._setattr.insert(0, (obj, name, oldval)) | ||||
|         setattr(obj, name, value) | ||||
| 
 | ||||
|     def delattr(self, obj, name, raising=True): | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ def test_forwarding_to_warnings_module(): | |||
| 
 | ||||
| def test_apiwarn_functional(): | ||||
|     capture = py.io.StdCapture() | ||||
|     py.log._apiwarn("x.y.z", "something") | ||||
|     py.log._apiwarn("x.y.z", "something", stacklevel=1) | ||||
|     out, err = capture.reset() | ||||
|     py.builtin.print_("out", out) | ||||
|     py.builtin.print_("err", err) | ||||
|  |  | |||
|  | @ -5,6 +5,13 @@ from py.__.test.plugin.pytest_monkeypatch import MonkeyPatch | |||
| def test_setattr(): | ||||
|     class A: | ||||
|         x = 1 | ||||
|     monkeypatch = MonkeyPatch() | ||||
|     py.test.raises(AttributeError, "monkeypatch.setattr(A, 'notexists', 2)") | ||||
|     monkeypatch.setattr(A, 'y', 2, raising=False) | ||||
|     assert A.y == 2 | ||||
|     monkeypatch.undo() | ||||
|     assert not hasattr(A, 'y') | ||||
| 
 | ||||
|     monkeypatch = MonkeyPatch() | ||||
|     monkeypatch.setattr(A, 'x', 2) | ||||
|     assert A.x == 2 | ||||
|  | @ -17,11 +24,6 @@ def test_setattr(): | |||
|     monkeypatch.undo() # double-undo makes no modification | ||||
|     assert A.x == 5 | ||||
| 
 | ||||
|     monkeypatch.setattr(A, 'y', 3) | ||||
|     assert A.y == 3 | ||||
|     monkeypatch.undo() | ||||
|     assert not hasattr(A, 'y') | ||||
|       | ||||
| def test_delattr(): | ||||
|     class A: | ||||
|         x = 1 | ||||
|  | @ -35,7 +37,7 @@ def test_delattr(): | |||
|     monkeypatch.delattr(A, 'x') | ||||
|     py.test.raises(AttributeError, "monkeypatch.delattr(A, 'y')") | ||||
|     monkeypatch.delattr(A, 'y', raising=False) | ||||
|     monkeypatch.setattr(A, 'x', 5) | ||||
|     monkeypatch.setattr(A, 'x', 5, raising=False) | ||||
|     assert A.x == 5 | ||||
|     monkeypatch.undo() | ||||
|     assert A.x == 1 | ||||
|  | @ -45,6 +47,7 @@ def test_setitem(): | |||
|     monkeypatch = MonkeyPatch() | ||||
|     monkeypatch.setitem(d, 'x', 2) | ||||
|     monkeypatch.setitem(d, 'y', 1700) | ||||
|     monkeypatch.setitem(d, 'y', 1700) | ||||
|     assert d['x'] == 2 | ||||
|     assert d['y'] == 1700 | ||||
|     monkeypatch.setitem(d, 'x', 3) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue