1import os
2import textwrap
3from optparse import OptionConflictError
4from warnings import warn
5from nose.util import tolist
6
7class Plugin(object):
8    """Base class for nose plugins. It's recommended but not *necessary* to
9    subclass this class to create a plugin, but all plugins *must* implement
10    `options(self, parser, env)` and `configure(self, options, conf)`, and
11    must have the attributes `enabled`, `name` and `score`.  The `name`
12    attribute may contain hyphens ('-').
13
14    Plugins should not be enabled by default.
15
16    Subclassing Plugin (and calling the superclass methods in
17    __init__, configure, and options, if you override them) will give
18    your plugin some friendly default behavior:
19
20    * A --with-$name option will be added to the command line interface
21      to enable the plugin, and a corresponding environment variable
22      will be used as the default value. The plugin class's docstring
23      will be used as the help for this option.
24    * The plugin will not be enabled unless this option is selected by
25      the user.
26    """
27    can_configure = False
28    enabled = False
29    enableOpt = None
30    name = None
31    score = 100
32
33    def __init__(self):
34        if self.name is None:
35            self.name = self.__class__.__name__.lower()
36        if self.enableOpt is None:
37            self.enableOpt = "enable_plugin_%s" % self.name.replace('-', '_')
38
39    def addOptions(self, parser, env=None):
40        """Add command-line options for this plugin.
41
42        The base plugin class adds --with-$name by default, used to enable the
43        plugin.
44
45        .. warning :: Don't implement addOptions unless you want to override
46                      all default option handling behavior, including
47                      warnings for conflicting options. Implement
48                      :meth:`options
49                      <nose.plugins.base.IPluginInterface.options>`
50                      instead.
51        """
52        self.add_options(parser, env)
53
54    def add_options(self, parser, env=None):
55        """Non-camel-case version of func name for backwards compatibility.
56
57        .. warning ::
58
59           DEPRECATED: Do not use this method,
60           use :meth:`options <nose.plugins.base.IPluginInterface.options>`
61           instead.
62
63        """
64        # FIXME raise deprecation warning if wasn't called by wrapper
65        if env is None:
66            env = os.environ
67        try:
68            self.options(parser, env)
69            self.can_configure = True
70        except OptionConflictError, e:
71            warn("Plugin %s has conflicting option string: %s and will "
72                 "be disabled" % (self, e), RuntimeWarning)
73            self.enabled = False
74            self.can_configure = False
75
76    def options(self, parser, env):
77        """Register commandline options.
78
79        Implement this method for normal options behavior with protection from
80        OptionConflictErrors. If you override this method and want the default
81        --with-$name option to be registered, be sure to call super().
82        """
83        env_opt = 'NOSE_WITH_%s' % self.name.upper()
84        env_opt = env_opt.replace('-', '_')
85        parser.add_option("--with-%s" % self.name,
86                          action="store_true",
87                          dest=self.enableOpt,
88                          default=env.get(env_opt),
89                          help="Enable plugin %s: %s [%s]" %
90                          (self.__class__.__name__, self.help(), env_opt))
91
92    def configure(self, options, conf):
93        """Configure the plugin and system, based on selected options.
94
95        The base plugin class sets the plugin to enabled if the enable option
96        for the plugin (self.enableOpt) is true.
97        """
98        if not self.can_configure:
99            return
100        self.conf = conf
101        if hasattr(options, self.enableOpt):
102            self.enabled = getattr(options, self.enableOpt)
103
104    def help(self):
105        """Return help for this plugin. This will be output as the help
106        section of the --with-$name option that enables the plugin.
107        """
108        if self.__class__.__doc__:
109            # doc sections are often indented; compress the spaces
110            return textwrap.dedent(self.__class__.__doc__)
111        return "(no help available)"
112
113    # Compatiblity shim
114    def tolist(self, val):
115        warn("Plugin.tolist is deprecated. Use nose.util.tolist instead",
116             DeprecationWarning)
117        return tolist(val)
118
119
120class IPluginInterface(object):
121    """
122    IPluginInterface describes the plugin API. Do not subclass or use this
123    class directly.
124    """
125    def __new__(cls, *arg, **kw):
126        raise TypeError("IPluginInterface class is for documentation only")
127
128    def addOptions(self, parser, env):
129        """Called to allow plugin to register command-line options with the
130        parser. DO NOT return a value from this method unless you want to stop
131        all other plugins from setting their options.
132
133        .. warning ::
134
135           DEPRECATED -- implement
136           :meth:`options <nose.plugins.base.IPluginInterface.options>` instead.
137        """
138        pass
139    add_options = addOptions
140    add_options.deprecated = True
141
142    def addDeprecated(self, test):
143        """Called when a deprecated test is seen. DO NOT return a value
144        unless you want to stop other plugins from seeing the deprecated
145        test.
146
147        .. warning :: DEPRECATED -- check error class in addError instead
148        """
149        pass
150    addDeprecated.deprecated = True
151
152    def addError(self, test, err):
153        """Called when a test raises an uncaught exception. DO NOT return a
154        value unless you want to stop other plugins from seeing that the
155        test has raised an error.
156
157        :param test: the test case
158        :type test: :class:`nose.case.Test`
159        :param err: sys.exc_info() tuple
160        :type err: 3-tuple
161        """
162        pass
163    addError.changed = True
164
165    def addFailure(self, test, err):
166        """Called when a test fails. DO NOT return a value unless you
167        want to stop other plugins from seeing that the test has failed.
168
169        :param test: the test case
170        :type test: :class:`nose.case.Test`
171        :param err: 3-tuple
172        :type err: sys.exc_info() tuple
173        """
174        pass
175    addFailure.changed = True
176
177    def addSkip(self, test):
178        """Called when a test is skipped. DO NOT return a value unless
179        you want to stop other plugins from seeing the skipped test.
180
181        .. warning:: DEPRECATED -- check error class in addError instead
182        """
183        pass
184    addSkip.deprecated = True
185
186    def addSuccess(self, test):
187        """Called when a test passes. DO NOT return a value unless you
188        want to stop other plugins from seeing the passing test.
189
190        :param test: the test case
191        :type test: :class:`nose.case.Test`
192        """
193        pass
194    addSuccess.changed = True
195
196    def afterContext(self):
197        """Called after a context (generally a module) has been
198        lazy-loaded, imported, setup, had its tests loaded and
199        executed, and torn down.
200        """
201        pass
202    afterContext._new = True
203
204    def afterDirectory(self, path):
205        """Called after all tests have been loaded from directory at path
206        and run.
207
208        :param path: the directory that has finished processing
209        :type path: string
210        """
211        pass
212    afterDirectory._new = True
213
214    def afterImport(self, filename, module):
215        """Called after module is imported from filename. afterImport
216        is called even if the import failed.
217
218        :param filename: The file that was loaded
219        :type filename: string
220        :param module: The name of the module
221        :type module: string
222        """
223        pass
224    afterImport._new = True
225
226    def afterTest(self, test):
227        """Called after the test has been run and the result recorded
228        (after stopTest).
229
230        :param test: the test case
231        :type test: :class:`nose.case.Test`
232        """
233        pass
234    afterTest._new = True
235
236    def beforeContext(self):
237        """Called before a context (generally a module) is
238        examined. Because the context is not yet loaded, plugins don't
239        get to know what the context is; so any context operations
240        should use a stack that is pushed in `beforeContext` and popped
241        in `afterContext` to ensure they operate symmetrically.
242
243        `beforeContext` and `afterContext` are mainly useful for tracking
244        and restoring global state around possible changes from within a
245        context, whatever the context may be. If you need to operate on
246        contexts themselves, see `startContext` and `stopContext`, which
247        are passed the context in question, but are called after
248        it has been loaded (imported in the module case).
249        """
250        pass
251    beforeContext._new = True
252
253    def beforeDirectory(self, path):
254        """Called before tests are loaded from directory at path.
255
256        :param path: the directory that is about to be processed
257        """
258        pass
259    beforeDirectory._new = True
260
261    def beforeImport(self, filename, module):
262        """Called before module is imported from filename.
263
264        :param filename: The file that will be loaded
265        :param module: The name of the module found in file
266        :type module: string
267        """
268    beforeImport._new = True
269
270    def beforeTest(self, test):
271        """Called before the test is run (before startTest).
272
273        :param test: the test case
274        :type test: :class:`nose.case.Test`
275        """
276        pass
277    beforeTest._new = True
278
279    def begin(self):
280        """Called before any tests are collected or run. Use this to
281        perform any setup needed before testing begins.
282        """
283        pass
284
285    def configure(self, options, conf):
286        """Called after the command line has been parsed, with the
287        parsed options and the config container. Here, implement any
288        config storage or changes to state or operation that are set
289        by command line options.
290
291        DO NOT return a value from this method unless you want to
292        stop all other plugins from being configured.
293        """
294        pass
295
296    def finalize(self, result):
297        """Called after all report output, including output from all
298        plugins, has been sent to the stream. Use this to print final
299        test results or perform final cleanup. Return None to allow
300        other plugins to continue printing, or any other value to stop
301        them.
302
303        :param result: test result object
304
305        .. Note:: When tests are run under a test runner other than
306           :class:`nose.core.TextTestRunner`, such as
307           via ``python setup.py test``, this method may be called
308           **before** the default report output is sent.
309        """
310        pass
311
312    def describeTest(self, test):
313        """Return a test description.
314
315        Called by :meth:`nose.case.Test.shortDescription`.
316
317        :param test: the test case
318        :type test: :class:`nose.case.Test`
319        """
320        pass
321    describeTest._new = True
322
323    def formatError(self, test, err):
324        """Called in result.addError, before plugin.addError. If you
325        want to replace or modify the error tuple, return a new error
326        tuple, otherwise return err, the original error tuple.
327
328        :param test: the test case
329        :type test: :class:`nose.case.Test`
330        :param err: sys.exc_info() tuple
331        :type err: 3-tuple
332        """
333        pass
334    formatError._new = True
335    formatError.chainable = True
336    # test arg is not chainable
337    formatError.static_args = (True, False)
338
339    def formatFailure(self, test, err):
340        """Called in result.addFailure, before plugin.addFailure. If you
341        want to replace or modify the error tuple, return a new error
342        tuple, otherwise return err, the original error tuple.
343
344        :param test: the test case
345        :type test: :class:`nose.case.Test`
346        :param err: sys.exc_info() tuple
347        :type err: 3-tuple
348        """
349        pass
350    formatFailure._new = True
351    formatFailure.chainable = True
352    # test arg is not chainable
353    formatFailure.static_args = (True, False)
354
355    def handleError(self, test, err):
356        """Called on addError. To handle the error yourself and prevent normal
357        error processing, return a true value.
358
359        :param test: the test case
360        :type test: :class:`nose.case.Test`
361        :param err: sys.exc_info() tuple
362        :type err: 3-tuple
363        """
364        pass
365    handleError._new = True
366
367    def handleFailure(self, test, err):
368        """Called on addFailure. To handle the failure yourself and
369        prevent normal failure processing, return a true value.
370
371        :param test: the test case
372        :type test: :class:`nose.case.Test`
373        :param err: sys.exc_info() tuple
374        :type err: 3-tuple
375        """
376        pass
377    handleFailure._new = True
378
379    def loadTestsFromDir(self, path):
380        """Return iterable of tests from a directory. May be a
381        generator.  Each item returned must be a runnable
382        unittest.TestCase (or subclass) instance or suite instance.
383        Return None if your plugin cannot collect any tests from
384        directory.
385
386        :param  path: The path to the directory.
387        """
388        pass
389    loadTestsFromDir.generative = True
390    loadTestsFromDir._new = True
391
392    def loadTestsFromModule(self, module, path=None):
393        """Return iterable of tests in a module. May be a
394        generator. Each item returned must be a runnable
395        unittest.TestCase (or subclass) instance.
396        Return None if your plugin cannot
397        collect any tests from module.
398
399        :param module: The module object
400        :type module: python module
401        :param path: the path of the module to search, to distinguish from
402            namespace package modules
403
404            .. note::
405
406               NEW. The ``path`` parameter will only be passed by nose 0.11
407               or above.
408        """
409        pass
410    loadTestsFromModule.generative = True
411
412    def loadTestsFromName(self, name, module=None, importPath=None):
413        """Return tests in this file or module. Return None if you are not able
414        to load any tests, or an iterable if you are. May be a
415        generator.
416
417        :param name: The test name. May be a file or module name plus a test
418            callable. Use split_test_name to split into parts. Or it might
419            be some crazy name of your own devising, in which case, do
420            whatever you want.
421        :param module: Module from which the name is to be loaded
422        :param importPath: Path from which file (must be a python module) was
423            found
424
425            .. warning:: DEPRECATED: this argument will NOT be passed.
426        """
427        pass
428    loadTestsFromName.generative = True
429
430    def loadTestsFromNames(self, names, module=None):
431        """Return a tuple of (tests loaded, remaining names). Return
432        None if you are not able to load any tests. Multiple plugins
433        may implement loadTestsFromNames; the remaining name list from
434        each will be passed to the next as input.
435
436        :param names: List of test names.
437        :type names: iterable
438        :param module: Module from which the names are to be loaded
439        """
440        pass
441    loadTestsFromNames._new = True
442    loadTestsFromNames.chainable = True
443
444    def loadTestsFromFile(self, filename):
445        """Return tests in this file. Return None if you are not
446        interested in loading any tests, or an iterable if you are and
447        can load some. May be a generator. *If you are interested in
448        loading tests from the file and encounter no errors, but find
449        no tests, yield False or return [False].*
450
451        .. Note:: This method replaces loadTestsFromPath from the 0.9
452                  API.
453
454        :param filename: The full path to the file or directory.
455        """
456        pass
457    loadTestsFromFile.generative = True
458    loadTestsFromFile._new = True
459
460    def loadTestsFromPath(self, path):
461        """
462        .. warning:: DEPRECATED -- use loadTestsFromFile instead
463        """
464        pass
465    loadTestsFromPath.deprecated = True
466
467    def loadTestsFromTestCase(self, cls):
468        """Return tests in this test case class. Return None if you are
469        not able to load any tests, or an iterable if you are. May be a
470        generator.
471
472        :param cls: The test case class. Must be subclass of
473           :class:`unittest.TestCase`.
474        """
475        pass
476    loadTestsFromTestCase.generative = True
477
478    def loadTestsFromTestClass(self, cls):
479        """Return tests in this test class. Class will *not* be a
480        unittest.TestCase subclass. Return None if you are not able to
481        load any tests, an iterable if you are. May be a generator.
482
483        :param cls: The test case class. Must be **not** be subclass of
484           :class:`unittest.TestCase`.
485        """
486        pass
487    loadTestsFromTestClass._new = True
488    loadTestsFromTestClass.generative = True
489
490    def makeTest(self, obj, parent):
491        """Given an object and its parent, return or yield one or more
492        test cases. Each test must be a unittest.TestCase (or subclass)
493        instance. This is called before default test loading to allow
494        plugins to load an alternate test case or cases for an
495        object. May be a generator.
496
497        :param obj: The object to be made into a test
498        :param parent: The parent of obj (eg, for a method, the class)
499        """
500        pass
501    makeTest._new = True
502    makeTest.generative = True
503
504    def options(self, parser, env):
505        """Called to allow plugin to register command line
506        options with the parser.
507
508        DO NOT return a value from this method unless you want to stop
509        all other plugins from setting their options.
510
511        :param parser: options parser instance
512        :type parser: :class:`ConfigParser.ConfigParser`
513        :param env: environment, default is os.environ
514        """
515        pass
516    options._new = True
517
518    def prepareTest(self, test):
519        """Called before the test is run by the test runner. Please
520        note the article *the* in the previous sentence: prepareTest
521        is called *only once*, and is passed the test case or test
522        suite that the test runner will execute. It is *not* called
523        for each individual test case. If you return a non-None value,
524        that return value will be run as the test. Use this hook to
525        wrap or decorate the test with another function. If you need
526        to modify or wrap individual test cases, use `prepareTestCase`
527        instead.
528
529        :param test: the test case
530        :type test: :class:`nose.case.Test`
531        """
532        pass
533
534    def prepareTestCase(self, test):
535        """Prepare or wrap an individual test case. Called before
536        execution of the test. The test passed here is a
537        nose.case.Test instance; the case to be executed is in the
538        test attribute of the passed case. To modify the test to be
539        run, you should return a callable that takes one argument (the
540        test result object) -- it is recommended that you *do not*
541        side-effect the nose.case.Test instance you have been passed.
542
543        Keep in mind that when you replace the test callable you are
544        replacing the run() method of the test case -- including the
545        exception handling and result calls, etc.
546
547        :param test: the test case
548        :type test: :class:`nose.case.Test`
549        """
550        pass
551    prepareTestCase._new = True
552
553    def prepareTestLoader(self, loader):
554        """Called before tests are loaded. To replace the test loader,
555        return a test loader. To allow other plugins to process the
556        test loader, return None. Only one plugin may replace the test
557        loader. Only valid when using nose.TestProgram.
558
559        :param loader: :class:`nose.loader.TestLoader`
560             (or other loader) instance
561        """
562        pass
563    prepareTestLoader._new = True
564
565    def prepareTestResult(self, result):
566        """Called before the first test is run. To use a different
567        test result handler for all tests than the given result,
568        return a test result handler. NOTE however that this handler
569        will only be seen by tests, that is, inside of the result
570        proxy system. The TestRunner and TestProgram -- whether nose's
571        or other -- will continue to see the original result
572        handler. For this reason, it is usually better to monkeypatch
573        the result (for instance, if you want to handle some
574        exceptions in a unique way). Only one plugin may replace the
575        result, but many may monkeypatch it. If you want to
576        monkeypatch and stop other plugins from doing so, monkeypatch
577        and return the patched result.
578
579        :param result: :class:`nose.result.TextTestResult`
580             (or other result) instance
581        """
582        pass
583    prepareTestResult._new = True
584
585    def prepareTestRunner(self, runner):
586        """Called before tests are run. To replace the test runner,
587        return a test runner. To allow other plugins to process the
588        test runner, return None. Only valid when using nose.TestProgram.
589
590        :param runner: :class:`nose.core.TextTestRunner`
591             (or other runner) instance
592        """
593        pass
594    prepareTestRunner._new = True
595
596    def report(self, stream):
597        """Called after all error output has been printed. Print your
598        plugin's report to the provided stream. Return None to allow
599        other plugins to print reports, any other value to stop them.
600
601        :param stream: stream object; send your output here
602        :type stream: file-like object
603        """
604        pass
605
606    def setOutputStream(self, stream):
607        """Called before test output begins. To direct test output to a
608        new stream, return a stream object, which must implement a
609        `write(msg)` method. If you only want to note the stream, not
610        capture or redirect it, then return None.
611
612        :param stream: stream object; send your output here
613        :type stream: file-like object
614        """
615
616    def startContext(self, context):
617        """Called before context setup and the running of tests in the
618        context. Note that tests have already been *loaded* from the
619        context before this call.
620
621        :param context: the context about to be setup. May be a module or
622             class, or any other object that contains tests.
623        """
624        pass
625    startContext._new = True
626
627    def startTest(self, test):
628        """Called before each test is run. DO NOT return a value unless
629        you want to stop other plugins from seeing the test start.
630
631        :param test: the test case
632        :type test: :class:`nose.case.Test`
633        """
634        pass
635
636    def stopContext(self, context):
637        """Called after the tests in a context have run and the
638        context has been torn down.
639
640        :param context: the context that has been torn down. May be a module or
641             class, or any other object that contains tests.
642        """
643        pass
644    stopContext._new = True
645
646    def stopTest(self, test):
647        """Called after each test is run. DO NOT return a value unless
648        you want to stop other plugins from seeing that the test has stopped.
649
650        :param test: the test case
651        :type test: :class:`nose.case.Test`
652        """
653        pass
654
655    def testName(self, test):
656        """Return a short test name. Called by `nose.case.Test.__str__`.
657
658        :param test: the test case
659        :type test: :class:`nose.case.Test`
660        """
661        pass
662    testName._new = True
663
664    def wantClass(self, cls):
665        """Return true if you want the main test selector to collect
666        tests from this class, false if you don't, and None if you don't
667        care.
668
669        :param cls: The class being examined by the selector
670        """
671        pass
672
673    def wantDirectory(self, dirname):
674        """Return true if you want test collection to descend into this
675        directory, false if you do not, and None if you don't care.
676
677        :param dirname: Full path to directory being examined by the selector
678        """
679        pass
680
681    def wantFile(self, file):
682        """Return true if you want to collect tests from this file,
683        false if you do not and None if you don't care.
684
685        Change from 0.9: The optional package parameter is no longer passed.
686
687        :param file: Full path to file being examined by the selector
688        """
689        pass
690
691    def wantFunction(self, function):
692        """Return true to collect this function as a test, false to
693        prevent it from being collected, and None if you don't care.
694
695        :param function: The function object being examined by the selector
696        """
697        pass
698
699    def wantMethod(self, method):
700        """Return true to collect this method as a test, false to
701        prevent it from being collected, and None if you don't care.
702
703        :param method: The method object being examined by the selector
704        :type method: unbound method
705        """
706        pass
707
708    def wantModule(self, module):
709        """Return true if you want to collection to descend into this
710        module, false to prevent the collector from descending into the
711        module, and None if you don't care.
712
713        :param module: The module object being examined by the selector
714        :type module: python module
715        """
716        pass
717
718    def wantModuleTests(self, module):
719        """
720        .. warning:: DEPRECATED -- this method will not be called, it has
721                     been folded into wantModule.
722        """
723        pass
724    wantModuleTests.deprecated = True
725
726