diff --git a/IPython/external/decorators/__init__.py b/IPython/external/decorators/__init__.py index fff075e..065ff18 100644 --- a/IPython/external/decorators/__init__.py +++ b/IPython/external/decorators/__init__.py @@ -1,4 +1,7 @@ try: from numpy.testing.decorators import * + from numpy.testing.noseclasses import KnownFailure except ImportError: from _decorators import * + # KnownFailure imported in _decorators from local version of + # noseclasses which is in _numpy_testing_noseclasses diff --git a/IPython/external/decorators/_decorators.py b/IPython/external/decorators/_decorators.py index 6f457f1..8ae4a92 100644 --- a/IPython/external/decorators/_decorators.py +++ b/IPython/external/decorators/_decorators.py @@ -14,7 +14,6 @@ function name, setup and teardown functions and so on - see """ import warnings -import sys # IPython changes: make this work if numpy not available # Original code: @@ -25,7 +24,12 @@ try: from numpy.testing.utils import WarningManager, WarningMessage except ImportError: from _numpy_testing_utils import WarningManager, WarningMessage - + +try: + from numpy.testing.noseclasses import KnownFailure, KnownFailureTest +except ImportError: + from _numpy_testing_noseclasses import KnownFailure, KnownFailureTest + # End IPython changes def slow(t): @@ -34,7 +38,7 @@ def slow(t): The exact definition of a slow test is obviously both subjective and hardware-dependent, but in general any individual test that requires more - than a second or two should be labeled as slow (the whole suite consits of + than a second or two should be labeled as slow (the whole suite consists of thousands of tests, so even a second is significant). Parameters @@ -172,7 +176,6 @@ def skipif(skip_condition, msg=None): return skip_decorator - def knownfailureif(fail_condition, msg=None): """ Make function raise KnownFailureTest exception if given condition is true. @@ -216,7 +219,6 @@ def knownfailureif(fail_condition, msg=None): # Local import to avoid a hard nose dependency and only incur the # import time overhead at actual test-time. import nose - from noseclasses import KnownFailureTest def knownfailer(*args, **kwargs): if fail_val(): raise KnownFailureTest, msg @@ -255,7 +257,6 @@ def deprecated(conditional=True): # Local import to avoid a hard nose dependency and only incur the # import time overhead at actual test-time. import nose - from noseclasses import KnownFailureTest def _deprecated_imp(*args, **kwargs): # Poor man's replacement for the with statement diff --git a/IPython/external/decorators/_numpy_testing_noseclasses.py b/IPython/external/decorators/_numpy_testing_noseclasses.py new file mode 100644 index 0000000..ca6ccd8 --- /dev/null +++ b/IPython/external/decorators/_numpy_testing_noseclasses.py @@ -0,0 +1,41 @@ +# IPython: modified copy of numpy.testing.noseclasses, so +# IPython.external._decorators works without numpy being installed. + +# These classes implement a "known failure" error class. + +import os + +from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin + +class KnownFailureTest(Exception): + '''Raise this exception to mark a test as a known failing test.''' + pass + + +class KnownFailure(ErrorClassPlugin): + '''Plugin that installs a KNOWNFAIL error class for the + KnownFailureClass exception. When KnownFailureTest is raised, + the exception will be logged in the knownfail attribute of the + result, 'K' or 'KNOWNFAIL' (verbose) will be output, and the + exception will not be counted as an error or failure.''' + enabled = True + knownfail = ErrorClass(KnownFailureTest, + label='KNOWNFAIL', + isfailure=False) + + def options(self, parser, env=os.environ): + env_opt = 'NOSE_WITHOUT_KNOWNFAIL' + parser.add_option('--no-knownfail', action='store_true', + dest='noKnownFail', default=env.get(env_opt, False), + help='Disable special handling of KnownFailureTest ' + 'exceptions') + + def configure(self, options, conf): + if not self.can_configure: + return + self.conf = conf + disable = getattr(options, 'noKnownFail', False) + if disable: + self.enabled = False + + diff --git a/IPython/external/decorators/_numpy_testing_utils.py b/IPython/external/decorators/_numpy_testing_utils.py index 8bcbb05..a01e346 100644 --- a/IPython/external/decorators/_numpy_testing_utils.py +++ b/IPython/external/decorators/_numpy_testing_utils.py @@ -1,14 +1,10 @@ -# IPython: modified copy of numpy.testing.utils, so numpy.testing.decorators -# works without numpy being installed. +# IPython: modified copy of numpy.testing.utils, so +# IPython.external._decorators works without numpy being installed. """ Utility function to facilitate testing. """ -import os import sys -import re -import operator -import types import warnings # The following two classes are copied from python 2.6 warnings module (context diff --git a/IPython/testing/decorators.py b/IPython/testing/decorators.py index bb96cc1..de3051d 100644 --- a/IPython/testing/decorators.py +++ b/IPython/testing/decorators.py @@ -24,9 +24,10 @@ Lightweight testing that remains unittest-compatible. recognize it as such. This will make it easier to migrate away from Nose if we ever need/want to while maintaining very lightweight tests. -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. +NOTE: This file contains IPython-specific decorators. Using the machinery in +IPython.external.decorators, we import either numpy.testing.decorators if numpy is +available, OR use equivalent code in IPython.external._decorators, which +we've copied verbatim from numpy. Authors ------- @@ -319,7 +320,7 @@ skipif_not_numpy = skipif(module_not_available('numpy'),"This test requires nump skipif_not_sympy = skipif(module_not_available('sympy'),"This test requires sympy") -skip_known_failure = skip('This test is known to fail') +skip_known_failure = knownfailureif(True,'This test is known to fail') # A null 'decorator', useful to make more readable code that needs to pick # between different decorators based on OS or other conditions diff --git a/IPython/testing/iptest.py b/IPython/testing/iptest.py index fce2111..0b915b6 100644 --- a/IPython/testing/iptest.py +++ b/IPython/testing/iptest.py @@ -53,6 +53,7 @@ from IPython.utils.sysinfo import sys_info from IPython.testing import globalipapp from IPython.testing.plugin.ipdoctest import IPythonDoctest +from IPython.external.decorators import KnownFailure pjoin = path.join @@ -357,7 +358,7 @@ def run_iptest(): # Construct list of plugins, omitting the existing doctest plugin, which # ours replaces (and extends). - plugins = [IPythonDoctest(make_exclude())] + plugins = [IPythonDoctest(make_exclude()), KnownFailure()] for p in nose.plugins.builtin.plugins: plug = p() if plug.name == 'doctest':