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