summaryrefslogtreecommitdiff
path: root/numpy/testing
diff options
context:
space:
mode:
authorMatthew Brett <matthew.brett@gmail.com>2011-08-10 19:06:48 -0700
committerCharles Harris <charlesr.harris@gmail.com>2011-08-16 10:44:29 -0600
commitb0c1f6b67ecd5cf865cf6945bff632f81473b81a (patch)
tree97debdbb7c4b173d9f2d988bcd841dc5beeebcbb /numpy/testing
parent5cf0a07396b88b48b6f8a922fe8b1147406cb4bc (diff)
downloadnumpy-b0c1f6b67ecd5cf865cf6945bff632f81473b81a.tar.gz
ENH: refactor of docteset plugin management
We previously had a baroque inheritance scheme to deal with the case where the user had normal nose doctests enabled in their environment. However, this scheme didn't deal with bench() routine, and was complicated. This commit uses a null Unplugger plugin to pull the doctest plugin off the nose configuration after it has been initialized. We can use this for bench() and test(), and it allows the doctest module to be enabled (by the user environment) and then thrown away. Also rejigged the docstrings and removed the automated docstring addition as the docstrings have already been copied and adapted in the code.
Diffstat (limited to 'numpy/testing')
-rw-r--r--numpy/testing/noseclasses.py66
-rw-r--r--numpy/testing/nosetester.py95
2 files changed, 71 insertions, 90 deletions
diff --git a/numpy/testing/noseclasses.py b/numpy/testing/noseclasses.py
index f97ea9126..25f6662b7 100644
--- a/numpy/testing/noseclasses.py
+++ b/numpy/testing/noseclasses.py
@@ -185,16 +185,24 @@ print_state = numpy.get_printoptions()
class NumpyDoctest(npd.Doctest):
name = 'numpydoctest' # call nosetests with --with-numpydoctest
- enabled = True
+ score = 1000 # load late, after doctest builtin
def options(self, parser, env=os.environ):
Plugin.options(self, parser, env)
def configure(self, options, config):
+ # parent method sets enabled flag from command line --with-numpydoctest
Plugin.configure(self, options, config)
self.doctest_tests = True
self.finder = NumpyDocTestFinder()
self.parser = doctest.DocTestParser()
+ if self.enabled:
+ # Pull standard doctest out of plugin list; there's no reason to run
+ # both. In practice the Unplugger plugin above would cover us when
+ # run from a standard numpy.test() call; this is just in case
+ # someone wants to run our plugin outside the numpy.test() machinery
+ config.plugins.plugins = [p for p in config.plugins.plugins
+ if p.name != 'doctest']
# Turn on whitespace normalization, set a minimal execution context
# for doctests, implement a "#random" directive to allow executing a
@@ -263,6 +271,27 @@ class NumpyDoctest(npd.Doctest):
return npd.Doctest.wantFile(self, file)
+class Unplugger(object):
+ """ Nose plugin to remove named plugin late in loading
+
+ By default it removes the "doctest" plugin.
+ """
+ name = 'unplugger'
+ enabled = True # always enabled
+ score = 4000 # load late in order to be after builtins
+
+ def __init__(self, to_unplug='doctest'):
+ self.to_unplug = to_unplug
+
+ def options(self, parser, env):
+ pass
+
+ def configure(self, options, config):
+ # Pull named plugin out of plugins list
+ config.plugins.plugins = [p for p in config.plugins.plugins
+ if p.name != self.to_unplug]
+
+
class KnownFailureTest(Exception):
'''Raise this exception to mark a test as a known failing test.'''
pass
@@ -295,41 +324,9 @@ class KnownFailure(ErrorClassPlugin):
self.enabled = False
-class NpConfig(nose.core.Config):
- ''' Class to pull out nose doctest plugin after configuration
-
- This allows the user to set doctest related settings in their
- configuration. For example, without this fix, a setting of
- 'with-doctest=1' in the user's .noserc file would cause an error, if
- we remove the doctest extension before this stage. Our configure
- uses the plugin to parse any settings, but then removed the doctest
- plugin because the numpy doctester should be used for doctests
- instead.
- '''
- def __init__(self, config):
- self.__dict__ = config.__dict__
-
- def configure(self, *args, **kwargs):
- super(NpConfig, self).configure(*args, **kwargs)
- self.plugins.plugins = [p for p in self.plugins.plugins
- if p.name != 'doctest']
-
-
-# Our class has two uses. First, to allow us to use NpConfig above to
-# remove the doctest plugin after it has parsed the configuration.
-# Second we save the results of the tests in runTests - see runTests
+# Class allows us to save the results of the tests in runTests - see runTests
# method docstring for details
class NumpyTestProgram(nose.core.TestProgram):
- def makeConfig(self, *args, **kwargs):
- """Load a Config, pre-filled with user config files if any are
- found.
-
- We override this method only to allow us to return a NpConfig
- object instead of a Config object.
- """
- config = super(NumpyTestProgram, self).makeConfig(*args, **kwargs)
- return NpConfig(config)
-
def runTests(self):
"""Run Tests. Returns true on success, false on failure, and
sets self.success to the same value.
@@ -345,7 +342,6 @@ class NumpyTestProgram(nose.core.TestProgram):
plug_runner = self.config.plugins.prepareTestRunner(self.testRunner)
if plug_runner is not None:
self.testRunner = plug_runner
-
self.result = self.testRunner.run(self.test)
self.success = self.result.wasSuccessful()
return self.success
diff --git a/numpy/testing/nosetester.py b/numpy/testing/nosetester.py
index 90e09f880..9e27352ab 100644
--- a/numpy/testing/nosetester.py
+++ b/numpy/testing/nosetester.py
@@ -79,33 +79,6 @@ def run_module_suite(file_to_run = None):
import_nose().run(argv=['',file_to_run])
-# contructs NoseTester method docstrings
-def _docmethod(meth, testtype):
- if not meth.__doc__:
- return
-
- test_header = \
- '''Parameters
- ----------
- label : {'fast', 'full', '', attribute identifer}
- Identifies the %(testtype)ss to run. This can be a string to
- pass to the nosetests executable with the '-A' option, or one of
- several special values.
- Special values are:
- 'fast' - the default - which corresponds to nosetests -A option
- of 'not slow'.
- 'full' - fast (as above) and slow %(testtype)ss as in the
- no -A option to nosetests - same as ''
- None or '' - run all %(testtype)ss
- attribute_identifier - string passed directly to nosetests as '-A'
- verbose : integer
- verbosity value for test outputs, 1-10
- extra_argv : list
- List with any extra args to pass to nosetests''' \
- % {'testtype': testtype}
-
- meth.__doc__ = meth.__doc__ % {'test_header':test_header}
-
class NoseTester(object):
"""
@@ -171,7 +144,19 @@ class NoseTester(object):
def _test_argv(self, label, verbose, extra_argv):
''' Generate argv for nosetest command
- %(test_header)s
+ Parameters
+ ----------
+ label : {'fast', 'full', '', attribute identifier}, optional
+ see ``test`` docstring
+ verbose : int, optional
+ Verbosity value for test outputs, in the range 1-10. Default is 1.
+ extra_argv : list, optional
+ List with any extra arguments to pass to nosetests.
+
+ Returns
+ -------
+ argv : list
+ command line arguments that will be passed to nose
'''
argv = [__file__, self.package_path, '-s']
if label and label != 'full':
@@ -239,12 +224,13 @@ class NoseTester(object):
argv += ['--exclude','pyrex_ext']
argv += ['--exclude','swig_ext']
- nose = import_nose()
+ # fail with nice error message if nose is not present
+ import_nose()
# construct list of plugins
import nose.plugins.builtin
- from noseclasses import NumpyDoctest, KnownFailure
- plugins = [NumpyDoctest(), KnownFailure()]
+ from noseclasses import NumpyDoctest, KnownFailure, Unplugger
+ plugins = [NumpyDoctest(), KnownFailure(), Unplugger()]
plugins += [p() for p in nose.plugins.builtin.plugins]
return argv, plugins
@@ -256,15 +242,14 @@ class NoseTester(object):
Parameters
----------
label : {'fast', 'full', '', attribute identifier}, optional
- Identifies the tests to run. This can be a string to pass to the
- nosetests executable with the '-A' option, or one of
- several special values.
- Special values are:
- 'fast' - the default - which corresponds to the ``nosetests -A``
- option of 'not slow'.
- 'full' - fast (as above) and slow tests as in the
- 'no -A' option to nosetests - this is the same as ''.
- None or '' - run all tests.
+ Identifies the tests to run. This can be a string to pass to
+ the nosetests executable with the '-A' option, or one of several
+ special values. Special values are:
+ * 'fast' - the default - which corresponds to the ``nosetests -A``
+ option of 'not slow'.
+ * 'full' - fast (as above) and slow tests as in the
+ 'no -A' option to nosetests - this is the same as ''.
+ * None or '' - run all tests.
attribute_identifier - string passed directly to nosetests as '-A'.
verbose : int, optional
Verbosity value for test outputs, in the range 1-10. Default is 1.
@@ -336,18 +321,17 @@ class NoseTester(object):
Parameters
----------
label : {'fast', 'full', '', attribute identifier}, optional
- Identifies the tests to run. This can be a string to pass to the
- nosetests executable with the '-A' option, or one of
- several special values.
- Special values are:
- 'fast' - the default - which corresponds to the ``nosetests -A``
- option of 'not slow'.
- 'full' - fast (as above) and slow tests as in the
- 'no -A' option to nosetests - this is the same as ''.
- None or '' - run all tests.
+ Identifies the benchmarks to run. This can be a string to pass to
+ the nosetests executable with the '-A' option, or one of several
+ special values. Special values are:
+ * 'fast' - the default - which corresponds to the ``nosetests -A``
+ option of 'not slow'.
+ * 'full' - fast (as above) and slow benchmarks as in the
+ 'no -A' option to nosetests - this is the same as ''.
+ * None or '' - run all tests.
attribute_identifier - string passed directly to nosetests as '-A'.
verbose : int, optional
- Verbosity value for test outputs, in the range 1-10. Default is 1.
+ Verbosity value for benchmark outputs, in the range 1-10. Default is 1.
extra_argv : list, optional
List with any extra arguments to pass to nosetests.
@@ -392,13 +376,14 @@ class NoseTester(object):
argv = self._test_argv(label, verbose, extra_argv)
argv += ['--match', r'(?:^|[\\b_\\.%s-])[Bb]ench' % os.sep]
+ # import nose or make informative error
nose = import_nose()
- return nose.run(argv=argv)
- # generate method docstrings
- _docmethod(_test_argv, '(testtype)')
- _docmethod(test, 'test')
- _docmethod(bench, 'benchmark')
+ # get plugin to disable doctests
+ from noseclasses import Unplugger
+ add_plugins = [Unplugger('doctest')]
+
+ return nose.run(argv=argv, addplugins=add_plugins)
########################################################################