From b64f754008964caef3b2a7620510b5c80f755fb0 2011-04-04 00:52:21
From: Paul Ivanov <pivanov314@gmail.com>
Date: 2011-04-04 00:52:21
Subject: [PATCH] make know failures report as 'K'

ported from numpy.testing.noseclasses, with the equivalent code
extracted into _numpy_testing_noseclasses in case numpy is not
installed.

removed some unused imports throughout

---

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