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:
|
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'
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue