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: class Project:
mydir = py.magic.autopath().dirpath() mydir = py.path.local(__file__).dirpath()
title = "py lib" title = "py lib"
prefix_title = "" # we have a logo already containing "py lib" prefix_title = "" # we have a logo already containing "py lib"
encoding = 'latin1' encoding = 'latin1'

View File

@ -10,7 +10,8 @@
using easy_install 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 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 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``. 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, 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. Windows and OSX, Python versions 2.4, 2.5, 2.6 through to
the Python3 versions 3.0 and 3.1.
**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
.. _mercurial: http://mercurial.selenic.com/wiki/ .. _mercurial: http://mercurial.selenic.com/wiki/
.. _`distribute installation`: http://pypi.python.org/pypi/distribute
.. _checkout: .. _checkout:
.. _tarball: .. _tarball:

View File

@ -74,8 +74,7 @@ per-test capturing. Here is an example test function:
def test_myoutput(capsys): def test_myoutput(capsys):
print ("hello") print ("hello")
sys.stderr.write("world sys.stderr.write("world\n")
")
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert out == "hello\n" assert out == "hello\n"
assert err == "world\n" assert err == "world\n"

View File

@ -10,46 +10,51 @@ safely patch object attributes, dicts and environment variables.
Usage Usage
---------------- ----------------
Use the `monkeypatch funcarg`_ to safely modify or delete environment Use the `monkeypatch funcarg`_ to tweak your global test environment
variables, object attributes or dictionary values. For example, if you want for running a particular test. You can safely set/del an attribute,
to set the environment variable ``ENV1`` and patch the dictionary item or environment variable by respective methods
``os.path.abspath`` function to return a particular value during a test on the monkeypatch funcarg. If you want e.g. to set an ENV1 variable
function execution you can write it down like this: and have os.path.expanduser return a particular directory, you can
write it down like this:
.. sourcecode:: python .. sourcecode:: python
def test_mytest(monkeypatch): def test_mytest(monkeypatch):
monkeypatch.setenv('ENV1', 'myval') monkeypatch.setenv('ENV1', 'myval')
monkeypatch.setattr(os.path, 'abspath', lambda x: '/') monkeypatch.setattr(os.path, 'expanduser', lambda x: '/tmp/xyz')
... # your test code ... # your test code that uses those patched values implicitely
The function argument will do the modifications and memorize the After the test function finished all modifications will be undone,
old state. After the test function finished execution all because the ``monkeypatch.undo()`` method is registered as a finalizer.
modifications will be reverted. See the `monkeypatch blog post`_
for an extensive discussion.
To add to a possibly existing environment parameter you ``monkeypatch.setattr/delattr/delitem/delenv()`` all
can use this example: 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 .. sourcecode:: python
def test_mypath_finding(monkeypatch): def test_mypath_finding(monkeypatch):
monkeypatch.setenv('PATH', 'x/y', prepend=":") 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 calling "undo" finalization explicitely
----------------------------------------- -----------------------------------------
Usually at the end of function execution py.test will invoke At the end of function execution py.test invokes
a teardown hook which undoes the changes. If you cannot wait a teardown hook which undoes all monkeypatch changes.
that long you can also call finalization explicitely:: If you do not want to wait that long you can call
finalization explicitely::
monkeypatch.undo() monkeypatch.undo()
This will undo previous changes. This call consumes the This will undo previous changes. This call consumes the
undo stack. Calling it a second time has no effect. undo stack. Calling it a second time has no effect unless
Within a test you can continue to use the monkeypatch you start monkeypatching after the undo call.
object, however.
.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/ .. _`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 The returned ``monkeypatch`` funcarg provides these
helper methods to modify objects, dictionaries or os.environ:: 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.delattr(obj, name, raising=True)
monkeypatch.setitem(mapping, name, value) monkeypatch.setitem(mapping, name, value)
monkeypatch.delitem(obj, name, raising=True) monkeypatch.delitem(obj, name, raising=True)

View File

@ -10,11 +10,11 @@ class Warning(DeprecationWarning):
def __str__(self): def __str__(self):
return self.msg 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() # below is mostly COPIED from python2.4/warnings.py's def warn()
# Get context information # Get context information
if stacklevel == "initpkg": if stacklevel == "initpkg":
frame = sys._getframe(1) frame = sys._getframe(stacklevel == "initpkg" and 1 or stacklevel)
level = 2 level = 2
while frame: while frame:
co = frame.f_code co = frame.f_code

View File

@ -68,7 +68,7 @@ per-test capturing. Here is an example test function:
def test_myoutput(capsys): def test_myoutput(capsys):
print ("hello") print ("hello")
sys.stderr.write("world\n") sys.stderr.write("world\\n")
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert out == "hello\\n" assert out == "hello\\n"
assert err == "world\\n" assert err == "world\\n"

View File

@ -4,46 +4,51 @@ safely patch object attributes, dicts and environment variables.
Usage Usage
---------------- ----------------
Use the `monkeypatch funcarg`_ to safely modify or delete environment Use the `monkeypatch funcarg`_ to tweak your global test environment
variables, object attributes or dictionary values. For example, if you want for running a particular test. You can safely set/del an attribute,
to set the environment variable ``ENV1`` and patch the dictionary item or environment variable by respective methods
``os.path.abspath`` function to return a particular value during a test on the monkeypatch funcarg. If you want e.g. to set an ENV1 variable
function execution you can write it down like this: and have os.path.expanduser return a particular directory, you can
write it down like this:
.. sourcecode:: python .. sourcecode:: python
def test_mytest(monkeypatch): def test_mytest(monkeypatch):
monkeypatch.setenv('ENV1', 'myval') monkeypatch.setenv('ENV1', 'myval')
monkeypatch.setattr(os.path, 'abspath', lambda x: '/') monkeypatch.setattr(os.path, 'expanduser', lambda x: '/tmp/xyz')
... # your test code ... # your test code that uses those patched values implicitely
The function argument will do the modifications and memorize the After the test function finished all modifications will be undone,
old state. After the test function finished execution all because the ``monkeypatch.undo()`` method is registered as a finalizer.
modifications will be reverted. See the `monkeypatch blog post`_
for an extensive discussion.
To add to a possibly existing environment parameter you ``monkeypatch.setattr/delattr/delitem/delenv()`` all
can use this example: 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 .. sourcecode:: python
def test_mypath_finding(monkeypatch): def test_mypath_finding(monkeypatch):
monkeypatch.setenv('PATH', 'x/y', prepend=":") 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 calling "undo" finalization explicitely
----------------------------------------- -----------------------------------------
Usually at the end of function execution py.test will invoke At the end of function execution py.test invokes
a teardown hook which undoes the changes. If you cannot wait a teardown hook which undoes all monkeypatch changes.
that long you can also call finalization explicitely:: If you do not want to wait that long you can call
finalization explicitely::
monkeypatch.undo() monkeypatch.undo()
This will undo previous changes. This call consumes the This will undo previous changes. This call consumes the
undo stack. Calling it a second time has no effect. undo stack. Calling it a second time has no effect unless
Within a test you can continue to use the monkeypatch you start monkeypatching after the undo call.
object, however.
.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/ .. _`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 """The returned ``monkeypatch`` funcarg provides these
helper methods to modify objects, dictionaries or os.environ:: 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.delattr(obj, name, raising=True)
monkeypatch.setitem(mapping, name, value) monkeypatch.setitem(mapping, name, value)
monkeypatch.delitem(obj, name, raising=True) monkeypatch.delitem(obj, name, raising=True)
@ -79,8 +84,11 @@ class MonkeyPatch:
self._setattr = [] self._setattr = []
self._setitem = [] self._setitem = []
def setattr(self, obj, name, value): def setattr(self, obj, name, value, raising=True):
self._setattr.insert(0, (obj, name, getattr(obj, name, notset))) 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) setattr(obj, name, value)
def delattr(self, obj, name, raising=True): def delattr(self, obj, name, raising=True):

View File

@ -6,7 +6,7 @@ def test_forwarding_to_warnings_module():
def test_apiwarn_functional(): def test_apiwarn_functional():
capture = py.io.StdCapture() capture = py.io.StdCapture()
py.log._apiwarn("x.y.z", "something") py.log._apiwarn("x.y.z", "something", stacklevel=1)
out, err = capture.reset() out, err = capture.reset()
py.builtin.print_("out", out) py.builtin.print_("out", out)
py.builtin.print_("err", err) py.builtin.print_("err", err)

View File

@ -5,6 +5,13 @@ from py.__.test.plugin.pytest_monkeypatch import MonkeyPatch
def test_setattr(): def test_setattr():
class A: class A:
x = 1 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 = MonkeyPatch()
monkeypatch.setattr(A, 'x', 2) monkeypatch.setattr(A, 'x', 2)
assert A.x == 2 assert A.x == 2
@ -17,11 +24,6 @@ def test_setattr():
monkeypatch.undo() # double-undo makes no modification monkeypatch.undo() # double-undo makes no modification
assert A.x == 5 assert A.x == 5
monkeypatch.setattr(A, 'y', 3)
assert A.y == 3
monkeypatch.undo()
assert not hasattr(A, 'y')
def test_delattr(): def test_delattr():
class A: class A:
x = 1 x = 1
@ -35,7 +37,7 @@ def test_delattr():
monkeypatch.delattr(A, 'x') monkeypatch.delattr(A, 'x')
py.test.raises(AttributeError, "monkeypatch.delattr(A, 'y')") py.test.raises(AttributeError, "monkeypatch.delattr(A, 'y')")
monkeypatch.delattr(A, 'y', raising=False) monkeypatch.delattr(A, 'y', raising=False)
monkeypatch.setattr(A, 'x', 5) monkeypatch.setattr(A, 'x', 5, raising=False)
assert A.x == 5 assert A.x == 5
monkeypatch.undo() monkeypatch.undo()
assert A.x == 1 assert A.x == 1
@ -45,6 +47,7 @@ def test_setitem():
monkeypatch = MonkeyPatch() monkeypatch = MonkeyPatch()
monkeypatch.setitem(d, 'x', 2) monkeypatch.setitem(d, 'x', 2)
monkeypatch.setitem(d, 'y', 1700) monkeypatch.setitem(d, 'y', 1700)
monkeypatch.setitem(d, 'y', 1700)
assert d['x'] == 2 assert d['x'] == 2
assert d['y'] == 1700 assert d['y'] == 1700
monkeypatch.setitem(d, 'x', 3) monkeypatch.setitem(d, 'x', 3)