monkeypatch, doc, apiwarn, deprecation fixes

--HG--
branch : trunk
This commit is contained in:
holger krekel 2009-09-07 17:53:50 +02:00
parent 29d437489d
commit 0f29b503ef
9 changed files with 79 additions and 71 deletions

View File

@ -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'

View File

@ -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:

View File

@ -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"

View File

@ -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)

View File

@ -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

View File

@ -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"

View File

@ -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):

View File

@ -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)

View File

@ -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)