##// END OF EJS Templates
BUG: Integrate bug fixes from Enthought
BUG: Integrate bug fixes from Enthought

File last commit:

r1721:1d6f14c1
r1887:63839136
Show More
decorators.py
160 lines | 4.9 KiB | text/x-python | PythonLexer
Fernando Perez
Checkpoint with more tests working....
r1420 """Decorators for labeling test objects.
Decorators that merely return a modified version of the original
function object are straightforward. Decorators that return a new
function object need to use
nose.tools.make_decorator(original_function)(decorator) in returning
the decorator, in order to preserve metadata such as function name,
setup and teardown functions and so on - see nose.tools for more
information.
Fernando Perez
Add new decorators to skip os-specific tests....
r1721 This module provides a set of useful decorators meant to be ready to use in
your own tests. See the bottom of the file for the ready-made ones, and if you
find yourself writing a new one that may be of generic use, add it here.
Fernando Perez
Checkpoint with more tests working....
r1420 NOTE: This file contains IPython-specific decorators and imports the
numpy.testing.decorators file, which we've copied verbatim. Any of our own
code will be added at the bottom if we end up extending this.
"""
# Stdlib imports
import inspect
Fernando Perez
Add new decorators to skip os-specific tests....
r1721 import sys
Fernando Perez
Checkpoint with more tests working....
r1420
# Third-party imports
# This is Michele Simionato's decorator module, also kept verbatim.
Fernando Perez
Complete first pass on testing system. All tests pass on my box. Whew....
r1435 from decorator_msim import decorator, update_wrapper
Fernando Perez
Checkpoint with more tests working....
r1420
# Grab the numpy-specific decorators which we keep in a file that we
# occasionally update from upstream: decorators_numpy.py is an IDENTICAL copy
# of numpy.testing.decorators.
from decorators_numpy import *
##############################################################################
# Local code begins
# Utility functions
def apply_wrapper(wrapper,func):
"""Apply a wrapper to a function for decoration.
This mixes Michele Simionato's decorator tool with nose's make_decorator,
to apply a wrapper in a decorator so that all nose attributes, as well as
function signature and other properties, survive the decoration cleanly.
This will ensure that wrapped functions can still be well introspected via
IPython, for example.
"""
import nose.tools
return decorator(wrapper,nose.tools.make_decorator(func)(wrapper))
def make_label_dec(label,ds=None):
"""Factory function to create a decorator that applies one or more labels.
:Parameters:
label : string or sequence
One or more labels that will be applied by the decorator to the functions
it decorates. Labels are attributes of the decorated function with their
value set to True.
:Keywords:
ds : string
An optional docstring for the resulting decorator. If not given, a
default docstring is auto-generated.
:Returns:
A decorator.
:Examples:
A simple labeling decorator:
>>> slow = make_label_dec('slow')
>>> print slow.__doc__
Labels a test as 'slow'.
And one that uses multiple labels and a custom docstring:
>>> rare = make_label_dec(['slow','hard'],
... "Mix labels 'slow' and 'hard' for rare tests.")
>>> print rare.__doc__
Mix labels 'slow' and 'hard' for rare tests.
Now, let's test using this one:
>>> @rare
... def f(): pass
...
>>>
>>> f.slow
True
>>> f.hard
True
"""
if isinstance(label,basestring):
labels = [label]
else:
labels = label
# Validate that the given label(s) are OK for use in setattr() by doing a
# dry run on a dummy function.
tmp = lambda : None
for label in labels:
setattr(tmp,label,True)
# This is the actual decorator we'll return
def decor(f):
for label in labels:
setattr(f,label,True)
return f
# Apply the user's docstring, or autogenerate a basic one
if ds is None:
ds = "Labels a test as %r." % label
decor.__doc__ = ds
return decor
#-----------------------------------------------------------------------------
# Decorators for public use
Fernando Perez
Complete first pass on testing system. All tests pass on my box. Whew....
r1435 skip_doctest = make_label_dec('skip_doctest',
"""Decorator - mark a function or method for skipping its doctest.
Fernando Perez
Checkpoint with more tests working....
r1420
This decorator allows you to mark a function whose docstring you wish to
omit from testing, while preserving the docstring for introspection, help,
Fernando Perez
Complete first pass on testing system. All tests pass on my box. Whew....
r1435 etc.""")
Fernando Perez
Checkpoint with more tests working....
r1420
Fernando Perez
Fix error in test decorator.
r1577 def skip(msg=''):
Fernando Perez
Add optional message to @skip test decorator.
r1560 """Decorator - mark a test function for skipping from test suite.
Fernando Perez
Add new decorators to skip os-specific tests....
r1721 This function *is* already a decorator, it is not a factory like
make_label_dec or some of those in decorators_numpy.
Fernando Perez
Add optional message to @skip test decorator.
r1560 :Parameters:
func : function
Test function to be skipped
msg : string
Optional message to be added.
"""
Fernando Perez
Checkpoint with more tests working....
r1420
import nose
Gael Varoquaux
Fix tests when ipdoctest nose plugin is enable (Grrr, no isolation at...
r1505
Fernando Perez
Fix error in test decorator.
r1577 def inner(func):
def wrapper(*a,**k):
if msg: out = '\n'+msg
else: out = ''
raise nose.SkipTest("Skipping test for function: %s%s" %
(func.__name__,out))
return apply_wrapper(wrapper,func)
Gael Varoquaux
Fix tests when ipdoctest nose plugin is enable (Grrr, no isolation at...
r1505
Fernando Perez
Fix error in test decorator.
r1577 return inner
Fernando Perez
Add new decorators to skip os-specific tests....
r1721
# Decorators to skip certain tests on specific platforms.
skip_win32 = skipif(sys.platform=='win32',"This test does not run under Windows")
skip_linux = skipif(sys.platform=='linux2',"This test does not run under Linux")
skip_osx = skipif(sys.platform=='darwin',"This test does not run under OSX")