From a7bc7156322e3a2dee50623e641e012249f6389c Mon Sep 17 00:00:00 2001
From: Rong Jinhui
Date: Mon, 12 Oct 2015 14:37:31 +0800
Subject: Import version of 1.2.1
Change-Id: I6d7bd5702c6c2516f71dc9ba48537d8e98c6fb22
Signed-off-by: Rong Jinhui
---
AUTHORS | 25 +
CHANGELOG | 678 ++++++
MANIFEST.in | 18 +
NEWS | 17 +
PKG-INFO | 38 +
README.txt | 494 +++++
bin/nosetests | 6 +
distribute_setup.py | 485 +++++
doc/.static/nose.css | 74 +
doc/.templates/index.html | 52 +
doc/.templates/indexsidebar.html | 56 +
doc/.templates/layout.html | 16 +
doc/.templates/page.html | 7 +
doc/Makefile | 89 +
doc/api.rst | 20 +
doc/api/commands.rst | 2 +
doc/api/config.rst | 5 +
doc/api/core.rst | 5 +
doc/api/importer.rst | 5 +
doc/api/inspector.rst | 5 +
doc/api/loader.rst | 2 +
doc/api/plugin_manager.rst | 2 +
doc/api/proxy.rst | 2 +
doc/api/result.rst | 2 +
doc/api/selector.rst | 2 +
doc/api/suite.rst | 2 +
doc/api/test_cases.rst | 8 +
doc/api/twistedtools.rst | 2 +
doc/api/util.rst | 5 +
doc/conf.py | 237 ++
doc/contributing.rst | 50 +
doc/developing.rst | 25 +
doc/docstring.py | 25 +
doc/finding_tests.rst | 32 +
doc/further_reading.rst | 34 +
doc/index.html | 8 +
doc/index.rst | 79 +
doc/man.rst | 24 +
doc/manbuilder.py | 24 +
doc/manbuilder.pyc | Bin 0 -> 1290 bytes
doc/manpage.py | 1119 ++++++++++
doc/manpage.pyc | Bin 0 -> 51122 bytes
doc/more_info.rst | 48 +
doc/news.rst | 4 +
doc/plugins.rst | 70 +
doc/plugins/allmodules.rst | 4 +
doc/plugins/attrib.rst | 4 +
doc/plugins/builtin.rst | 30 +
doc/plugins/capture.rst | 5 +
doc/plugins/collect.rst | 4 +
doc/plugins/cover.rst | 14 +
doc/plugins/debug.rst | 4 +
doc/plugins/deprecated.rst | 4 +
doc/plugins/doctests.rst | 4 +
doc/plugins/documenting.rst | 62 +
doc/plugins/errorclasses.rst | 7 +
doc/plugins/failuredetail.rst | 4 +
doc/plugins/interface.rst | 122 ++
doc/plugins/isolate.rst | 4 +
doc/plugins/logcapture.rst | 4 +
doc/plugins/multiprocess.rst | 5 +
doc/plugins/other.rst | 6 +
doc/plugins/prof.rst | 4 +
doc/plugins/skip.rst | 5 +
doc/plugins/testid.rst | 4 +
doc/plugins/testing.rst | 7 +
doc/plugins/writing.rst | 1 +
doc/plugins/xunit.rst | 4 +
doc/rtd-requirements.txt | 3 +
doc/setuptools_integration.rst | 38 +
doc/testing.rst | 55 +
doc/testing_tools.rst | 11 +
doc/usage.rst | 42 +
doc/writing_tests.rst | 172 ++
examples/attrib_plugin.py | 82 +
examples/html_plugin/htmlplug.py | 92 +
examples/html_plugin/setup.py | 24 +
examples/plugin/plug.py | 4 +
examples/plugin/setup.py | 27 +
.../doc_tests/test_addplugins/support/test.py | 2 +
.../doc_tests/test_addplugins/support/test.pyc | Bin 0 -> 352 bytes
.../doc_tests/test_addplugins/test_addplugins.rst | 80 +
.../doc_tests/test_allmodules/support/mod.py | 5 +
.../doc_tests/test_allmodules/support/mod.pyc | Bin 0 -> 601 bytes
.../doc_tests/test_allmodules/support/test.py | 2 +
.../doc_tests/test_allmodules/support/test.pyc | Bin 0 -> 352 bytes
.../doc_tests/test_allmodules/test_allmodules.rst | 67 +
.../test_coverage_html/coverage_html_fixtures.pyc | Bin 0 -> 1233 bytes
.../doc_tests/test_coverage_html/support/blah.pyc | Bin 0 -> 402 bytes
.../support/tests/test_covered.pyc | Bin 0 -> 337 bytes
.../test_doctest_fixtures/doctest_fixtures.rst | 122 ++
.../doctest_fixtures_fixtures.py | 17 +
.../doctest_fixtures_fixtures.pyc | Bin 0 -> 1234 bytes
.../doc_tests/test_init_plugin/example.cfg | 3 +
.../doc_tests/test_init_plugin/init_plugin.rst | 164 ++
.../test_init_plugin/init_plugin.rst.py3.patch | 10 +
.../support/unwanted_package/__init__.py | 1 +
.../support/unwanted_package/__init__.pyc | Bin 0 -> 193 bytes
.../support/unwanted_package/test_spam.py | 3 +
.../support/unwanted_package/test_spam.pyc | Bin 0 -> 439 bytes
.../support/wanted_package/__init__.py | 1 +
.../support/wanted_package/__init__.pyc | Bin 0 -> 191 bytes
.../support/wanted_package/test_eggs.py | 3 +
.../support/wanted_package/test_eggs.pyc | Bin 0 -> 435 bytes
.../doc_tests/test_issue089/unwanted_package.rst | 70 +
.../test_issue097/plugintest_environment.rst | 160 ++
.../doc_tests/test_issue107/plugin_exceptions.rst | 149 ++
.../doc_tests/test_issue107/support/test_spam.py | 5 +
.../doc_tests/test_issue107/support/test_spam.pyc | Bin 0 -> 593 bytes
.../doc_tests/test_issue119/empty_plugin.rst | 57 +
.../doc_tests/test_issue119/test_zeronine.py | 26 +
.../doc_tests/test_issue119/test_zeronine.pyc | Bin 0 -> 1560 bytes
.../doc_tests/test_issue142/errorclass_failure.rst | 124 ++
.../support/errorclass_failing_test.py | 7 +
.../support/errorclass_failing_test.pyc | Bin 0 -> 690 bytes
.../support/errorclass_failure_plugin.py | 16 +
.../support/errorclass_failure_plugin.pyc | Bin 0 -> 1248 bytes
.../test_issue142/support/errorclass_tests.py | 20 +
.../test_issue142/support/errorclass_tests.pyc | Bin 0 -> 1628 bytes
.../doc_tests/test_issue145/imported_tests.rst | 117 +
.../test_issue145/support/package1/__init__.py | 2 +
.../test_issue145/support/package1/__init__.pyc | Bin 0 -> 399 bytes
.../test_issue145/support/package1/test_module.py | 12 +
.../test_issue145/support/package1/test_module.pyc | Bin 0 -> 1307 bytes
.../test_issue145/support/package2c/__init__.py | 2 +
.../test_issue145/support/package2c/__init__.pyc | Bin 0 -> 402 bytes
.../test_issue145/support/package2c/test_module.py | 1 +
.../support/package2c/test_module.pyc | Bin 0 -> 283 bytes
.../test_issue145/support/package2f/__init__.py | 2 +
.../test_issue145/support/package2f/__init__.pyc | Bin 0 -> 402 bytes
.../test_issue145/support/package2f/test_module.py | 1 +
.../support/package2f/test_module.pyc | Bin 0 -> 263 bytes
.../doc_tests/test_multiprocess/multiprocess.rst | 269 +++
.../test_multiprocess/multiprocess_fixtures.py | 16 +
.../test_multiprocess/multiprocess_fixtures.pyc | Bin 0 -> 850 bytes
.../test_multiprocess/support/test_can_split.py | 30 +
.../test_multiprocess/support/test_can_split.pyc | Bin 0 -> 2128 bytes
.../test_multiprocess/support/test_not_shared.py | 30 +
.../test_multiprocess/support/test_not_shared.pyc | Bin 0 -> 2126 bytes
.../test_multiprocess/support/test_shared.py | 49 +
.../test_multiprocess/support/test_shared.pyc | Bin 0 -> 3050 bytes
.../restricted_plugin_options.rst | 89 +
.../restricted_plugin_options.rst.py3.patch | 9 +
.../test_restricted_plugin_options/support/bad.cfg | 2 +
.../support/start.cfg | 2 +
.../test_restricted_plugin_options/support/test.py | 2 +
.../support/test.pyc | Bin 0 -> 382 bytes
.../test_selector_plugin/selector_plugin.rst | 119 +
.../test_selector_plugin/support/mymodule.py | 2 +
.../test_selector_plugin/support/mymodule.pyc | Bin 0 -> 407 bytes
.../support/mypackage/__init__.py | 1 +
.../support/mypackage/__init__.pyc | Bin 0 -> 193 bytes
.../support/mypackage/math/__init__.py | 1 +
.../support/mypackage/math/__init__.pyc | Bin 0 -> 249 bytes
.../support/mypackage/math/basic.py | 5 +
.../support/mypackage/math/basic.pyc | Bin 0 -> 623 bytes
.../support/mypackage/strings.py | 2 +
.../support/mypackage/strings.pyc | Bin 0 -> 418 bytes
.../support/tests/math/basic.py | 17 +
.../support/tests/math/basic.pyc | Bin 0 -> 1609 bytes
.../support/tests/mymodule/my_function.py | 7 +
.../support/tests/mymodule/my_function.pyc | Bin 0 -> 862 bytes
.../support/tests/strings/cat.py | 12 +
.../support/tests/strings/cat.pyc | Bin 0 -> 1129 bytes
.../test_selector_plugin/support/tests/testlib.py | 6 +
.../test_selector_plugin/support/tests/testlib.pyc | Bin 0 -> 541 bytes
.../test_xunit_plugin/support/nosetests.xml | 25 +
.../test_xunit_plugin/support/test_skip.py | 13 +
.../test_xunit_plugin/support/test_skip.pyc | Bin 0 -> 1121 bytes
.../doc_tests/test_xunit_plugin/test_skips.rst | 40 +
functional_tests/support/att/test_attr.py | 96 +
functional_tests/support/att/test_attr.pyc | Bin 0 -> 5486 bytes
functional_tests/support/coverage/blah.py | 6 +
functional_tests/support/coverage/blah.pyc | Bin 0 -> 519 bytes
.../support/coverage/tests/test_covered.py | 4 +
.../support/coverage/tests/test_covered.pyc | Bin 0 -> 406 bytes
functional_tests/support/coverage2/blah.py | 6 +
functional_tests/support/coverage2/moo.py | 2 +
functional_tests/support/coverage2/moo.pyc | Bin 0 -> 334 bytes
.../support/coverage2/tests/test_covered.py | 8 +
.../support/coverage2/tests/test_covered.pyc | Bin 0 -> 632 bytes
functional_tests/support/ctx/mod_import_skip.py | 9 +
functional_tests/support/ctx/mod_import_skip.pyc | Bin 0 -> 705 bytes
functional_tests/support/ctx/mod_setup_fails.py | 12 +
functional_tests/support/ctx/mod_setup_fails.pyc | Bin 0 -> 831 bytes
functional_tests/support/ctx/mod_setup_skip.py | 14 +
functional_tests/support/ctx/mod_setup_skip.pyc | Bin 0 -> 855 bytes
functional_tests/support/dir1/mod.py | 1 +
functional_tests/support/dir1/mod.pyc | Bin 0 -> 152 bytes
functional_tests/support/dir1/pak/__init__.py | 1 +
functional_tests/support/dir1/pak/__init__.pyc | Bin 0 -> 161 bytes
functional_tests/support/dir1/pak/mod.py | 1 +
functional_tests/support/dir1/pak/mod.pyc | Bin 0 -> 156 bytes
functional_tests/support/dir1/pak/sub/__init__.py | 1 +
functional_tests/support/dir1/pak/sub/__init__.pyc | Bin 0 -> 165 bytes
functional_tests/support/dir2/mod.py | 1 +
functional_tests/support/dir2/mod.pyc | Bin 0 -> 152 bytes
functional_tests/support/dir2/pak/__init__.py | 1 +
functional_tests/support/dir2/pak/__init__.pyc | Bin 0 -> 161 bytes
functional_tests/support/dir2/pak/mod.py | 1 +
functional_tests/support/dir2/pak/mod.pyc | Bin 0 -> 156 bytes
functional_tests/support/dir2/pak/sub/__init__.py | 1 +
functional_tests/support/dir2/pak/sub/__init__.pyc | Bin 0 -> 165 bytes
functional_tests/support/dtt/docs/doc.txt | 6 +
functional_tests/support/dtt/docs/errdoc.txt | 7 +
functional_tests/support/dtt/docs/nodoc.txt | 1 +
functional_tests/support/dtt/some_mod.py | 17 +
functional_tests/support/dtt/some_mod.pyc | Bin 0 -> 467 bytes
functional_tests/support/empty/.hidden | 0
.../support/ep/Some_plugin.egg-info/PKG-INFO | 10 +
.../support/ep/Some_plugin.egg-info/SOURCES.txt | 6 +
.../ep/Some_plugin.egg-info/dependency_links.txt | 1 +
.../ep/Some_plugin.egg-info/entry_points.txt | 3 +
.../support/ep/Some_plugin.egg-info/top_level.txt | 1 +
functional_tests/support/ep/setup.py | 10 +
functional_tests/support/ep/someplugin.py | 4 +
functional_tests/support/fdp/test_fdp.py | 10 +
functional_tests/support/fdp/test_fdp.pyc | Bin 0 -> 794 bytes
functional_tests/support/fdp/test_fdp_no_capt.py | 9 +
functional_tests/support/fdp/test_fdp_no_capt.pyc | Bin 0 -> 809 bytes
functional_tests/support/gen/test.py | 12 +
functional_tests/support/gen/test.pyc | Bin 0 -> 753 bytes
functional_tests/support/id_fails/test_a.py | 1 +
functional_tests/support/id_fails/test_a.pyc | Bin 0 -> 204 bytes
functional_tests/support/id_fails/test_b.py | 5 +
functional_tests/support/id_fails/test_b.pyc | Bin 0 -> 535 bytes
functional_tests/support/idp/exm.py | 21 +
functional_tests/support/idp/exm.pyc | Bin 0 -> 531 bytes
functional_tests/support/idp/tests.py | 38 +
functional_tests/support/idp/tests.pyc | Bin 0 -> 2603 bytes
functional_tests/support/ipt/test1/ipthelp.py | 4 +
functional_tests/support/ipt/test1/ipthelp.pyc | Bin 0 -> 376 bytes
functional_tests/support/ipt/test1/tests.py | 7 +
functional_tests/support/ipt/test1/tests.pyc | Bin 0 -> 455 bytes
functional_tests/support/ipt/test2/ipthelp.py | 5 +
functional_tests/support/ipt/test2/ipthelp.pyc | Bin 0 -> 397 bytes
functional_tests/support/ipt/test2/tests.py | 8 +
functional_tests/support/ipt/test2/tests.pyc | Bin 0 -> 463 bytes
functional_tests/support/issue038/test.py | 9 +
functional_tests/support/issue038/test.pyc | Bin 0 -> 590 bytes
functional_tests/support/issue072/test.py | 4 +
functional_tests/support/issue072/test.pyc | Bin 0 -> 400 bytes
.../support/issue082/_mypackage/__init__.py | 1 +
.../support/issue082/_mypackage/_eggs.py | 8 +
.../support/issue082/_mypackage/bacon.py | 8 +
.../support/issue082/mypublicpackage/__init__.py | 1 +
.../support/issue082/mypublicpackage/__init__.pyc | Bin 0 -> 177 bytes
.../support/issue082/mypublicpackage/_foo.py | 8 +
.../support/issue082/mypublicpackage/_foo.pyc | Bin 0 -> 214 bytes
.../support/issue082/mypublicpackage/bar.py | 8 +
.../support/issue082/mypublicpackage/bar.pyc | Bin 0 -> 213 bytes
functional_tests/support/issue130/test.py | 5 +
functional_tests/support/issue130/test.pyc | Bin 0 -> 545 bytes
.../support/issue143/not-a-package/__init__.py | 1 +
.../support/issue143/not-a-package/test.py | 2 +
.../support/issue191/UNKNOWN.egg-info/PKG-INFO | 10 +
.../support/issue191/UNKNOWN.egg-info/SOURCES.txt | 6 +
.../issue191/UNKNOWN.egg-info/dependency_links.txt | 1 +
.../issue191/UNKNOWN.egg-info/top_level.txt | 1 +
functional_tests/support/issue191/setup.cfg | 2 +
functional_tests/support/issue191/setup.py | 3 +
functional_tests/support/issue191/test.py | 2 +
functional_tests/support/issue191/test.pyc | Bin 0 -> 318 bytes
.../support/issue269/test_bad_class.py | 5 +
.../support/issue269/test_bad_class.pyc | Bin 0 -> 809 bytes
.../support/issue279/test_mod_setup_fails.py | 5 +
.../support/issue279/test_mod_setup_fails.pyc | Bin 0 -> 622 bytes
functional_tests/support/issue408/nosetests.xml | 0
functional_tests/support/issue408/test.py | 16 +
functional_tests/support/issue408/test.pyc | Bin 0 -> 1591 bytes
functional_tests/support/ltfn/state.py | 1 +
functional_tests/support/ltfn/state.pyc | Bin 0 -> 171 bytes
functional_tests/support/ltfn/test_mod.py | 10 +
functional_tests/support/ltfn/test_mod.pyc | Bin 0 -> 845 bytes
.../support/ltfn/test_pak1/__init__.py | 13 +
.../support/ltfn/test_pak1/__init__.pyc | Bin 0 -> 1127 bytes
.../support/ltfn/test_pak1/test_mod.py | 12 +
.../support/ltfn/test_pak1/test_mod.pyc | Bin 0 -> 933 bytes
.../support/ltfn/test_pak2/__init__.py | 13 +
.../support/ltfn/test_pak2/__init__.pyc | Bin 0 -> 1127 bytes
functional_tests/support/ltftc/tests.py | 9 +
functional_tests/support/ltftc/tests.pyc | Bin 0 -> 822 bytes
.../namespace_pkg/namespace_pkg/__init__.py | 2 +
.../namespace_pkg/namespace_pkg/__init__.pyc | Bin 0 -> 271 bytes
.../support/namespace_pkg/namespace_pkg/example.py | 1 +
.../namespace_pkg/namespace_pkg/example.pyc | Bin 0 -> 213 bytes
.../namespace_pkg/namespace_pkg/test_pkg.py | 6 +
.../namespace_pkg/namespace_pkg/test_pkg.pyc | Bin 0 -> 609 bytes
.../site-packages/namespace_pkg/__init__.py | 2 +
.../site-packages/namespace_pkg/example2.py | 1 +
.../site-packages/namespace_pkg/example2.pyc | Bin 0 -> 235 bytes
.../site-packages/namespace_pkg/test_pkg2.py | 6 +
.../site-packages/namespace_pkg/test_pkg2.pyc | Bin 0 -> 640 bytes
functional_tests/support/package1/example.py | 8 +
functional_tests/support/package1/example.pyc | Bin 0 -> 416 bytes
.../package1/tests/test_example_function.py | 15 +
.../package1/tests/test_example_function.pyc | Bin 0 -> 1503 bytes
functional_tests/support/package2/maths.py | 11 +
functional_tests/support/package2/maths.pyc | Bin 0 -> 869 bytes
.../support/package2/test_pak/__init__.py | 11 +
.../support/package2/test_pak/__init__.pyc | Bin 0 -> 669 bytes
.../support/package2/test_pak/test_mod.py | 20 +
.../support/package2/test_pak/test_mod.pyc | Bin 0 -> 1446 bytes
.../support/package2/test_pak/test_sub/__init__.py | 9 +
.../package2/test_pak/test_sub/__init__.pyc | Bin 0 -> 719 bytes
.../support/package2/test_pak/test_sub/test_mod.py | 36 +
.../package2/test_pak/test_sub/test_mod.pyc | Bin 0 -> 3157 bytes
functional_tests/support/package3/lib/a.py | 2 +
functional_tests/support/package3/lib/a.pyc | Bin 0 -> 317 bytes
functional_tests/support/package3/src/b.py | 2 +
functional_tests/support/package3/src/b.pyc | Bin 0 -> 317 bytes
functional_tests/support/package3/tests/test_a.py | 4 +
functional_tests/support/package3/tests/test_a.pyc | Bin 0 -> 376 bytes
functional_tests/support/package3/tests/test_b.py | 4 +
functional_tests/support/package3/tests/test_b.pyc | Bin 0 -> 376 bytes
functional_tests/support/pass/test.py | 2 +
functional_tests/support/pass/test.pyc | Bin 0 -> 310 bytes
functional_tests/support/test.cfg | 2 +
functional_tests/support/test_buggy_generators.py | 29 +
functional_tests/support/test_buggy_generators.pyc | Bin 0 -> 2399 bytes
functional_tests/support/todo/test_with_todo.py | 7 +
functional_tests/support/todo/test_with_todo.pyc | Bin 0 -> 624 bytes
functional_tests/support/todo/todoplug.py | 7 +
functional_tests/support/todo/todoplug.pyc | Bin 0 -> 774 bytes
functional_tests/support/twist/test_twisted.py | 15 +
functional_tests/support/twist/test_twisted.pyc | Bin 0 -> 1301 bytes
functional_tests/support/xunit.xml | 24 +
.../support/xunit/test_xunit_as_suite.py | 24 +
.../support/xunit/test_xunit_as_suite.pyc | Bin 0 -> 1883 bytes
functional_tests/test_attribute_plugin.py | 181 ++
functional_tests/test_attribute_plugin.pyc | Bin 0 -> 9500 bytes
functional_tests/test_buggy_generators.py | 36 +
functional_tests/test_buggy_generators.pyc | Bin 0 -> 2034 bytes
functional_tests/test_cases.py | 38 +
functional_tests/test_cases.pyc | Bin 0 -> 2467 bytes
functional_tests/test_collector.py | 46 +
functional_tests/test_collector.pyc | Bin 0 -> 2148 bytes
functional_tests/test_commands.py | 47 +
functional_tests/test_commands.pyc | Bin 0 -> 2155 bytes
functional_tests/test_config_files.py | 41 +
functional_tests/test_config_files.pyc | Bin 0 -> 2161 bytes
functional_tests/test_coverage_plugin.py | 78 +
functional_tests/test_coverage_plugin.pyc | Bin 0 -> 4079 bytes
functional_tests/test_defaultpluginmanager.py | 22 +
functional_tests/test_defaultpluginmanager.pyc | Bin 0 -> 1409 bytes
functional_tests/test_doctest_plugin.py | 44 +
functional_tests/test_doctest_plugin.pyc | Bin 0 -> 2150 bytes
functional_tests/test_entrypoints.py | 17 +
functional_tests/test_entrypoints.pyc | Bin 0 -> 950 bytes
functional_tests/test_failuredetail_plugin.py | 50 +
functional_tests/test_failuredetail_plugin.pyc | Bin 0 -> 2001 bytes
functional_tests/test_generator_fixtures.py | 58 +
functional_tests/test_generator_fixtures.pyc | Bin 0 -> 2918 bytes
functional_tests/test_id_plugin.py | 261 +++
functional_tests/test_id_plugin.pyc | Bin 0 -> 10626 bytes
functional_tests/test_importer.py | 168 ++
functional_tests/test_importer.pyc | Bin 0 -> 6925 bytes
functional_tests/test_isolate_plugin.py | 57 +
functional_tests/test_isolate_plugin.pyc | Bin 0 -> 2767 bytes
.../test_issue120/support/some_test.py | 3 +
.../test_issue120/support/some_test.pyc | Bin 0 -> 343 bytes
.../test_issue120/test_named_test_with_doctest.rst | 25 +
functional_tests/test_issue_072.py | 45 +
functional_tests/test_issue_072.pyc | Bin 0 -> 2073 bytes
functional_tests/test_issue_082.py | 74 +
functional_tests/test_issue_082.pyc | Bin 0 -> 3382 bytes
functional_tests/test_issue_408.py | 25 +
functional_tests/test_issue_408.pyc | Bin 0 -> 1339 bytes
functional_tests/test_load_tests_from_test_case.py | 56 +
.../test_load_tests_from_test_case.pyc | Bin 0 -> 2972 bytes
functional_tests/test_loader.py | 451 ++++
functional_tests/test_loader.pyc | Bin 0 -> 18497 bytes
functional_tests/test_multiprocessing/__init__.py | 28 +
functional_tests/test_multiprocessing/__init__.pyc | Bin 0 -> 1681 bytes
.../test_multiprocessing/support/class.py | 14 +
.../test_multiprocessing/support/class.pyc | Bin 0 -> 1530 bytes
.../support/concurrent_shared/__init__.py | 6 +
.../support/concurrent_shared/__init__.pyc | Bin 0 -> 737 bytes
.../support/concurrent_shared/test.py | 11 +
.../support/concurrent_shared/test.pyc | Bin 0 -> 1158 bytes
.../test_multiprocessing/support/fake_nosetest.py | 14 +
.../support/keyboardinterrupt.py | 29 +
.../support/keyboardinterrupt.pyc | Bin 0 -> 1657 bytes
.../support/keyboardinterrupt_twice.py | 34 +
.../support/keyboardinterrupt_twice.pyc | Bin 0 -> 1824 bytes
.../test_multiprocessing/support/nameerror.py | 4 +
.../test_multiprocessing/support/nameerror.pyc | Bin 0 -> 201 bytes
.../test_multiprocessing/support/timeout.py | 12 +
.../test_multiprocessing/support/timeout.pyc | Bin 0 -> 841 bytes
.../test_multiprocessing/test_class.py | 13 +
.../test_multiprocessing/test_class.pyc | Bin 0 -> 944 bytes
.../test_multiprocessing/test_concurrent_shared.py | 13 +
.../test_concurrent_shared.pyc | Bin 0 -> 1099 bytes
.../test_multiprocessing/test_keyboardinterrupt.py | 84 +
.../test_keyboardinterrupt.pyc | Bin 0 -> 4177 bytes
.../test_multiprocessing/test_nameerror.py | 13 +
.../test_multiprocessing/test_nameerror.pyc | Bin 0 -> 1011 bytes
.../test_multiprocessing/test_process_timeout.py | 21 +
.../test_multiprocessing/test_process_timeout.pyc | Bin 0 -> 1702 bytes
functional_tests/test_namespace_pkg.py | 58 +
functional_tests/test_namespace_pkg.pyc | Bin 0 -> 2756 bytes
functional_tests/test_plugin_api.py | 45 +
functional_tests/test_plugin_api.pyc | Bin 0 -> 2298 bytes
functional_tests/test_plugins.py | 71 +
functional_tests/test_plugins.pyc | Bin 0 -> 3271 bytes
functional_tests/test_plugintest.py | 51 +
functional_tests/test_plugintest.pyc | Bin 0 -> 3702 bytes
functional_tests/test_program.py | 189 ++
functional_tests/test_program.pyc | Bin 0 -> 6931 bytes
functional_tests/test_result.py | 32 +
functional_tests/test_result.pyc | Bin 0 -> 1482 bytes
functional_tests/test_selector.py | 17 +
functional_tests/test_selector.pyc | Bin 0 -> 1101 bytes
functional_tests/test_skip_pdb_interaction.py | 49 +
functional_tests/test_skip_pdb_interaction.pyc | Bin 0 -> 2958 bytes
functional_tests/test_success.py | 43 +
functional_tests/test_success.pyc | Bin 0 -> 1790 bytes
functional_tests/test_suite.py | 47 +
functional_tests/test_suite.pyc | Bin 0 -> 2355 bytes
functional_tests/test_withid_failures.rst | 50 +
functional_tests/test_xunit.py | 61 +
functional_tests/test_xunit.pyc | Bin 0 -> 2957 bytes
install-rpm.sh | 3 +
lgpl.txt | 504 +++++
nose.egg-info/PKG-INFO | 38 +
nose.egg-info/SOURCES.txt | 608 ++++++
nose.egg-info/dependency_links.txt | 1 +
nose.egg-info/entry_points.txt | 7 +
nose.egg-info/not-zip-safe | 1 +
nose.egg-info/top_level.txt | 1 +
nose/__init__.py | 15 +
nose/case.py | 397 ++++
nose/commands.py | 163 ++
nose/config.py | 638 ++++++
nose/core.py | 324 +++
nose/exc.py | 9 +
nose/ext/__init__.py | 3 +
nose/ext/dtcompat.py | 2272 ++++++++++++++++++++
nose/failure.py | 39 +
nose/importer.py | 154 ++
nose/inspector.py | 207 ++
nose/loader.py | 595 +++++
nose/plugins/__init__.py | 190 ++
nose/plugins/allmodules.py | 45 +
nose/plugins/attrib.py | 286 +++
nose/plugins/base.py | 728 +++++++
nose/plugins/builtin.py | 34 +
nose/plugins/capture.py | 129 ++
nose/plugins/collect.py | 94 +
nose/plugins/cover.py | 228 ++
nose/plugins/debug.py | 62 +
nose/plugins/deprecated.py | 45 +
nose/plugins/doctests.py | 452 ++++
nose/plugins/errorclass.py | 210 ++
nose/plugins/failuredetail.py | 43 +
nose/plugins/isolate.py | 103 +
nose/plugins/logcapture.py | 242 +++
nose/plugins/manager.py | 460 ++++
nose/plugins/multiprocess.py | 819 +++++++
nose/plugins/plugintest.py | 416 ++++
nose/plugins/prof.py | 154 ++
nose/plugins/skip.py | 56 +
nose/plugins/testid.py | 306 +++
nose/plugins/xunit.py | 253 +++
nose/proxy.py | 191 ++
nose/pyversion.py | 130 ++
nose/result.py | 200 ++
nose/selector.py | 251 +++
nose/sphinx/__init__.py | 1 +
nose/sphinx/pluginopts.py | 186 ++
nose/suite.py | 607 ++++++
nose/tools/__init__.py | 11 +
nose/tools/nontrivial.py | 150 ++
nose/tools/trivial.py | 54 +
nose/twistedtools.py | 173 ++
nose/usage.txt | 110 +
nose/util.py | 663 ++++++
nosetests.1 | 495 +++++
patch.py | 639 ++++++
selftest.py | 60 +
setup.cfg | 14 +
setup.py | 121 ++
setup3lib.py | 151 ++
unit_tests/helpers.py | 6 +
unit_tests/helpers.pyc | Bin 0 -> 385 bytes
unit_tests/mock.py | 107 +
unit_tests/mock.pyc | Bin 0 -> 6605 bytes
unit_tests/support/bug101/tests.py | 9 +
unit_tests/support/bug105/tests.py | 49 +
unit_tests/support/bug105/tests.pyc | Bin 0 -> 2536 bytes
unit_tests/support/config_defaults/a.cfg | 2 +
unit_tests/support/config_defaults/b.cfg | 2 +
unit_tests/support/config_defaults/invalid.cfg | 1 +
.../support/config_defaults/invalid_value.cfg | 2 +
unit_tests/support/doctest/err_doctests.py | 12 +
unit_tests/support/doctest/err_doctests.pyc | Bin 0 -> 520 bytes
unit_tests/support/doctest/no_doctests.py | 9 +
unit_tests/support/doctest/no_doctests.pyc | Bin 0 -> 466 bytes
unit_tests/support/foo/__init__.py | 7 +
unit_tests/support/foo/__init__.pyc | Bin 0 -> 394 bytes
unit_tests/support/foo/bar/__init__.py | 1 +
unit_tests/support/foo/bar/__init__.pyc | Bin 0 -> 154 bytes
unit_tests/support/foo/bar/buz.py | 8 +
unit_tests/support/foo/bar/buz.pyc | Bin 0 -> 402 bytes
unit_tests/support/foo/doctests.txt | 7 +
unit_tests/support/foo/test_foo.py | 1 +
unit_tests/support/foo/tests/dir_test_file.py | 3 +
unit_tests/support/issue006/tests.py | 19 +
unit_tests/support/issue006/tests.pyc | Bin 0 -> 1555 bytes
unit_tests/support/issue065/tests.py | 5 +
unit_tests/support/issue065/tests.pyc | Bin 0 -> 594 bytes
unit_tests/support/issue270/__init__.py | 2 +
unit_tests/support/issue270/__init__.pyc | Bin 0 -> 315 bytes
unit_tests/support/issue270/foo_test.py | 7 +
unit_tests/support/issue270/foo_test.pyc | Bin 0 -> 711 bytes
unit_tests/support/other/file.txt | 1 +
unit_tests/support/pkgorg/lib/modernity.py | 1 +
unit_tests/support/pkgorg/tests/test_mod.py | 4 +
unit_tests/support/script.py | 3 +
unit_tests/support/test-dir/test.py | 1 +
unit_tests/support/test.py | 13 +
unit_tests/test_attribute_plugin.py | 53 +
unit_tests/test_attribute_plugin.pyc | Bin 0 -> 2919 bytes
unit_tests/test_bug105.py | 32 +
unit_tests/test_bug105.pyc | Bin 0 -> 1383 bytes
unit_tests/test_capture_plugin.py | 100 +
unit_tests/test_capture_plugin.pyc | Bin 0 -> 4129 bytes
unit_tests/test_cases.py | 274 +++
unit_tests/test_cases.pyc | Bin 0 -> 14843 bytes
unit_tests/test_config.py | 141 ++
unit_tests/test_config.pyc | Bin 0 -> 6636 bytes
unit_tests/test_config_defaults.rst | 146 ++
unit_tests/test_core.py | 96 +
unit_tests/test_core.pyc | Bin 0 -> 4349 bytes
unit_tests/test_deprecated_plugin.py | 131 ++
unit_tests/test_deprecated_plugin.pyc | Bin 0 -> 6165 bytes
unit_tests/test_doctest_error_handling.py | 40 +
unit_tests/test_doctest_error_handling.pyc | Bin 0 -> 2249 bytes
unit_tests/test_doctest_munging.rst | 105 +
unit_tests/test_id_plugin.py | 20 +
unit_tests/test_id_plugin.pyc | Bin 0 -> 1089 bytes
unit_tests/test_importer.py | 55 +
unit_tests/test_importer.pyc | Bin 0 -> 2493 bytes
unit_tests/test_inspector.py | 149 ++
unit_tests/test_inspector.pyc | Bin 0 -> 5352 bytes
unit_tests/test_isolation_plugin.py | 2 +
unit_tests/test_isolation_plugin.pyc | Bin 0 -> 362 bytes
unit_tests/test_issue155.rst | 46 +
unit_tests/test_issue270.rst | 22 +
unit_tests/test_issue270_fixtures.py | 11 +
unit_tests/test_issue270_fixtures.pyc | Bin 0 -> 734 bytes
unit_tests/test_issue_006.py | 31 +
unit_tests/test_issue_006.pyc | Bin 0 -> 1540 bytes
unit_tests/test_issue_064.py | 2 +
unit_tests/test_issue_064.pyc | Bin 0 -> 410 bytes
unit_tests/test_issue_065.py | 20 +
unit_tests/test_issue_065.pyc | Bin 0 -> 1143 bytes
unit_tests/test_issue_100.rst | 12 +
unit_tests/test_issue_100.rst.py3.patch | 8 +
unit_tests/test_issue_101.py | 27 +
unit_tests/test_issue_101.pyc | Bin 0 -> 1662 bytes
unit_tests/test_issue_159.rst | 6 +
unit_tests/test_issue_227.py | 12 +
unit_tests/test_issue_227.pyc | Bin 0 -> 680 bytes
unit_tests/test_issue_230.py | 21 +
unit_tests/test_issue_230.pyc | Bin 0 -> 1233 bytes
unit_tests/test_lazy_suite.py | 21 +
unit_tests/test_lazy_suite.pyc | Bin 0 -> 1458 bytes
unit_tests/test_loader.py | 501 +++++
unit_tests/test_loader.pyc | Bin 0 -> 20830 bytes
unit_tests/test_logcapture_plugin.py | 220 ++
unit_tests/test_logcapture_plugin.pyc | Bin 0 -> 9450 bytes
unit_tests/test_logging.py | 40 +
unit_tests/test_logging.pyc | Bin 0 -> 1752 bytes
unit_tests/test_ls_tree.rst | 50 +
unit_tests/test_multiprocess.py | 62 +
unit_tests/test_multiprocess.pyc | Bin 0 -> 2793 bytes
unit_tests/test_multiprocess_runner.py | 120 ++
unit_tests/test_multiprocess_runner.pyc | Bin 0 -> 6205 bytes
unit_tests/test_pdb_plugin.py | 117 +
unit_tests/test_pdb_plugin.pyc | Bin 0 -> 4864 bytes
unit_tests/test_plugin.py | 33 +
unit_tests/test_plugin.pyc | Bin 0 -> 1621 bytes
unit_tests/test_plugin_interfaces.py | 45 +
unit_tests/test_plugin_interfaces.pyc | Bin 0 -> 1914 bytes
unit_tests/test_plugin_manager.py | 74 +
unit_tests/test_plugin_manager.pyc | Bin 0 -> 5207 bytes
unit_tests/test_plugins.py | 415 ++++
unit_tests/test_plugins.pyc | Bin 0 -> 16605 bytes
unit_tests/test_result_proxy.py | 188 ++
unit_tests/test_result_proxy.pyc | Bin 0 -> 9498 bytes
unit_tests/test_selector.py | 200 ++
unit_tests/test_selector.pyc | Bin 0 -> 9127 bytes
unit_tests/test_selector_plugins.py | 30 +
unit_tests/test_selector_plugins.pyc | Bin 0 -> 1685 bytes
unit_tests/test_skip_plugin.py | 130 ++
unit_tests/test_skip_plugin.pyc | Bin 0 -> 5946 bytes
unit_tests/test_suite.py | 301 +++
unit_tests/test_suite.pyc | Bin 0 -> 12451 bytes
unit_tests/test_tools.py | 223 ++
unit_tests/test_tools.pyc | Bin 0 -> 9156 bytes
unit_tests/test_twisted.py | 93 +
unit_tests/test_twisted.pyc | Bin 0 -> 3562 bytes
unit_tests/test_twisted_testcase.py | 11 +
unit_tests/test_twisted_testcase.pyc | Bin 0 -> 750 bytes
unit_tests/test_utils.py | 180 ++
unit_tests/test_utils.pyc | Bin 0 -> 8894 bytes
unit_tests/test_xunit.py | 343 +++
unit_tests/test_xunit.pyc | Bin 0 -> 14095 bytes
609 files changed, 31143 insertions(+)
create mode 100644 AUTHORS
create mode 100644 CHANGELOG
create mode 100644 MANIFEST.in
create mode 100644 NEWS
create mode 100644 PKG-INFO
create mode 100644 README.txt
create mode 100755 bin/nosetests
create mode 100644 distribute_setup.py
create mode 100644 doc/.static/nose.css
create mode 100644 doc/.templates/index.html
create mode 100644 doc/.templates/indexsidebar.html
create mode 100644 doc/.templates/layout.html
create mode 100644 doc/.templates/page.html
create mode 100644 doc/Makefile
create mode 100644 doc/api.rst
create mode 100644 doc/api/commands.rst
create mode 100644 doc/api/config.rst
create mode 100644 doc/api/core.rst
create mode 100644 doc/api/importer.rst
create mode 100644 doc/api/inspector.rst
create mode 100644 doc/api/loader.rst
create mode 100644 doc/api/plugin_manager.rst
create mode 100644 doc/api/proxy.rst
create mode 100644 doc/api/result.rst
create mode 100644 doc/api/selector.rst
create mode 100644 doc/api/suite.rst
create mode 100644 doc/api/test_cases.rst
create mode 100644 doc/api/twistedtools.rst
create mode 100644 doc/api/util.rst
create mode 100644 doc/conf.py
create mode 100644 doc/contributing.rst
create mode 100644 doc/developing.rst
create mode 100644 doc/docstring.py
create mode 100644 doc/finding_tests.rst
create mode 100644 doc/further_reading.rst
create mode 100644 doc/index.html
create mode 100644 doc/index.rst
create mode 100644 doc/man.rst
create mode 100644 doc/manbuilder.py
create mode 100644 doc/manbuilder.pyc
create mode 100644 doc/manpage.py
create mode 100644 doc/manpage.pyc
create mode 100644 doc/more_info.rst
create mode 100644 doc/news.rst
create mode 100644 doc/plugins.rst
create mode 100644 doc/plugins/allmodules.rst
create mode 100644 doc/plugins/attrib.rst
create mode 100644 doc/plugins/builtin.rst
create mode 100644 doc/plugins/capture.rst
create mode 100644 doc/plugins/collect.rst
create mode 100644 doc/plugins/cover.rst
create mode 100644 doc/plugins/debug.rst
create mode 100644 doc/plugins/deprecated.rst
create mode 100644 doc/plugins/doctests.rst
create mode 100644 doc/plugins/documenting.rst
create mode 100644 doc/plugins/errorclasses.rst
create mode 100644 doc/plugins/failuredetail.rst
create mode 100644 doc/plugins/interface.rst
create mode 100644 doc/plugins/isolate.rst
create mode 100644 doc/plugins/logcapture.rst
create mode 100644 doc/plugins/multiprocess.rst
create mode 100644 doc/plugins/other.rst
create mode 100644 doc/plugins/prof.rst
create mode 100644 doc/plugins/skip.rst
create mode 100644 doc/plugins/testid.rst
create mode 100644 doc/plugins/testing.rst
create mode 100644 doc/plugins/writing.rst
create mode 100644 doc/plugins/xunit.rst
create mode 100644 doc/rtd-requirements.txt
create mode 100644 doc/setuptools_integration.rst
create mode 100644 doc/testing.rst
create mode 100644 doc/testing_tools.rst
create mode 100644 doc/usage.rst
create mode 100644 doc/writing_tests.rst
create mode 100644 examples/attrib_plugin.py
create mode 100644 examples/html_plugin/htmlplug.py
create mode 100644 examples/html_plugin/setup.py
create mode 100644 examples/plugin/plug.py
create mode 100644 examples/plugin/setup.py
create mode 100644 functional_tests/doc_tests/test_addplugins/support/test.py
create mode 100644 functional_tests/doc_tests/test_addplugins/support/test.pyc
create mode 100644 functional_tests/doc_tests/test_addplugins/test_addplugins.rst
create mode 100644 functional_tests/doc_tests/test_allmodules/support/mod.py
create mode 100644 functional_tests/doc_tests/test_allmodules/support/mod.pyc
create mode 100644 functional_tests/doc_tests/test_allmodules/support/test.py
create mode 100644 functional_tests/doc_tests/test_allmodules/support/test.pyc
create mode 100644 functional_tests/doc_tests/test_allmodules/test_allmodules.rst
create mode 100644 functional_tests/doc_tests/test_coverage_html/coverage_html_fixtures.pyc
create mode 100644 functional_tests/doc_tests/test_coverage_html/support/blah.pyc
create mode 100644 functional_tests/doc_tests/test_coverage_html/support/tests/test_covered.pyc
create mode 100644 functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures.rst
create mode 100644 functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures_fixtures.py
create mode 100644 functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures_fixtures.pyc
create mode 100644 functional_tests/doc_tests/test_init_plugin/example.cfg
create mode 100644 functional_tests/doc_tests/test_init_plugin/init_plugin.rst
create mode 100644 functional_tests/doc_tests/test_init_plugin/init_plugin.rst.py3.patch
create mode 100644 functional_tests/doc_tests/test_issue089/support/unwanted_package/__init__.py
create mode 100644 functional_tests/doc_tests/test_issue089/support/unwanted_package/__init__.pyc
create mode 100644 functional_tests/doc_tests/test_issue089/support/unwanted_package/test_spam.py
create mode 100644 functional_tests/doc_tests/test_issue089/support/unwanted_package/test_spam.pyc
create mode 100644 functional_tests/doc_tests/test_issue089/support/wanted_package/__init__.py
create mode 100644 functional_tests/doc_tests/test_issue089/support/wanted_package/__init__.pyc
create mode 100644 functional_tests/doc_tests/test_issue089/support/wanted_package/test_eggs.py
create mode 100644 functional_tests/doc_tests/test_issue089/support/wanted_package/test_eggs.pyc
create mode 100644 functional_tests/doc_tests/test_issue089/unwanted_package.rst
create mode 100644 functional_tests/doc_tests/test_issue097/plugintest_environment.rst
create mode 100644 functional_tests/doc_tests/test_issue107/plugin_exceptions.rst
create mode 100644 functional_tests/doc_tests/test_issue107/support/test_spam.py
create mode 100644 functional_tests/doc_tests/test_issue107/support/test_spam.pyc
create mode 100644 functional_tests/doc_tests/test_issue119/empty_plugin.rst
create mode 100644 functional_tests/doc_tests/test_issue119/test_zeronine.py
create mode 100644 functional_tests/doc_tests/test_issue119/test_zeronine.pyc
create mode 100644 functional_tests/doc_tests/test_issue142/errorclass_failure.rst
create mode 100644 functional_tests/doc_tests/test_issue142/support/errorclass_failing_test.py
create mode 100644 functional_tests/doc_tests/test_issue142/support/errorclass_failing_test.pyc
create mode 100644 functional_tests/doc_tests/test_issue142/support/errorclass_failure_plugin.py
create mode 100644 functional_tests/doc_tests/test_issue142/support/errorclass_failure_plugin.pyc
create mode 100644 functional_tests/doc_tests/test_issue142/support/errorclass_tests.py
create mode 100644 functional_tests/doc_tests/test_issue142/support/errorclass_tests.pyc
create mode 100644 functional_tests/doc_tests/test_issue145/imported_tests.rst
create mode 100644 functional_tests/doc_tests/test_issue145/support/package1/__init__.py
create mode 100644 functional_tests/doc_tests/test_issue145/support/package1/__init__.pyc
create mode 100644 functional_tests/doc_tests/test_issue145/support/package1/test_module.py
create mode 100644 functional_tests/doc_tests/test_issue145/support/package1/test_module.pyc
create mode 100644 functional_tests/doc_tests/test_issue145/support/package2c/__init__.py
create mode 100644 functional_tests/doc_tests/test_issue145/support/package2c/__init__.pyc
create mode 100644 functional_tests/doc_tests/test_issue145/support/package2c/test_module.py
create mode 100644 functional_tests/doc_tests/test_issue145/support/package2c/test_module.pyc
create mode 100644 functional_tests/doc_tests/test_issue145/support/package2f/__init__.py
create mode 100644 functional_tests/doc_tests/test_issue145/support/package2f/__init__.pyc
create mode 100644 functional_tests/doc_tests/test_issue145/support/package2f/test_module.py
create mode 100644 functional_tests/doc_tests/test_issue145/support/package2f/test_module.pyc
create mode 100644 functional_tests/doc_tests/test_multiprocess/multiprocess.rst
create mode 100644 functional_tests/doc_tests/test_multiprocess/multiprocess_fixtures.py
create mode 100644 functional_tests/doc_tests/test_multiprocess/multiprocess_fixtures.pyc
create mode 100644 functional_tests/doc_tests/test_multiprocess/support/test_can_split.py
create mode 100644 functional_tests/doc_tests/test_multiprocess/support/test_can_split.pyc
create mode 100644 functional_tests/doc_tests/test_multiprocess/support/test_not_shared.py
create mode 100644 functional_tests/doc_tests/test_multiprocess/support/test_not_shared.pyc
create mode 100644 functional_tests/doc_tests/test_multiprocess/support/test_shared.py
create mode 100644 functional_tests/doc_tests/test_multiprocess/support/test_shared.pyc
create mode 100644 functional_tests/doc_tests/test_restricted_plugin_options/restricted_plugin_options.rst
create mode 100644 functional_tests/doc_tests/test_restricted_plugin_options/restricted_plugin_options.rst.py3.patch
create mode 100644 functional_tests/doc_tests/test_restricted_plugin_options/support/bad.cfg
create mode 100644 functional_tests/doc_tests/test_restricted_plugin_options/support/start.cfg
create mode 100644 functional_tests/doc_tests/test_restricted_plugin_options/support/test.py
create mode 100644 functional_tests/doc_tests/test_restricted_plugin_options/support/test.pyc
create mode 100644 functional_tests/doc_tests/test_selector_plugin/selector_plugin.rst
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/mymodule.py
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/mymodule.pyc
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/mypackage/__init__.py
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/mypackage/__init__.pyc
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/__init__.py
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/__init__.pyc
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/basic.py
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/basic.pyc
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/mypackage/strings.py
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/mypackage/strings.pyc
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/tests/math/basic.py
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/tests/math/basic.pyc
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/tests/mymodule/my_function.py
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/tests/mymodule/my_function.pyc
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/tests/strings/cat.py
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/tests/strings/cat.pyc
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/tests/testlib.py
create mode 100644 functional_tests/doc_tests/test_selector_plugin/support/tests/testlib.pyc
create mode 100644 functional_tests/doc_tests/test_xunit_plugin/support/nosetests.xml
create mode 100644 functional_tests/doc_tests/test_xunit_plugin/support/test_skip.py
create mode 100644 functional_tests/doc_tests/test_xunit_plugin/support/test_skip.pyc
create mode 100644 functional_tests/doc_tests/test_xunit_plugin/test_skips.rst
create mode 100644 functional_tests/support/att/test_attr.py
create mode 100644 functional_tests/support/att/test_attr.pyc
create mode 100644 functional_tests/support/coverage/blah.py
create mode 100644 functional_tests/support/coverage/blah.pyc
create mode 100644 functional_tests/support/coverage/tests/test_covered.py
create mode 100644 functional_tests/support/coverage/tests/test_covered.pyc
create mode 100644 functional_tests/support/coverage2/blah.py
create mode 100644 functional_tests/support/coverage2/moo.py
create mode 100644 functional_tests/support/coverage2/moo.pyc
create mode 100644 functional_tests/support/coverage2/tests/test_covered.py
create mode 100644 functional_tests/support/coverage2/tests/test_covered.pyc
create mode 100644 functional_tests/support/ctx/mod_import_skip.py
create mode 100644 functional_tests/support/ctx/mod_import_skip.pyc
create mode 100644 functional_tests/support/ctx/mod_setup_fails.py
create mode 100644 functional_tests/support/ctx/mod_setup_fails.pyc
create mode 100644 functional_tests/support/ctx/mod_setup_skip.py
create mode 100644 functional_tests/support/ctx/mod_setup_skip.pyc
create mode 100644 functional_tests/support/dir1/mod.py
create mode 100644 functional_tests/support/dir1/mod.pyc
create mode 100644 functional_tests/support/dir1/pak/__init__.py
create mode 100644 functional_tests/support/dir1/pak/__init__.pyc
create mode 100644 functional_tests/support/dir1/pak/mod.py
create mode 100644 functional_tests/support/dir1/pak/mod.pyc
create mode 100644 functional_tests/support/dir1/pak/sub/__init__.py
create mode 100644 functional_tests/support/dir1/pak/sub/__init__.pyc
create mode 100644 functional_tests/support/dir2/mod.py
create mode 100644 functional_tests/support/dir2/mod.pyc
create mode 100644 functional_tests/support/dir2/pak/__init__.py
create mode 100644 functional_tests/support/dir2/pak/__init__.pyc
create mode 100644 functional_tests/support/dir2/pak/mod.py
create mode 100644 functional_tests/support/dir2/pak/mod.pyc
create mode 100644 functional_tests/support/dir2/pak/sub/__init__.py
create mode 100644 functional_tests/support/dir2/pak/sub/__init__.pyc
create mode 100644 functional_tests/support/dtt/docs/doc.txt
create mode 100644 functional_tests/support/dtt/docs/errdoc.txt
create mode 100644 functional_tests/support/dtt/docs/nodoc.txt
create mode 100644 functional_tests/support/dtt/some_mod.py
create mode 100644 functional_tests/support/dtt/some_mod.pyc
create mode 100644 functional_tests/support/empty/.hidden
create mode 100644 functional_tests/support/ep/Some_plugin.egg-info/PKG-INFO
create mode 100644 functional_tests/support/ep/Some_plugin.egg-info/SOURCES.txt
create mode 100644 functional_tests/support/ep/Some_plugin.egg-info/dependency_links.txt
create mode 100644 functional_tests/support/ep/Some_plugin.egg-info/entry_points.txt
create mode 100644 functional_tests/support/ep/Some_plugin.egg-info/top_level.txt
create mode 100644 functional_tests/support/ep/setup.py
create mode 100644 functional_tests/support/ep/someplugin.py
create mode 100644 functional_tests/support/fdp/test_fdp.py
create mode 100644 functional_tests/support/fdp/test_fdp.pyc
create mode 100644 functional_tests/support/fdp/test_fdp_no_capt.py
create mode 100644 functional_tests/support/fdp/test_fdp_no_capt.pyc
create mode 100644 functional_tests/support/gen/test.py
create mode 100644 functional_tests/support/gen/test.pyc
create mode 100644 functional_tests/support/id_fails/test_a.py
create mode 100644 functional_tests/support/id_fails/test_a.pyc
create mode 100644 functional_tests/support/id_fails/test_b.py
create mode 100644 functional_tests/support/id_fails/test_b.pyc
create mode 100644 functional_tests/support/idp/exm.py
create mode 100644 functional_tests/support/idp/exm.pyc
create mode 100644 functional_tests/support/idp/tests.py
create mode 100644 functional_tests/support/idp/tests.pyc
create mode 100644 functional_tests/support/ipt/test1/ipthelp.py
create mode 100644 functional_tests/support/ipt/test1/ipthelp.pyc
create mode 100644 functional_tests/support/ipt/test1/tests.py
create mode 100644 functional_tests/support/ipt/test1/tests.pyc
create mode 100644 functional_tests/support/ipt/test2/ipthelp.py
create mode 100644 functional_tests/support/ipt/test2/ipthelp.pyc
create mode 100644 functional_tests/support/ipt/test2/tests.py
create mode 100644 functional_tests/support/ipt/test2/tests.pyc
create mode 100644 functional_tests/support/issue038/test.py
create mode 100644 functional_tests/support/issue038/test.pyc
create mode 100644 functional_tests/support/issue072/test.py
create mode 100644 functional_tests/support/issue072/test.pyc
create mode 100644 functional_tests/support/issue082/_mypackage/__init__.py
create mode 100644 functional_tests/support/issue082/_mypackage/_eggs.py
create mode 100644 functional_tests/support/issue082/_mypackage/bacon.py
create mode 100644 functional_tests/support/issue082/mypublicpackage/__init__.py
create mode 100644 functional_tests/support/issue082/mypublicpackage/__init__.pyc
create mode 100644 functional_tests/support/issue082/mypublicpackage/_foo.py
create mode 100644 functional_tests/support/issue082/mypublicpackage/_foo.pyc
create mode 100644 functional_tests/support/issue082/mypublicpackage/bar.py
create mode 100644 functional_tests/support/issue082/mypublicpackage/bar.pyc
create mode 100644 functional_tests/support/issue130/test.py
create mode 100644 functional_tests/support/issue130/test.pyc
create mode 100644 functional_tests/support/issue143/not-a-package/__init__.py
create mode 100644 functional_tests/support/issue143/not-a-package/test.py
create mode 100644 functional_tests/support/issue191/UNKNOWN.egg-info/PKG-INFO
create mode 100644 functional_tests/support/issue191/UNKNOWN.egg-info/SOURCES.txt
create mode 100644 functional_tests/support/issue191/UNKNOWN.egg-info/dependency_links.txt
create mode 100644 functional_tests/support/issue191/UNKNOWN.egg-info/top_level.txt
create mode 100644 functional_tests/support/issue191/setup.cfg
create mode 100644 functional_tests/support/issue191/setup.py
create mode 100644 functional_tests/support/issue191/test.py
create mode 100644 functional_tests/support/issue191/test.pyc
create mode 100644 functional_tests/support/issue269/test_bad_class.py
create mode 100644 functional_tests/support/issue269/test_bad_class.pyc
create mode 100644 functional_tests/support/issue279/test_mod_setup_fails.py
create mode 100644 functional_tests/support/issue279/test_mod_setup_fails.pyc
create mode 100644 functional_tests/support/issue408/nosetests.xml
create mode 100644 functional_tests/support/issue408/test.py
create mode 100644 functional_tests/support/issue408/test.pyc
create mode 100644 functional_tests/support/ltfn/state.py
create mode 100644 functional_tests/support/ltfn/state.pyc
create mode 100644 functional_tests/support/ltfn/test_mod.py
create mode 100644 functional_tests/support/ltfn/test_mod.pyc
create mode 100644 functional_tests/support/ltfn/test_pak1/__init__.py
create mode 100644 functional_tests/support/ltfn/test_pak1/__init__.pyc
create mode 100644 functional_tests/support/ltfn/test_pak1/test_mod.py
create mode 100644 functional_tests/support/ltfn/test_pak1/test_mod.pyc
create mode 100644 functional_tests/support/ltfn/test_pak2/__init__.py
create mode 100644 functional_tests/support/ltfn/test_pak2/__init__.pyc
create mode 100644 functional_tests/support/ltftc/tests.py
create mode 100644 functional_tests/support/ltftc/tests.pyc
create mode 100644 functional_tests/support/namespace_pkg/namespace_pkg/__init__.py
create mode 100644 functional_tests/support/namespace_pkg/namespace_pkg/__init__.pyc
create mode 100644 functional_tests/support/namespace_pkg/namespace_pkg/example.py
create mode 100644 functional_tests/support/namespace_pkg/namespace_pkg/example.pyc
create mode 100644 functional_tests/support/namespace_pkg/namespace_pkg/test_pkg.py
create mode 100644 functional_tests/support/namespace_pkg/namespace_pkg/test_pkg.pyc
create mode 100644 functional_tests/support/namespace_pkg/site-packages/namespace_pkg/__init__.py
create mode 100644 functional_tests/support/namespace_pkg/site-packages/namespace_pkg/example2.py
create mode 100644 functional_tests/support/namespace_pkg/site-packages/namespace_pkg/example2.pyc
create mode 100644 functional_tests/support/namespace_pkg/site-packages/namespace_pkg/test_pkg2.py
create mode 100644 functional_tests/support/namespace_pkg/site-packages/namespace_pkg/test_pkg2.pyc
create mode 100644 functional_tests/support/package1/example.py
create mode 100644 functional_tests/support/package1/example.pyc
create mode 100644 functional_tests/support/package1/tests/test_example_function.py
create mode 100644 functional_tests/support/package1/tests/test_example_function.pyc
create mode 100644 functional_tests/support/package2/maths.py
create mode 100644 functional_tests/support/package2/maths.pyc
create mode 100644 functional_tests/support/package2/test_pak/__init__.py
create mode 100644 functional_tests/support/package2/test_pak/__init__.pyc
create mode 100644 functional_tests/support/package2/test_pak/test_mod.py
create mode 100644 functional_tests/support/package2/test_pak/test_mod.pyc
create mode 100644 functional_tests/support/package2/test_pak/test_sub/__init__.py
create mode 100644 functional_tests/support/package2/test_pak/test_sub/__init__.pyc
create mode 100644 functional_tests/support/package2/test_pak/test_sub/test_mod.py
create mode 100644 functional_tests/support/package2/test_pak/test_sub/test_mod.pyc
create mode 100644 functional_tests/support/package3/lib/a.py
create mode 100644 functional_tests/support/package3/lib/a.pyc
create mode 100644 functional_tests/support/package3/src/b.py
create mode 100644 functional_tests/support/package3/src/b.pyc
create mode 100644 functional_tests/support/package3/tests/test_a.py
create mode 100644 functional_tests/support/package3/tests/test_a.pyc
create mode 100644 functional_tests/support/package3/tests/test_b.py
create mode 100644 functional_tests/support/package3/tests/test_b.pyc
create mode 100644 functional_tests/support/pass/test.py
create mode 100644 functional_tests/support/pass/test.pyc
create mode 100644 functional_tests/support/test.cfg
create mode 100644 functional_tests/support/test_buggy_generators.py
create mode 100644 functional_tests/support/test_buggy_generators.pyc
create mode 100644 functional_tests/support/todo/test_with_todo.py
create mode 100644 functional_tests/support/todo/test_with_todo.pyc
create mode 100644 functional_tests/support/todo/todoplug.py
create mode 100644 functional_tests/support/todo/todoplug.pyc
create mode 100644 functional_tests/support/twist/test_twisted.py
create mode 100644 functional_tests/support/twist/test_twisted.pyc
create mode 100644 functional_tests/support/xunit.xml
create mode 100644 functional_tests/support/xunit/test_xunit_as_suite.py
create mode 100644 functional_tests/support/xunit/test_xunit_as_suite.pyc
create mode 100644 functional_tests/test_attribute_plugin.py
create mode 100644 functional_tests/test_attribute_plugin.pyc
create mode 100644 functional_tests/test_buggy_generators.py
create mode 100644 functional_tests/test_buggy_generators.pyc
create mode 100644 functional_tests/test_cases.py
create mode 100644 functional_tests/test_cases.pyc
create mode 100644 functional_tests/test_collector.py
create mode 100644 functional_tests/test_collector.pyc
create mode 100644 functional_tests/test_commands.py
create mode 100644 functional_tests/test_commands.pyc
create mode 100644 functional_tests/test_config_files.py
create mode 100644 functional_tests/test_config_files.pyc
create mode 100644 functional_tests/test_coverage_plugin.py
create mode 100644 functional_tests/test_coverage_plugin.pyc
create mode 100644 functional_tests/test_defaultpluginmanager.py
create mode 100644 functional_tests/test_defaultpluginmanager.pyc
create mode 100644 functional_tests/test_doctest_plugin.py
create mode 100644 functional_tests/test_doctest_plugin.pyc
create mode 100644 functional_tests/test_entrypoints.py
create mode 100644 functional_tests/test_entrypoints.pyc
create mode 100644 functional_tests/test_failuredetail_plugin.py
create mode 100644 functional_tests/test_failuredetail_plugin.pyc
create mode 100644 functional_tests/test_generator_fixtures.py
create mode 100644 functional_tests/test_generator_fixtures.pyc
create mode 100644 functional_tests/test_id_plugin.py
create mode 100644 functional_tests/test_id_plugin.pyc
create mode 100644 functional_tests/test_importer.py
create mode 100644 functional_tests/test_importer.pyc
create mode 100644 functional_tests/test_isolate_plugin.py
create mode 100644 functional_tests/test_isolate_plugin.pyc
create mode 100644 functional_tests/test_issue120/support/some_test.py
create mode 100644 functional_tests/test_issue120/support/some_test.pyc
create mode 100644 functional_tests/test_issue120/test_named_test_with_doctest.rst
create mode 100644 functional_tests/test_issue_072.py
create mode 100644 functional_tests/test_issue_072.pyc
create mode 100644 functional_tests/test_issue_082.py
create mode 100644 functional_tests/test_issue_082.pyc
create mode 100644 functional_tests/test_issue_408.py
create mode 100644 functional_tests/test_issue_408.pyc
create mode 100644 functional_tests/test_load_tests_from_test_case.py
create mode 100644 functional_tests/test_load_tests_from_test_case.pyc
create mode 100644 functional_tests/test_loader.py
create mode 100644 functional_tests/test_loader.pyc
create mode 100644 functional_tests/test_multiprocessing/__init__.py
create mode 100644 functional_tests/test_multiprocessing/__init__.pyc
create mode 100644 functional_tests/test_multiprocessing/support/class.py
create mode 100644 functional_tests/test_multiprocessing/support/class.pyc
create mode 100644 functional_tests/test_multiprocessing/support/concurrent_shared/__init__.py
create mode 100644 functional_tests/test_multiprocessing/support/concurrent_shared/__init__.pyc
create mode 100644 functional_tests/test_multiprocessing/support/concurrent_shared/test.py
create mode 100644 functional_tests/test_multiprocessing/support/concurrent_shared/test.pyc
create mode 100644 functional_tests/test_multiprocessing/support/fake_nosetest.py
create mode 100644 functional_tests/test_multiprocessing/support/keyboardinterrupt.py
create mode 100644 functional_tests/test_multiprocessing/support/keyboardinterrupt.pyc
create mode 100644 functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.py
create mode 100644 functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.pyc
create mode 100644 functional_tests/test_multiprocessing/support/nameerror.py
create mode 100644 functional_tests/test_multiprocessing/support/nameerror.pyc
create mode 100644 functional_tests/test_multiprocessing/support/timeout.py
create mode 100644 functional_tests/test_multiprocessing/support/timeout.pyc
create mode 100644 functional_tests/test_multiprocessing/test_class.py
create mode 100644 functional_tests/test_multiprocessing/test_class.pyc
create mode 100644 functional_tests/test_multiprocessing/test_concurrent_shared.py
create mode 100644 functional_tests/test_multiprocessing/test_concurrent_shared.pyc
create mode 100644 functional_tests/test_multiprocessing/test_keyboardinterrupt.py
create mode 100644 functional_tests/test_multiprocessing/test_keyboardinterrupt.pyc
create mode 100644 functional_tests/test_multiprocessing/test_nameerror.py
create mode 100644 functional_tests/test_multiprocessing/test_nameerror.pyc
create mode 100644 functional_tests/test_multiprocessing/test_process_timeout.py
create mode 100644 functional_tests/test_multiprocessing/test_process_timeout.pyc
create mode 100644 functional_tests/test_namespace_pkg.py
create mode 100644 functional_tests/test_namespace_pkg.pyc
create mode 100644 functional_tests/test_plugin_api.py
create mode 100644 functional_tests/test_plugin_api.pyc
create mode 100644 functional_tests/test_plugins.py
create mode 100644 functional_tests/test_plugins.pyc
create mode 100644 functional_tests/test_plugintest.py
create mode 100644 functional_tests/test_plugintest.pyc
create mode 100644 functional_tests/test_program.py
create mode 100644 functional_tests/test_program.pyc
create mode 100644 functional_tests/test_result.py
create mode 100644 functional_tests/test_result.pyc
create mode 100644 functional_tests/test_selector.py
create mode 100644 functional_tests/test_selector.pyc
create mode 100644 functional_tests/test_skip_pdb_interaction.py
create mode 100644 functional_tests/test_skip_pdb_interaction.pyc
create mode 100644 functional_tests/test_success.py
create mode 100644 functional_tests/test_success.pyc
create mode 100644 functional_tests/test_suite.py
create mode 100644 functional_tests/test_suite.pyc
create mode 100644 functional_tests/test_withid_failures.rst
create mode 100644 functional_tests/test_xunit.py
create mode 100644 functional_tests/test_xunit.pyc
create mode 100755 install-rpm.sh
create mode 100644 lgpl.txt
create mode 100644 nose.egg-info/PKG-INFO
create mode 100644 nose.egg-info/SOURCES.txt
create mode 100644 nose.egg-info/dependency_links.txt
create mode 100644 nose.egg-info/entry_points.txt
create mode 100644 nose.egg-info/not-zip-safe
create mode 100644 nose.egg-info/top_level.txt
create mode 100644 nose/__init__.py
create mode 100644 nose/case.py
create mode 100644 nose/commands.py
create mode 100644 nose/config.py
create mode 100644 nose/core.py
create mode 100644 nose/exc.py
create mode 100644 nose/ext/__init__.py
create mode 100644 nose/ext/dtcompat.py
create mode 100644 nose/failure.py
create mode 100644 nose/importer.py
create mode 100644 nose/inspector.py
create mode 100644 nose/loader.py
create mode 100644 nose/plugins/__init__.py
create mode 100644 nose/plugins/allmodules.py
create mode 100644 nose/plugins/attrib.py
create mode 100644 nose/plugins/base.py
create mode 100644 nose/plugins/builtin.py
create mode 100644 nose/plugins/capture.py
create mode 100644 nose/plugins/collect.py
create mode 100644 nose/plugins/cover.py
create mode 100644 nose/plugins/debug.py
create mode 100644 nose/plugins/deprecated.py
create mode 100644 nose/plugins/doctests.py
create mode 100644 nose/plugins/errorclass.py
create mode 100644 nose/plugins/failuredetail.py
create mode 100644 nose/plugins/isolate.py
create mode 100644 nose/plugins/logcapture.py
create mode 100644 nose/plugins/manager.py
create mode 100644 nose/plugins/multiprocess.py
create mode 100644 nose/plugins/plugintest.py
create mode 100644 nose/plugins/prof.py
create mode 100644 nose/plugins/skip.py
create mode 100644 nose/plugins/testid.py
create mode 100644 nose/plugins/xunit.py
create mode 100644 nose/proxy.py
create mode 100644 nose/pyversion.py
create mode 100644 nose/result.py
create mode 100644 nose/selector.py
create mode 100644 nose/sphinx/__init__.py
create mode 100644 nose/sphinx/pluginopts.py
create mode 100644 nose/suite.py
create mode 100644 nose/tools/__init__.py
create mode 100644 nose/tools/nontrivial.py
create mode 100644 nose/tools/trivial.py
create mode 100644 nose/twistedtools.py
create mode 100644 nose/usage.txt
create mode 100644 nose/util.py
create mode 100644 nosetests.1
create mode 100644 patch.py
create mode 100755 selftest.py
create mode 100644 setup.cfg
create mode 100644 setup.py
create mode 100644 setup3lib.py
create mode 100644 unit_tests/helpers.py
create mode 100644 unit_tests/helpers.pyc
create mode 100644 unit_tests/mock.py
create mode 100644 unit_tests/mock.pyc
create mode 100644 unit_tests/support/bug101/tests.py
create mode 100644 unit_tests/support/bug105/tests.py
create mode 100644 unit_tests/support/bug105/tests.pyc
create mode 100644 unit_tests/support/config_defaults/a.cfg
create mode 100644 unit_tests/support/config_defaults/b.cfg
create mode 100644 unit_tests/support/config_defaults/invalid.cfg
create mode 100644 unit_tests/support/config_defaults/invalid_value.cfg
create mode 100644 unit_tests/support/doctest/err_doctests.py
create mode 100644 unit_tests/support/doctest/err_doctests.pyc
create mode 100644 unit_tests/support/doctest/no_doctests.py
create mode 100644 unit_tests/support/doctest/no_doctests.pyc
create mode 100644 unit_tests/support/foo/__init__.py
create mode 100644 unit_tests/support/foo/__init__.pyc
create mode 100644 unit_tests/support/foo/bar/__init__.py
create mode 100644 unit_tests/support/foo/bar/__init__.pyc
create mode 100644 unit_tests/support/foo/bar/buz.py
create mode 100644 unit_tests/support/foo/bar/buz.pyc
create mode 100644 unit_tests/support/foo/doctests.txt
create mode 100644 unit_tests/support/foo/test_foo.py
create mode 100644 unit_tests/support/foo/tests/dir_test_file.py
create mode 100644 unit_tests/support/issue006/tests.py
create mode 100644 unit_tests/support/issue006/tests.pyc
create mode 100644 unit_tests/support/issue065/tests.py
create mode 100644 unit_tests/support/issue065/tests.pyc
create mode 100644 unit_tests/support/issue270/__init__.py
create mode 100644 unit_tests/support/issue270/__init__.pyc
create mode 100644 unit_tests/support/issue270/foo_test.py
create mode 100644 unit_tests/support/issue270/foo_test.pyc
create mode 100644 unit_tests/support/other/file.txt
create mode 100644 unit_tests/support/pkgorg/lib/modernity.py
create mode 100644 unit_tests/support/pkgorg/tests/test_mod.py
create mode 100755 unit_tests/support/script.py
create mode 100644 unit_tests/support/test-dir/test.py
create mode 100644 unit_tests/support/test.py
create mode 100644 unit_tests/test_attribute_plugin.py
create mode 100644 unit_tests/test_attribute_plugin.pyc
create mode 100644 unit_tests/test_bug105.py
create mode 100644 unit_tests/test_bug105.pyc
create mode 100644 unit_tests/test_capture_plugin.py
create mode 100644 unit_tests/test_capture_plugin.pyc
create mode 100644 unit_tests/test_cases.py
create mode 100644 unit_tests/test_cases.pyc
create mode 100644 unit_tests/test_config.py
create mode 100644 unit_tests/test_config.pyc
create mode 100644 unit_tests/test_config_defaults.rst
create mode 100644 unit_tests/test_core.py
create mode 100644 unit_tests/test_core.pyc
create mode 100644 unit_tests/test_deprecated_plugin.py
create mode 100644 unit_tests/test_deprecated_plugin.pyc
create mode 100644 unit_tests/test_doctest_error_handling.py
create mode 100644 unit_tests/test_doctest_error_handling.pyc
create mode 100644 unit_tests/test_doctest_munging.rst
create mode 100644 unit_tests/test_id_plugin.py
create mode 100644 unit_tests/test_id_plugin.pyc
create mode 100644 unit_tests/test_importer.py
create mode 100644 unit_tests/test_importer.pyc
create mode 100644 unit_tests/test_inspector.py
create mode 100644 unit_tests/test_inspector.pyc
create mode 100644 unit_tests/test_isolation_plugin.py
create mode 100644 unit_tests/test_isolation_plugin.pyc
create mode 100644 unit_tests/test_issue155.rst
create mode 100644 unit_tests/test_issue270.rst
create mode 100644 unit_tests/test_issue270_fixtures.py
create mode 100644 unit_tests/test_issue270_fixtures.pyc
create mode 100644 unit_tests/test_issue_006.py
create mode 100644 unit_tests/test_issue_006.pyc
create mode 100644 unit_tests/test_issue_064.py
create mode 100644 unit_tests/test_issue_064.pyc
create mode 100644 unit_tests/test_issue_065.py
create mode 100644 unit_tests/test_issue_065.pyc
create mode 100644 unit_tests/test_issue_100.rst
create mode 100644 unit_tests/test_issue_100.rst.py3.patch
create mode 100644 unit_tests/test_issue_101.py
create mode 100644 unit_tests/test_issue_101.pyc
create mode 100644 unit_tests/test_issue_159.rst
create mode 100644 unit_tests/test_issue_227.py
create mode 100644 unit_tests/test_issue_227.pyc
create mode 100644 unit_tests/test_issue_230.py
create mode 100644 unit_tests/test_issue_230.pyc
create mode 100644 unit_tests/test_lazy_suite.py
create mode 100644 unit_tests/test_lazy_suite.pyc
create mode 100644 unit_tests/test_loader.py
create mode 100644 unit_tests/test_loader.pyc
create mode 100644 unit_tests/test_logcapture_plugin.py
create mode 100644 unit_tests/test_logcapture_plugin.pyc
create mode 100644 unit_tests/test_logging.py
create mode 100644 unit_tests/test_logging.pyc
create mode 100644 unit_tests/test_ls_tree.rst
create mode 100644 unit_tests/test_multiprocess.py
create mode 100644 unit_tests/test_multiprocess.pyc
create mode 100644 unit_tests/test_multiprocess_runner.py
create mode 100644 unit_tests/test_multiprocess_runner.pyc
create mode 100644 unit_tests/test_pdb_plugin.py
create mode 100644 unit_tests/test_pdb_plugin.pyc
create mode 100644 unit_tests/test_plugin.py
create mode 100644 unit_tests/test_plugin.pyc
create mode 100644 unit_tests/test_plugin_interfaces.py
create mode 100644 unit_tests/test_plugin_interfaces.pyc
create mode 100644 unit_tests/test_plugin_manager.py
create mode 100644 unit_tests/test_plugin_manager.pyc
create mode 100644 unit_tests/test_plugins.py
create mode 100644 unit_tests/test_plugins.pyc
create mode 100644 unit_tests/test_result_proxy.py
create mode 100644 unit_tests/test_result_proxy.pyc
create mode 100644 unit_tests/test_selector.py
create mode 100644 unit_tests/test_selector.pyc
create mode 100644 unit_tests/test_selector_plugins.py
create mode 100644 unit_tests/test_selector_plugins.pyc
create mode 100644 unit_tests/test_skip_plugin.py
create mode 100644 unit_tests/test_skip_plugin.pyc
create mode 100644 unit_tests/test_suite.py
create mode 100644 unit_tests/test_suite.pyc
create mode 100644 unit_tests/test_tools.py
create mode 100644 unit_tests/test_tools.pyc
create mode 100644 unit_tests/test_twisted.py
create mode 100644 unit_tests/test_twisted.pyc
create mode 100644 unit_tests/test_twisted_testcase.py
create mode 100644 unit_tests/test_twisted_testcase.pyc
create mode 100644 unit_tests/test_utils.py
create mode 100644 unit_tests/test_utils.pyc
create mode 100644 unit_tests/test_xunit.py
create mode 100644 unit_tests/test_xunit.pyc
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..b852772
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,25 @@
+Jason Pellerin
+Kumar McMillan
+Mika Eloranta
+Jay Parlar
+Scot Doyle
+James Casbon
+Antoine Pitrou
+John J Lee
+Allen Bierbaum
+Pam Zerbinos
+Augie Fackler
+Peter Fein
+Kevin Mitchell
+Alex Stewart
+Timothee Peignier
+Thomas Kluyver
+Heng Liu
+Rosen Diankov
+Buck Golemon
+Bobby Impollonia
+Takafumi Arakaki
+Peter Bengtsson
+Gary Donovan
+Brendan McCollam
+Erik Rose
diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644
index 0000000..b4584e6
--- /dev/null
+++ b/CHANGELOG
@@ -0,0 +1,678 @@
+1.2.1
+
+- Correct nose.__version__ (#549). Thanks to Chris Withers for the bug report.
+
+1.2.0
+
+- Fixed issue where plugins included with `addplugins` keyword could
+ be overridden by built-in plugins (or third-party plugins registered
+ with setuptools) of the same name (#466).
+ Patch by Brendan McCollam
+- Adds :option:`--cover-xml` and :option:`--cover-xml-file` (#311).
+ Patch by Timothée Peignier.
+- Adds support for :option:`--cover-branches` (related to #370).
+ Patch by Timothée Peignier.
+- Fixed Unicode issue on Python 3.1 with coverage (#442)
+- fixed class level fixture handling in multiprocessing plugin
+- Clue in the ``unittest`` module so it no longer prints traceback frames for
+ our clones of their simple assertion helpers (#453). Patch by Erik Rose.
+- Stop using the ``assert`` statement in ``ok_`` and ``eq_`` so they work under
+ ``python -O`` (#504). Patch by Erik Rose.
+- Add loglevel option to logcapture plugin (#493). Patch by Arach Tchoupani.
+- Add doctest options flag (#7 from google code tracker). Patch by Michael
+ Forbes.
+- Add support for using 2to3 with the nosetests setuptools command. Patch by
+ Andrey Golovizin.
+- Add --cover-min-percentage flag to force test runs without sufficient
+ coverage to fail (#540). Patch by Domen Kožar.
+- Add travis-ci configuraion (#545). Patch by Domen Kožar.
+- Call reactor.stop from twisted thread (#301). Patch by Adi Roiban.
+
+
+1.1.2
+
+- Fixed regression where the .coverage file was not saved (#439).
+ Patch by Timothée Peignier.
+
+1.1.1
+
+- Fixed missing nose.sphinx module in source distribution (#436).
+
+1.1.0
+
+- Revised multiprocessing implementation so that it works for test generators
+ (#399). Thanks to Rosen Diankov for the patch.
+- More fixes to multiprocessing implemented by Buck Golemon and Gary Donovan
+ (also part of #399).
+- Lots of improvements to the attrib plugin by Bobby Impollonia (#412, #411,
+ #324 and #381)
+- Code coverage plugin now uses native HTML generation when coverage 3 is
+ installed (#264). Thanks to Timothée Peignier for the patch.
+- Xunit plugin now shows test run time in fractions of a second (#317)
+- @attr (from nose.plugins.attrib) can now be used as a class decorator (#292)
+- Fixes Xunit plugin to handle non-UTF8 characters (#395)
+- Fixes Xunit plugin for reporting generator tests (#369)
+- Fixed problems with SkipTest in Python 3.2 (#389)
+- Fixed bug in doctest plugin under python 3. Thanks to Thomas Kluyver
+ for the patch. (#391)
+- Fixes mishandling of custom exceptions during failures (#405)
+- Fixed subtle bug in :option:`--first-package-wins` that made it
+ unpredictable (#293)
+- Fixes case where teardown_class() was called more than once (#408). Thanks
+ to Heng Liu for the patch.
+- Fixes coverage module names -- 'cal' used to also match calendar which was a
+ bug (#433)
+- Fixes capture plugin when exception message contains non-ascii chars (#402)
+- Fixed bug in tests for twisted tools. Thanks to Thomas Kluyver
+ for the patch.
+- Makes :option:`--plugins` more succinct when there are no options (#235)
+
+1.0.0
+
+- Made nose compatible with python 3. **Huge** thanks to Alex "foogod"
+ Stewart!
+
+0.11.4
+
+- Made nose compatible with Python 2.7.
+
+0.11.3
+
+- Fixed default plugin manager's use of plugin overriding. Thanks to
+ rob.daylife for the bug report and patch. (#323).
+
+0.11.2
+
+- Changed plugin loading so that external plugins loaded via extension
+ points can override builtin plugins with the same name.
+- Updated multiprocess plugin and nose's packaging to allow multiprocess
+ plugin to work on Windows (#265).
+- Fixed bug in xunit plugin's interaction with suites and errors in
+ module-level setup. Thanks to Mark McCague for the bug report (#279).
+- Fixed bug in nose.loader.TestLoader that allowed Test classes that raise
+ exceptions in __init__ to crash the test run (#269).
+- Fixed bugs in nose's test suite that caused spurious failures on Windows.
+- Fixed bug in twisted tools: delayed calls were not shut down on
+ reactor stop. Thanks to abbeyj for the patch (#278).
+- Fixed bug where root log handlers were not cleared. For example, this was
+ emitting unwanted messages when testing Google App Engine websites.
+- Fixed bug in test names output by xunit plugin. Thanks to Philip
+ Jenvey for the bug report and patch (#280).
+- Fixed bug in profile plugin that caused stats to fail to print under Python
+ 2.5 and later. Thanks to djs at n-cube dot org for the bug report (#285).
+- Improved logcapture filtering, with default setting to filter out log
+ messages from nose itself. Thanks to gfxmonk for the patch (#277).
+- The xunit plugin now tags skipped tests with a testcase tag, and
+ prevents the XML from containing invalid control characters.
+- Updated nose to be compatible with python 2.7 (#305).
+- Updated loading of usage document to allow nose to run from within
+ an egg archive (#288).
+- Fixed IronPython checks to make nose compatible with more versions
+ of IronPython. Thanks to Kevin Mitchell for the patch (#316).
+
+0.11.1
+
+- Fixed bug in xunit plugin xml escaping. Thanks to Nat Williams for the bug
+ report (#266).
+- Fixed bug in xunit plugin that could cause test run to crash after certain
+ types of errors or actions by other plugins.
+- Fixed bug in testid plugin that could cause test run to crash after certain
+ types of errors or actions by other plugins.
+- Fixed bug in collect only plugin that caused it to fail when collecting from
+ test generators.
+- Fixed some broken html in docs.
+
+0.11
+
+- **All new documentation!** nose's documentation is now generated by
+ Sphinx. And thanks to Pam Zerbinos, it is much better organized and easier
+ to use and read.
+- Two new core commandline options can help with testing namespace
+ packages. :option:`--first-package-wins` is useful when you want to test one
+ part of a namespace package that uses another part; in previous versions of
+ nose, the other part of the namespace package would be evicted from
+ sys.modules when the 2nd loaded. :option:`--traverse-namespace` is useful if
+ you want nose to discover tests across entries in a package's
+ __path__. (This was formerly the default behavior).
+- To make it easier to use custom plugins without needing setuptools,
+ :func:`nose.core.main` and :func:`nose.core.run` now support an
+ :doc:`addplugins ` keyword
+ argument that takes a list of additional plugins to make available. **Note**
+ that adding a plugin to this list **does not** activate or enable the
+ plugin, only makes it available to be enabled via command-line or
+ config file settings.
+- Thanks to Kevin Mitchell, nose is now more compatible with
+ IronPython. IronPython is still not fully supported, but it should work. If
+ you'd like to improve nose's support for IronPython further, please join the
+ nose developer's list and volunteer to become the IronPython maintainer for
+ nose!
+- Added multiprocess plugin that allows tests to be run in parallel
+ across multiple processes.
+- Added logcapture plugin that captures logging messages and prints them with
+ failing tests. Thanks to Max Ischenko for the implementation.
+- Added optional HTML coverage reports to coverage plugin. Thanks to Augie
+ Fackler for the patch.
+- Added plugin that enables collection of tests in all modules. Thanks to
+ Peter Fein for the patch (#137).
+- Added --failed option to testid plugin. When this option is in effect, if
+ any tests failed in the previous test run (so long as testid was active for
+ that test run) only the failed tests will run.
+- Made it possible to 'yield test' in addition to 'yield test,' from test
+ generators. Thanks to Chad Whitacre for the patch (#230).
+- Fixed bug that caused traceback inspector to fail when source code file
+ could not be found. Thanks to Philip Jenvey for the bug report and patch
+ (#236).
+- Fixed some issues limiting compatibility with IronPython. Thanks to Kevin
+ Mitchell for the patch.
+- Added support for module and test case fixtures in doctest files (#60).
+- Added --traverse-namespace commandline option that restores old default
+ behavior of following all package __path__ entries when loading tests from
+ packages. Thanks to Philip Jenvey for the patch (#167).
+- Added --first-package-wins commandline option to better support testing
+ parts of namespace packages. Thanks to Jason Coombs for the bug report
+ (#197).
+- Added versioned nosetests scripts (#123).
+- Fixed bug that would cause context teardown to fail to run in some
+ cases. Thanks to John Shaw for the bug report and patch (#234).
+- Enabled doctest plugin to use variable other than "_" as the default result
+ variable. Thanks to Matt Good for the patch (#163).
+- Fixed bug that would cause unicode output to crash output capture. Thanks to
+ schickb for the bug report (#227).
+- Added setUp and tearDown as valid names for module-level fixtures. Thanks to
+ AgilityNerd for the patch (#211).
+- Fixed bug in list of valid names for package-level fixtures. Thanks to
+ Philip Jenvey for the patch (#237).
+- Updated man page generation using hacked up manpage writer from
+ docutils sandbox. Thanks grubert@users.sourceforge.net for the
+ original module.
+
+0.10.4
+
+- nose is now compatible with python 2.6.
+
+0.10.3
+
+- Fixed bug in nosetests setup command that caused an exception to be raised
+ if run with options. Thanks to Philip Jenvey for the bug report (#191).
+- Raised score of coverage plugin to 200, so that it will execute before
+ default-score plugins, and so be able to catch more import-time code. Thanks
+ to Ned Batchelder for the bug report and patch (#190).
+
+0.10.2
+
+- nose now runs under jython (jython svn trunk only at this time). Thanks to
+ Philip Jenvey, Pam Zerbinos and the other pycon sprinters (#160).
+- Fixed bugs in loader, default plugin manager, and other modules that
+ caused plugin exceptions to be swallowed (#152, #155). Thanks to John J
+ Lee for the bug report and patch.
+- Added selftest.py script, used to test a non-installed distribution of
+ nose (#49). Thanks to Antoine Pitrou and John J Lee for the bug report and
+ patches.
+- Fixed bug in nose.importer that caused errors with namespace
+ packages. Thanks to Philip Jenvey for the bug report and patch (#164).
+- Fixed bug in nose.tools.with_setup that prevented use of multiple
+ @with_setup decorators. Thanks to tlesher for the bug report (#151).
+- Fixed bugs in handling of context fixtures for tests imported into a
+ package. Thanks to Gary Bernhardt for the bug report (#145).
+- Fixed bugs in handling of config files and config file options for plugins
+ excluded by a RestrictedPluginManager. Thanks to John J Lee and Philip
+ Jenvey for the bug reports and patches (#158, #166).
+- Updated ErrorClass exception reporting to be shorter and more clear. Thanks
+ to John J Lee for the patch (#142).
+- Allowed plugins to load tests from modules starting with '_'. Thanks to John
+ J Lee for the patch (#82).
+- Updated documentation about building as rpm (#127).
+- Updated config to make including executable files the default on
+ IronPython as well as on Windows. Thanks to sanxiyn for the bug
+ report and patch (#183).
+- Fixed a python 2.3 incompatibility in errorclass_failure.rst
+ (#173). Thanks to Philip Jenvey for the bug report and patch.
+- Classes with metaclasses can now be collected as tests (#153).
+- Made sure the document tree in the selector plugin test is accurate
+ and tested (#144). Thanks to John J Lee for the bug report and
+ patch.
+- Fixed stack level used when dropping into pdb in a doctest
+ (#154). Thanks to John J Lee for the bug report and patch.
+- Fixed bug in ErrorClassPlugin that made some missing keyword
+ argument errors obscure (#159). Thanks to Philip Jenvey for the bug
+ report and patch.
+
+0.10.1
+
+- Fixed bug in capture plugin that caused it to record captured output
+ on the test in the wrong attribute (#113).
+- Fixed bug in result proxy that caused tests to fail if they accessed
+ certain result attibutes directly (#114). Thanks to Neilen Marais
+ for the bug report.
+- Fixed bug in capture plugin that caused other error formatters
+ changes to be lost if no output was captured (#124). Thanks to
+ someone at ilorentz.org for the bug report.
+- Fixed several bugs in the nosetests setup command that made some
+ options unusable and the command itself unusable when no options
+ were set (#125, #126, #128). Thanks to Alain Poirier for the bug
+ reports.
+- Fixed bug in handling of string errors (#130). Thanks to schl... at
+ uni-oldenburg.de for the bug report.
+- Fixed bug in coverage plugin option handling that prevented
+ --cover-package=mod1,mod2 from working (#117). Thanks to Allen
+ Bierbaum for the patch.
+- Fixed bug in profiler plugin that prevented output from being
+ produced when output capture was enabled on python 2.5
+ (#129). Thanks to James Casbon for the patch.
+- Fixed bug in adapting 0.9 plugins to 0.10 (#119 part one). Thanks to
+ John J Lee for the bug report and tests.
+- Fixed bug in handling of argv in config and plugin test utilities
+ (#119 part two). Thanks to John J Lee for the bug report and patch.
+- Fixed bug where Failure cases due to invalid test name
+ specifications were passed to plugins makeTest (#120). Thanks to
+ John J Lee for the bug report and patch.
+- Fixed bugs in doc css that mangled display in small windows. Thanks
+ to Ben Hoyt for the bug report and Michal Kwiatkowski for the fix.
+- Made it possible to pass a list or comma-separated string as
+ defaultTest to main(). Thanks to Allen Bierbaum for the suggestion
+ and patch.
+- Fixed a bug in nose.selector and nose.util.getpackage that caused
+ directories with names that are not legal python identifiers to be
+ collected as packages (#143). Thanks to John J Lee for the bug
+ report.
+
+0.10.0
+
+- Fixed bug that broke plugins with names containing underscores or
+ hyphens. Thanks to John J Lee for the bug report and patch (Issue
+ #81).
+- Fixed typo in nose.__all__. Thanks to John J Lee for the bug report.
+- Fixed handling of test descriptions that are multiline
+ docstrings. Thanks to James Casbon for the patch (Issue #50).
+- Improved documentation of doctest plugin to make it clear that
+ entities may have doctests, or themselves be tests, but not
+ both. Thanks to John J Lee for the bug report and patch (Issue #84).
+- Made __file__ available in non-python-module doctests.
+- Fixed bug that made it impossible for plugins to exclude package
+ directories from test discovery (Issue #89). Thanks to John J Lee
+ for the bug report and patch.
+- Fixed bug that swallowed TypeError and AttributeError exceptions
+ raised in some plugin calls (Issue #95). Thanks to John J Lee for
+ the bug report.
+- Fixed inconsistencies in many interfaces and docs. Thanks to John J
+ Lee for many bug reports.
+- Fixed bugs in rpm generation (Issue #96). Thanks to Mike Verdone for
+ the bug report and http://bugs.python.org/issue644744 for the fix.
+- Fixed inconsisent use of os.environ in plugin testing
+ utilities. Thanks to John J Lee for the bug report and patch (Issue
+ #97).
+- Fixed bug in test_address that prevented use of nose.case.Test in
+ doctests (Issue #100). Thanks to John J Lee for the bug report.
+- Fixed bug in error class plugin that caused string exceptions to be
+ masked (#Issue 101). Thanks to depaula for the bug report.
+- Fixed bugs in tests and the profiler plugin when running under
+ Windows (Issue #103). Thanks to Sidnei Da Silva for the bug report.
+- Fixed bugs in plugin calls that caused exception swallowing (Issue
+ #107). Thanks to John L Lee for the bug report and patch.
+- Added more plugin example doctests. Thanks to Kumar McMillan and
+ John L Lee for patches and lots of help.
+- Changed default location of id file for TestId plugin from ~/.noseids to
+ .noseids in the configured working directory.
+
+0.10.0b1
+
+- Added support for a description attribute on tests in function and
+ method test cases. Most useful for generators: set the description
+ attribute on the yielded function.
+- Fixed incorrect signature of addSuccess() method in
+ IPluginInterface. Thanks to nosexunit for the bug report. (Issue
+ #68).
+- Fixed isclass() function in nose.util so that it will not raise an
+ exception when examining instances that have no accessible __bases__
+ attribute. (Issue #65).
+- Fixed passing of tests to result; the test itself and not the
+ wrapper was being passed, resulting in test description plugin hooks
+ not being called. (Issue #71).
+- Fixed bugs in FailureDetail and Capture plugins, and plugin manager
+ and proxy uses of chainable plugin calls. Thanks to Ian Bicking for
+ the bug report (Issue #72).
+- Improved documentation.
+
+0.10.0a2
+
+- Changed entry point name to nose.plugins.0.10 -- dashes and other
+ non-word characters besides . are not allowed in entry point names.
+ (Issue #67)
+- Fixed loading of plugins from that entry point.
+- Fixed backwards-compatibility issue in nose.util (is_generator was
+ renamed isgenerator). (Issue #64)
+- Fixed bug in --logging-config option. Thanks to anton_kr... at yahoo
+ com for the bug report. (Issue #62)
+- Fixed bug in handling of --where argument: first --where was not
+ passed to loader as workingDir. Thanks to nosexunit for the bug
+ report. (Issue #63).
+
+0.10.0a1
+
+- Rewrote test loader to be more drop-in compatible with
+ unittest.TestLoader and to support a more user-friendly command
+ line.
+- Rewrote test runner and result classes to reduce duplication of effort.
+- Revised configuration system to be less convoluted.
+- Added nose.case.TestCase as universal wrapper for all
+ testcases. Plugins always see instances of this class.
+- Added a management layer to the plugin system, allowing for easy use
+ of different plugin loading schemes. The default manager loads
+ builtin plugins, 0.10 plugins under the setuptools entrypoint
+ nose.plugins.0-10 and provides limited support for legacy plugins
+ loaded under the entrypoint nose.plugins.
+- Added plugin hooks in all phases of discovery, running and description.
+- Converted several formely core features to plugins: output capture,
+ assert introspection, pdb, and skipped and deprecated test support.
+- Added id plugin that allows for easier specification of tests on the
+ command line.
+- Added ErrorClassPlugin base class to allow for easier authoring of
+ plugins that handle errors, like the builtin skipped and deprecated
+ test plugins.
+- Added support for loading doctests from non-module files for all
+ supported python versions.
+- Added score property to plugins to allow plugins to execute in a
+ defined order (higher score execute first).
+- Expanded nose's own test suite to include a variety of functional tests.
+- Fixed many bugs.
+
+0.9.3
+
+- Added support for user configuration files. Thanks to Antoine Pitrou for the
+ patch.
+- Fixed bug that caused profiler plugin to leak 0-byte temp files. Thanks to
+ Antoine Pitrou for the patch.
+- Made usage of temp files in profiler plugin more sensible. Thanks to Michael
+ Sclenker for the bug report.
+- Fixed bug that stopped loading of twisted TestCase tests. Thanks to Kumar
+ McMillan for the bug report.
+- Corrected man page location. Thanks to luke macken for the bug report and
+ patch.
+- Added with_setup to nose.tools.__all__. Thanks to Allen Bierbaum for the bug
+ report.
+- Altered plugin loading so that builtin plugins can be loaded without
+ setuptools. Thanks to Allen Bierbaum for the suggestion.
+- Fixed a bug in the doctests plugin that caused an error when multiple
+ exclude arguments were specified. Thanks to mbeachy for the bug report and
+ patch.
+
+0.9.2
+
+- Added nosetests setuptools command. Now you can run python setup.py
+ nosetests and have access to all nose features and plugins. Thanks to James
+ Casbon for the patch.
+- Added make_decorator function to nose.tools. Used to construct decorator
+ functions that are well-behaved and preserve as much of the original
+ function's metadata as possible. Thanks to Antoine Pitrou for the patch.
+- Added nose.twistedtools, contributed by Antoine Pitrou. This module adds
+ @deferred decorator that makes it simple to write deferred tests, with or
+ without timeouts.
+- Added monkeypatch to doctests that keeps doctest from stepping on coverage
+ when the two plugins are used together. Thanks to David Avraamides for the
+ bug report.
+- Added isolation plugin. Use this plugin to automatically restore sys.modules
+ after each test module or package. Thanks to Michal Kwiatkowski for the
+ feature request.
+- Fixed bug where -vvvv turned off verbose logging instead of making it even
+ more verbose. Thanks to Ian Bicking for the bug report.
+- Fixed bug where assert inspection would fail when the trailing """ of a
+ docstring was one of the inspected lines. Thanks to cito at online dot de
+ for the bug report.
+- Updated attrib plugin to allow selection of test methods by attributes of
+ the test case class. Thanks to Jason Hildebrand for the patch.
+- Improved compatibility with python 2.2. Thanks to Chad Whitacre for the
+ patch.
+- Fixed bug in handling of options from setup.cfg. Thanks to Kumar McMillan for
+ the patch.
+- Fixed bug in generator methods, where a generator method using an inline
+ funciton would result in an AttributeError. Thanks to Antoine Pitrou for the
+ bug report.
+- Updated coverage plugin to ignore lines tagged with #pragma: no cover,
+ matching the behavior of coverage.py on the command line. Thanks to Bill
+ Zingler for the bug report.
+- Added a man page for nosetests. Thanks to Gustavo Noronha Silva for the
+ request and providing an example.
+
+0.9.1
+
+- New function nose.runmodule() finds and runs tests only in a
+ single module, which defaults to __main__ (like unittest.main() or
+ doctest.runmodule()). Thanks Greg Wilson for the suggestion.
+- Multiple -w (--where) arguments can now be used in one command line,
+ to find and run tests in multiple locations. Thanks Titus Brown for
+ the suggestion.
+- Multiple --include and --exclude arguments are now accepted in one command
+ line. Thanks Michal Kwiatkowski for the feature request.
+- Coverage will now include modules not imported by any test when
+ using the new --cover-inclusive switch. Thanks James Casbon for the
+ patch.
+- module:TestClass test selections now properly select all tests in the test
+ class.
+- startTest and stopTest are now called in plugins at the beginning and end of
+ test suites, including test modules, as well as individual tests. Thanks
+ Michal Kwiatkowski for the suggestion.
+- Fix bug in test selection when run as ``python setup.py test``: 'test' was
+ passing through and being used as the test name selection. Thanks Kumar
+ McMillan for the bug report.
+- Fix bug in handling of -x/--stop option where the test run would stop on
+ skipped or deprecated tests. Thanks Kumar McMillan for the bug report.
+- Fix bug in loading tests from projects with layouts that place modules in
+ /lib or /src dirs and tests in a parallel /tests dir.
+- Fix bug in python version detection. Thanks Kevin Dangoor for the bug report
+ and fix.
+- Fix log message in selector that could raise IndexError. Thanks Kumar
+ McMillan for the bug report and patch.
+- Fix bug in handling doctest extension arguments specified in environment and
+ on command line. Thanks Ian Bicking for the bug report.
+- Fix bug in running fixtures (setup/teardown) that are not functions, and
+ report a better error message when a fixture is not callable. Thanks Ian
+ Bicking for the bug report.
+
+0.9.0
+
+- More unit tests and better test coverage. Numerous bugfixes deriving from
+ same.
+- Make --exe option do what it says, and turn it on by default on
+ Windows. Add --noexe option so windows users can turn if off.Thanks
+ richard at artsalliancemedia dot com for the bug reports.
+- Handle a working directory that happens to be in the middle of a package
+ more gracefully. Thanks Max Ischenko for the bug report and test case.
+- Fix bugs in test name comparison when a test module is specified whose name
+ overlaps that of a non-test module. Thanks Max Ischenko for the bug report
+ and test case.
+- Fix warning spam when a non-existent test file is requested on the command
+ line. Thanks Max Ischenko for the bug report.
+
+0.9.0b2
+
+- Allow --debug to set any logger to DEBUG. Thanks to casbon at gmail dot com
+ for the patch.
+- Fix doctest help, which was missing notes about the environment variables
+ that it accepts. Thanks to Kumar McMillan for the patch.
+- Restore sys.stdout after run() in nose.core. Thanks to Titus Brown for the
+ bug report.
+- Correct handling of trailing comma in attrib plugin args. Thanks Titus Brown
+ for the patch.
+
+0.9.0b1
+
+- Fix bug in handling of OR conditions in attrib plugin. Thanks to Titus
+ Brown for the bug report.
+- Fix bug in nose.importer that would cause an attribute error when a local
+ module shadowed a builtin, or other object in sys.modules, without a
+ __file__ attribute. Thanks to casbon at gmail dot com for the bug report.
+- Fix bug in nose.tools decorators that would cause decorated tests to appear
+ with incorrect names in result output.
+
+0.9.0a2
+
+- In TestLoader, use inspect's isfunction() and ismethod() to filter functions
+ and methods, instead of callable(). Thanks to Kumar McMillan for reporting
+ the bug.
+- Fix doctest plugin: return an empty iterable when no tests are found in a
+ directory instead of None. Thanks to Kumar McMillan for the bug report and
+ patch.
+- Ignore executable python modules, unless run with --exe file. This is a
+ partial defense against nose causing trouble by loading python modules that
+ are not import-safe. The full defense: don't write modules that aren't
+ import safe!
+- Catch and warn about errors on plugin load instead of dying.
+- Renamed builtin profile module from nose.plugins.profile to
+ nose.plugins.prof to avoid shadowing stdlib profile.py module.
+
+0.9.0a1
+
+- Add support for plugins, with hooks for selecting, loading and reporting on
+ tests. Doctest and coverage are now plugins.
+- Add builtin plugins for profiling with hotshot, selecting tests by
+ attribute (contributed by Mika Eloranta), and warning of missed tests
+ specified on command line.
+- Change command line test selection syntax to match unittest. Thanks to Titus
+ Brown for the suggestion.
+- Option to drop into pdb on error or failure.
+- Option to stop running on first error or failure. Thanks to Kevin Dangoor
+ for the suggestion.
+- Support for doctests in files other than python modules (python 2.4 only)
+- Reimplement base test selection as single self-contained class.
+- Reimplement test loading as unittest-compatible TestLoader class.
+- Remove all monkeypatching.
+- Reimplement output capture and assert introspection support in
+ unittest-compatible Result class.
+- Better support for multiline constructions in assert introspection.
+- More context output with assert introspections.
+- Refactor setuptools test command support to use proxied result, which
+ enables output capture and assert introspection support without
+ monkeypatching. Thanks to Philip J. Eby for the suggestion and skeleton
+ implementation.
+- Add support for generators in test classes. Thanks to Jay Parlar for the
+ suggestion and patch.
+- Add nose.tools package with some helpful test-composition functions and
+ decorators, including @raises, contributed by Scot Doyle.
+- Reimplement nose.main (TestProgram) to have unittest-compatible signature.
+- All-new import path handling. You can even turn it off! (If you don't,
+ nose will ensure that all directories from which it imports anything are on
+ sys.path before the import.)
+- Logging package used for verbose logging.
+- Support for skipped and deprecated tests.
+- Configuration is no longer global.
+
+0.8.7
+
+- Add support for py.test-style test generators. Thanks to Jay Parlar for
+ the suggestion.
+- Fix bug in doctest discovery. Thanks to Richard Cooper for the bug report.
+- Fix bug in output capture being appended to later exceptions. Thanks to
+ Titus Brown for the patch that uncovered the bug.
+- Fix bug(?) in Exception patch that caused masked hasattr/__getattr__ loops
+ to either become actual infinite loops, or at least take so long to finally
+ error out that they might as well be infinite.
+- Add -m option to restrict test running to only tests in a particular package
+ or module. Like the -f option, -m does not restrict test *loading*, only
+ test *execution*.
+- When loading and running a test module, ensure that the module's path is in
+ sys.path for the duration of the run, not just while importing the module.
+- Add id() method to all callable test classes, for greater unittest
+ compatibility.
+
+0.8.6
+
+- Fix bug with coverage output when sys.modules contains entries without
+ __file__ attributes
+- Added -p (--cover-packages) switch that may be used to restrict coverage
+ report to modules in the indicated package(s)
+
+0.8.5
+
+- Output capture and verbose assertion errors now work when run like
+ 'python setup.py test', as advertised.
+- Code coverage improvements: now coverage will be output for all modules
+ imported by any means that were not in sys.modules at the start of the test
+ run. By default, test modules will be excluded from the coverage report, but
+ you can include them with the -t (--cover-tests) option.
+
+0.8.4
+
+- Fix bugs in handling of setup/teardown fixtures that could cause TypeError
+ exceptions in fixtures to be silently ignored, or multiple fixtures of the
+ same type to run. Thanks to Titus Brown for the bug report.
+
+0.8.3
+
+- Add -V (--version) switch to nosetests
+- Fix bug where sys.path would not be set up correctly when running some
+ tests, producing spurious import errors (Thanks to Titus Brown and Mike
+ Thomson for the bug reports)
+- For test classses not derived from unittest.TestCase, output (module.Class)
+ "doc string" as test description, when method doc string is available
+ (Thanks to David Keeney for the suggestion, even if this isn't quite what he
+ meant)
+
+0.8.2
+
+- Revise import to bypass sys.path and manipulate sys.modules more
+ intelligently, ensuring that the test module we think we are loading is the
+ module we actually load, and that modules loaded by other imports are not
+ reloaded without cause
+- Allow test directories inside of packages. Formerly directories matching
+ testMatch but lacking an __init__.py would cause an ImportError when located
+ inside of packages
+- Fix bugs in different handling of -f switch in combination with -w and -o
+
+0.8.1
+
+- Fix bug in main() that resulted in incorrect exit status for nosetests
+ script when tests fail
+- Add missing test files to MANIFEST.in
+- Miscellaneous pylint cleanups
+
+0.8
+
+- Add doctest support
+- Add optional code coverage support, using Ned Batchelder's coverage.py;
+ activate with --coverage switch or NOSE_COVERAGE environment variable
+- More informative error message on import error
+- Fix bug where module setup could be called twice and teardown skipped
+ for certain setup method names.
+- main() returns success value, does not exit. run_exit() added to support
+ old behavior; nosetests script now calls nose.run_exit()
+
+0.7.5
+
+- Fix bus error on exit
+- Discover tests inside of non-TestCase classes that match testMatch
+- Reorganize selftest: now selftest tests the output of a full nose run
+- Add test_with_setup.py contributed by Kumar McMillan
+
+0.7.2
+
+- Refactor and correct bugs in discovery and test loading
+- Reorganize and expand documentation
+- Add -f (run this test file only) switch
+
+0.7.1
+
+- Bugfix release: test files in root of working directory were not being
+ stripped of file extension before import.
+
+0.7
+
+- Change license to LGPL
+- Major rework of output capture and assert introspection
+- Improve test discovery: now finds tests in packages
+- Replace -n switch ('no cwd') with -w switch ('look here')
+
+0.6
+
+- New nosetests script
+- Allow specification of names on command line that are loadable but not
+ directly loadable as modules (eg nosetests -o path/to/tests.py)
+- Add optional py.test-like assert introspection. Thanks to Kevin Dangoor
+ for the suggestion.
+- Improvements to selftest
+
+0.5.1
+
+- Increased compatibility with python 2.3 (and maybe earlier)
+- Increased compatibility with tests written for py.test: now calls
+ module.setup_module(module) if module.setup_module() fails
+
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..5d36ca2
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,18 @@
+include AUTHORS
+include CHANGELOG
+include NEWS
+include README.txt
+include lgpl.txt
+include nosetests.1
+include install-rpm.sh
+include bin/nosetests
+include distribute_setup.py
+include selftest.py
+include setup3lib.py
+include patch.py
+include nose/usage.txt
+graft doc
+graft examples
+graft unit_tests
+graft functional_tests
+prune doc/.build
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..fa8043f
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,17 @@
+1.2
+---
+
+This release was a long time in coming, and wouldn't have been
+possible at all without the contributions of numerous developers and
+community members. Please check out the changelog to see what's new
+and who to thank.
+
+If you're interested in the future of nose, please take a look at the
+nose2 project on github (https://github.com/nose-devs/nose2) or pypi
+(http://pypi.python.org/pypi/nose2/0.4.1).
+
+And lastly if you have the money to spare, please consider donating to
+the John Hunter memorial fund (http://numfocus.org/johnhunter/). We
+all give up time with our families to work on free software: so now
+the free software community that has benefited so much from that
+time we took can give something back to his family.
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..0ad5792
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,38 @@
+Metadata-Version: 1.1
+Name: nose
+Version: 1.2.1
+Summary: nose extends unittest to make testing easier
+Home-page: http://readthedocs.org/docs/nose/
+Author: Jason Pellerin
+Author-email: jpellerin+nose@gmail.com
+License: GNU LGPL
+Description: nose extends the test loading and running features of unittest, making
+ it easier to write, find and run tests.
+
+ By default, nose will run tests in files or directories under the current
+ working directory whose names include "test" or "Test" at a word boundary
+ (like "test_this" or "functional_test" or "TestClass" but not
+ "libtest"). Test output is similar to that of unittest, but also includes
+ captured stdout output from failing tests, for easy print-style debugging.
+
+ These features, and many more, are customizable through the use of
+ plugins. Plugins included with nose provide support for doctest, code
+ coverage and profiling, flexible attribute-based test selection,
+ output capture and more. More information about writing plugins may be
+ found on in the nose API documentation, here:
+ http://readthedocs.org/docs/nose/
+
+ If you have recently reported a bug marked as fixed, or have a craving for
+ the very latest, you may want the development version instead:
+ https://github.com/nose-devs/nose/tarball/master#egg=nose-dev
+
+Keywords: test unittest doctest automatic discovery
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
+Classifier: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Software Development :: Testing
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..f8a057f
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,494 @@
+
+Basic usage
+***********
+
+Use the nosetests script (after installation by setuptools):
+
+ nosetests [options] [(optional) test files or directories]
+
+In addition to passing command-line options, you may also put
+configuration options in a .noserc or nose.cfg file in your home
+directory. These are standard .ini-style config files. Put your
+nosetests configuration in a [nosetests] section, with the -- prefix
+removed:
+
+ [nosetests]
+ verbosity=3
+ with-doctest=1
+
+There are several other ways to use the nose test runner besides the
+*nosetests* script. You may use nose in a test script:
+
+ import nose
+ nose.main()
+
+If you don't want the test script to exit with 0 on success and 1 on
+failure (like unittest.main), use nose.run() instead:
+
+ import nose
+ result = nose.run()
+
+*result* will be true if the test run succeeded, or false if any test
+failed or raised an uncaught exception. Lastly, you can run nose.core
+directly, which will run nose.main():
+
+ python /path/to/nose/core.py
+
+Please see the usage message for the nosetests script for information
+about how to control which tests nose runs, which plugins are loaded,
+and the test output.
+
+
+Extended usage
+==============
+
+nose collects tests automatically from python source files,
+directories and packages found in its working directory (which
+defaults to the current working directory). Any python source file,
+directory or package that matches the testMatch regular expression (by
+default: *(?:^|[b_.-])[Tt]est)* will be collected as a test (or source
+for collection of tests). In addition, all other packages found in the
+working directory will be examined for python source files or
+directories that match testMatch. Package discovery descends all the
+way down the tree, so package.tests and package.sub.tests and
+package.sub.sub2.tests will all be collected.
+
+Within a test directory or package, any python source file matching
+testMatch will be examined for test cases. Within a test module,
+functions and classes whose names match testMatch and TestCase
+subclasses with any name will be loaded and executed as tests. Tests
+may use the assert keyword or raise AssertionErrors to indicate test
+failure. TestCase subclasses may do the same or use the various
+TestCase methods available.
+
+
+Selecting Tests
+---------------
+
+To specify which tests to run, pass test names on the command line:
+
+ nosetests only_test_this.py
+
+Test names specified may be file or module names, and may optionally
+indicate the test case to run by separating the module or file name
+from the test case name with a colon. Filenames may be relative or
+absolute. Examples:
+
+ nosetests test.module
+ nosetests another.test:TestCase.test_method
+ nosetests a.test:TestCase
+ nosetests /path/to/test/file.py:test_function
+
+You may also change the working directory where nose looks for tests
+by using the -w switch:
+
+ nosetests -w /path/to/tests
+
+Note, however, that support for multiple -w arguments is now
+deprecated and will be removed in a future release. As of nose 0.10,
+you can get the same behavior by specifying the target directories
+*without* the -w switch:
+
+ nosetests /path/to/tests /another/path/to/tests
+
+Further customization of test selection and loading is possible
+through the use of plugins.
+
+Test result output is identical to that of unittest, except for the
+additional features (error classes, and plugin-supplied features such
+as output capture and assert introspection) detailed in the options
+below.
+
+
+Configuration
+-------------
+
+In addition to passing command-line options, you may also put
+configuration options in your project's *setup.cfg* file, or a .noserc
+or nose.cfg file in your home directory. In any of these standard
+.ini-style config files, you put your nosetests configuration in a
+"[nosetests]" section. Options are the same as on the command line,
+with the -- prefix removed. For options that are simple switches, you
+must supply a value:
+
+ [nosetests]
+ verbosity=3
+ with-doctest=1
+
+All configuration files that are found will be loaded and their
+options combined. You can override the standard config file loading
+with the "-c" option.
+
+
+Using Plugins
+-------------
+
+There are numerous nose plugins available via easy_install and
+elsewhere. To use a plugin, just install it. The plugin will add
+command line options to nosetests. To verify that the plugin is
+installed, run:
+
+ nosetests --plugins
+
+You can add -v or -vv to that command to show more information about
+each plugin.
+
+If you are running nose.main() or nose.run() from a script, you can
+specify a list of plugins to use by passing a list of plugins with the
+plugins keyword argument.
+
+
+0.9 plugins
+-----------
+
+nose 1.0 can use SOME plugins that were written for nose 0.9. The
+default plugin manager inserts a compatibility wrapper around 0.9
+plugins that adapts the changed plugin api calls. However, plugins
+that access nose internals are likely to fail, especially if they
+attempt to access test case or test suite classes. For example,
+plugins that try to determine if a test passed to startTest is an
+individual test or a suite will fail, partly because suites are no
+longer passed to startTest and partly because it's likely that the
+plugin is trying to find out if the test is an instance of a class
+that no longer exists.
+
+
+0.10 and 0.11 plugins
+---------------------
+
+All plugins written for nose 0.10 and 0.11 should work with nose 1.0.
+
+
+Options
+-------
+
+-V, --version
+
+ Output nose version and exit
+
+-p, --plugins
+
+ Output list of available plugins and exit. Combine with higher
+ verbosity for greater detail
+
+-v=DEFAULT, --verbose=DEFAULT
+
+ Be more verbose. [NOSE_VERBOSE]
+
+--verbosity=VERBOSITY
+
+ Set verbosity; --verbosity=2 is the same as -v
+
+-q=DEFAULT, --quiet=DEFAULT
+
+ Be less verbose
+
+-c=FILES, --config=FILES
+
+ Load configuration from config file(s). May be specified multiple
+ times; in that case, all config files will be loaded and combined
+
+-w=WHERE, --where=WHERE
+
+ Look for tests in this directory. May be specified multiple times.
+ The first directory passed will be used as the working directory,
+ in place of the current working directory, which is the default.
+ Others will be added to the list of tests to execute. [NOSE_WHERE]
+
+--py3where=PY3WHERE
+
+ Look for tests in this directory under Python 3.x. Functions the
+ same as 'where', but only applies if running under Python 3.x or
+ above. Note that, if present under 3.x, this option completely
+ replaces any directories specified with 'where', so the 'where'
+ option becomes ineffective. [NOSE_PY3WHERE]
+
+-m=REGEX, --match=REGEX, --testmatch=REGEX
+
+ Files, directories, function names, and class names that match this
+ regular expression are considered tests. Default:
+ (?:^|[b_./-])[Tt]est [NOSE_TESTMATCH]
+
+--tests=NAMES
+
+ Run these tests (comma-separated list). This argument is useful
+ mainly from configuration files; on the command line, just pass the
+ tests to run as additional arguments with no switch.
+
+-l=DEFAULT, --debug=DEFAULT
+
+ Activate debug logging for one or more systems. Available debug
+ loggers: nose, nose.importer, nose.inspector, nose.plugins,
+ nose.result and nose.selector. Separate multiple names with a
+ comma.
+
+--debug-log=FILE
+
+ Log debug messages to this file (default: sys.stderr)
+
+--logging-config=FILE, --log-config=FILE
+
+ Load logging config from this file -- bypasses all other logging
+ config settings.
+
+-I=REGEX, --ignore-files=REGEX
+
+ Completely ignore any file that matches this regular expression.
+ Takes precedence over any other settings or plugins. Specifying
+ this option will replace the default setting. Specify this option
+ multiple times to add more regular expressions [NOSE_IGNORE_FILES]
+
+-e=REGEX, --exclude=REGEX
+
+ Don't run tests that match regular expression [NOSE_EXCLUDE]
+
+-i=REGEX, --include=REGEX
+
+ This regular expression will be applied to files, directories,
+ function names, and class names for a chance to include additional
+ tests that do not match TESTMATCH. Specify this option multiple
+ times to add more regular expressions [NOSE_INCLUDE]
+
+-x, --stop
+
+ Stop running tests after the first error or failure
+
+-P, --no-path-adjustment
+
+ Don't make any changes to sys.path when loading tests [NOSE_NOPATH]
+
+--exe
+
+ Look for tests in python modules that are executable. Normal
+ behavior is to exclude executable modules, since they may not be
+ import-safe [NOSE_INCLUDE_EXE]
+
+--noexe
+
+ DO NOT look for tests in python modules that are executable. (The
+ default on the windows platform is to do so.)
+
+--traverse-namespace
+
+ Traverse through all path entries of a namespace package
+
+--first-package-wins, --first-pkg-wins, --1st-pkg-wins
+
+ nose's importer will normally evict a package from sys.modules if
+ it sees a package with the same name in a different location. Set
+ this option to disable that behavior.
+
+-a=ATTR, --attr=ATTR
+
+ Run only tests that have attributes specified by ATTR [NOSE_ATTR]
+
+-A=EXPR, --eval-attr=EXPR
+
+ Run only tests for whose attributes the Python expression EXPR
+ evaluates to True [NOSE_EVAL_ATTR]
+
+-s, --nocapture
+
+ Don't capture stdout (any stdout output will be printed
+ immediately) [NOSE_NOCAPTURE]
+
+--nologcapture
+
+ Disable logging capture plugin. Logging configurtion will be left
+ intact. [NOSE_NOLOGCAPTURE]
+
+--logging-format=FORMAT
+
+ Specify custom format to print statements. Uses the same format as
+ used by standard logging handlers. [NOSE_LOGFORMAT]
+
+--logging-datefmt=FORMAT
+
+ Specify custom date/time format to print statements. Uses the same
+ format as used by standard logging handlers. [NOSE_LOGDATEFMT]
+
+--logging-filter=FILTER
+
+ Specify which statements to filter in/out. By default, everything
+ is captured. If the output is too verbose, use this option to
+ filter out needless output. Example: filter=foo will capture
+ statements issued ONLY to foo or foo.what.ever.sub but not foobar
+ or other logger. Specify multiple loggers with comma:
+ filter=foo,bar,baz. If any logger name is prefixed with a minus, eg
+ filter=-foo, it will be excluded rather than included. Default:
+ exclude logging messages from nose itself (-nose). [NOSE_LOGFILTER]
+
+--logging-clear-handlers
+
+ Clear all other logging handlers
+
+--with-coverage
+
+ Enable plugin Coverage: Activate a coverage report using Ned
+ Batchelder's coverage module. [NOSE_WITH_COVERAGE]
+
+--cover-package=PACKAGE
+
+ Restrict coverage output to selected packages [NOSE_COVER_PACKAGE]
+
+--cover-erase
+
+ Erase previously collected coverage statistics before run
+
+--cover-tests
+
+ Include test modules in coverage report [NOSE_COVER_TESTS]
+
+--cover-inclusive
+
+ Include all python files under working directory in coverage
+ report. Useful for discovering holes in test coverage if not all
+ files are imported by the test suite. [NOSE_COVER_INCLUSIVE]
+
+--cover-html
+
+ Produce HTML coverage information
+
+--cover-html-dir=DIR
+
+ Produce HTML coverage information in dir
+
+--cover-branches
+
+ Include branch coverage in coverage report [NOSE_COVER_BRANCHES]
+
+--cover-xml
+
+ Produce XML coverage information
+
+--cover-xml-file=FILE
+
+ Produce XML coverage information in file
+
+--pdb
+
+ Drop into debugger on errors
+
+--pdb-failures
+
+ Drop into debugger on failures
+
+--no-deprecated
+
+ Disable special handling of DeprecatedTest exceptions.
+
+--with-doctest
+
+ Enable plugin Doctest: Activate doctest plugin to find and run
+ doctests in non-test modules. [NOSE_WITH_DOCTEST]
+
+--doctest-tests
+
+ Also look for doctests in test modules. Note that classes, methods
+ and functions should have either doctests or non-doctest tests, not
+ both. [NOSE_DOCTEST_TESTS]
+
+--doctest-extension=EXT
+
+ Also look for doctests in files with this extension
+ [NOSE_DOCTEST_EXTENSION]
+
+--doctest-result-variable=VAR
+
+ Change the variable name set to the result of the last interpreter
+ command from the default '_'. Can be used to avoid conflicts with
+ the _() function used for text translation.
+ [NOSE_DOCTEST_RESULT_VAR]
+
+--doctest-fixtures=SUFFIX
+
+ Find fixtures for a doctest file in module with this name appended
+ to the base name of the doctest file
+
+--with-isolation
+
+ Enable plugin IsolationPlugin: Activate the isolation plugin to
+ isolate changes to external modules to a single test module or
+ package. The isolation plugin resets the contents of sys.modules
+ after each test module or package runs to its state before the
+ test. PLEASE NOTE that this plugin should not be used with the
+ coverage plugin, or in any other case where module reloading may
+ produce undesirable side-effects. [NOSE_WITH_ISOLATION]
+
+-d, --detailed-errors, --failure-detail
+
+ Add detail to error output by attempting to evaluate failed asserts
+ [NOSE_DETAILED_ERRORS]
+
+--with-profile
+
+ Enable plugin Profile: Use this plugin to run tests using the
+ hotshot profiler. [NOSE_WITH_PROFILE]
+
+--profile-sort=SORT
+
+ Set sort order for profiler output
+
+--profile-stats-file=FILE
+
+ Profiler stats file; default is a new temp file on each run
+
+--profile-restrict=RESTRICT
+
+ Restrict profiler output. See help for pstats.Stats for details
+
+--no-skip
+
+ Disable special handling of SkipTest exceptions.
+
+--with-id
+
+ Enable plugin TestId: Activate to add a test id (like #1) to each
+ test name output. Activate with --failed to rerun failing tests
+ only. [NOSE_WITH_ID]
+
+--id-file=FILE
+
+ Store test ids found in test runs in this file. Default is the file
+ .noseids in the working directory.
+
+--failed
+
+ Run the tests that failed in the last test run.
+
+--processes=NUM
+
+ Spread test run among this many processes. Set a number equal to
+ the number of processors or cores in your machine for best results.
+ [NOSE_PROCESSES]
+
+--process-timeout=SECONDS
+
+ Set timeout for return of results from each test runner process.
+ [NOSE_PROCESS_TIMEOUT]
+
+--process-restartworker
+
+ If set, will restart each worker process once their tests are done,
+ this helps control memory leaks from killing the system.
+ [NOSE_PROCESS_RESTARTWORKER]
+
+--with-xunit
+
+ Enable plugin Xunit: This plugin provides test results in the
+ standard XUnit XML format. [NOSE_WITH_XUNIT]
+
+--xunit-file=FILE
+
+ Path to xml file to store the xunit report in. Default is
+ nosetests.xml in the working directory [NOSE_XUNIT_FILE]
+
+--all-modules
+
+ Enable plugin AllModules: Collect tests from all python modules.
+ [NOSE_ALL_MODULES]
+
+--collect-only
+
+ Enable collect-only: Collect and output test names only, don't run
+ any tests. [COLLECT_ONLY]
diff --git a/bin/nosetests b/bin/nosetests
new file mode 100755
index 0000000..36e0ee9
--- /dev/null
+++ b/bin/nosetests
@@ -0,0 +1,6 @@
+#!/usr/bin/env python
+
+from nose import main
+
+if __name__ == '__main__':
+ main()
diff --git a/distribute_setup.py b/distribute_setup.py
new file mode 100644
index 0000000..3ea2e66
--- /dev/null
+++ b/distribute_setup.py
@@ -0,0 +1,485 @@
+#!python
+"""Bootstrap distribute installation
+
+If you want to use setuptools in your package's setup.py, just include this
+file in the same directory with it, and add this to the top of your setup.py::
+
+ from distribute_setup import use_setuptools
+ use_setuptools()
+
+If you want to require a specific version of setuptools, set a download
+mirror, or use an alternate download directory, you can do so by supplying
+the appropriate options to ``use_setuptools()``.
+
+This file can also be run as a script to install or upgrade setuptools.
+"""
+import os
+import sys
+import time
+import fnmatch
+import tempfile
+import tarfile
+from distutils import log
+
+try:
+ from site import USER_SITE
+except ImportError:
+ USER_SITE = None
+
+try:
+ import subprocess
+
+ def _python_cmd(*args):
+ args = (sys.executable,) + args
+ return subprocess.call(args) == 0
+
+except ImportError:
+ # will be used for python 2.3
+ def _python_cmd(*args):
+ args = (sys.executable,) + args
+ # quoting arguments if windows
+ if sys.platform == 'win32':
+ def quote(arg):
+ if ' ' in arg:
+ return '"%s"' % arg
+ return arg
+ args = [quote(arg) for arg in args]
+ return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
+
+DEFAULT_VERSION = "0.6.14"
+DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
+SETUPTOOLS_FAKED_VERSION = "0.6c11"
+
+SETUPTOOLS_PKG_INFO = """\
+Metadata-Version: 1.0
+Name: setuptools
+Version: %s
+Summary: xxxx
+Home-page: xxx
+Author: xxx
+Author-email: xxx
+License: xxx
+Description: xxx
+""" % SETUPTOOLS_FAKED_VERSION
+
+
+def _install(tarball):
+ # extracting the tarball
+ tmpdir = tempfile.mkdtemp()
+ log.warn('Extracting in %s', tmpdir)
+ old_wd = os.getcwd()
+ try:
+ os.chdir(tmpdir)
+ tar = tarfile.open(tarball)
+ _extractall(tar)
+ tar.close()
+
+ # going in the directory
+ subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
+ os.chdir(subdir)
+ log.warn('Now working in %s', subdir)
+
+ # installing
+ log.warn('Installing Distribute')
+ if not _python_cmd('setup.py', 'install'):
+ log.warn('Something went wrong during the installation.')
+ log.warn('See the error message above.')
+ finally:
+ os.chdir(old_wd)
+
+
+def _build_egg(egg, tarball, to_dir):
+ # extracting the tarball
+ tmpdir = tempfile.mkdtemp()
+ log.warn('Extracting in %s', tmpdir)
+ old_wd = os.getcwd()
+ try:
+ os.chdir(tmpdir)
+ tar = tarfile.open(tarball)
+ _extractall(tar)
+ tar.close()
+
+ # going in the directory
+ subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
+ os.chdir(subdir)
+ log.warn('Now working in %s', subdir)
+
+ # building an egg
+ log.warn('Building a Distribute egg in %s', to_dir)
+ _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
+
+ finally:
+ os.chdir(old_wd)
+ # returning the result
+ log.warn(egg)
+ if not os.path.exists(egg):
+ raise IOError('Could not build the egg.')
+
+
+def _do_download(version, download_base, to_dir, download_delay):
+ egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
+ % (version, sys.version_info[0], sys.version_info[1]))
+ if not os.path.exists(egg):
+ tarball = download_setuptools(version, download_base,
+ to_dir, download_delay)
+ _build_egg(egg, tarball, to_dir)
+ sys.path.insert(0, egg)
+ import setuptools
+ setuptools.bootstrap_install_from = egg
+
+
+def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
+ to_dir=os.curdir, download_delay=15, no_fake=True):
+ # making sure we use the absolute path
+ to_dir = os.path.abspath(to_dir)
+ was_imported = 'pkg_resources' in sys.modules or \
+ 'setuptools' in sys.modules
+ try:
+ try:
+ import pkg_resources
+ if not hasattr(pkg_resources, '_distribute'):
+ if not no_fake:
+ _fake_setuptools()
+ raise ImportError
+ except ImportError:
+ return _do_download(version, download_base, to_dir, download_delay)
+ try:
+ pkg_resources.require("distribute>="+version)
+ return
+ except pkg_resources.VersionConflict:
+ e = sys.exc_info()[1]
+ if was_imported:
+ sys.stderr.write(
+ "The required version of distribute (>=%s) is not available,\n"
+ "and can't be installed while this script is running. Please\n"
+ "install a more recent version first, using\n"
+ "'easy_install -U distribute'."
+ "\n\n(Currently using %r)\n" % (version, e.args[0]))
+ sys.exit(2)
+ else:
+ del pkg_resources, sys.modules['pkg_resources'] # reload ok
+ return _do_download(version, download_base, to_dir,
+ download_delay)
+ except pkg_resources.DistributionNotFound:
+ return _do_download(version, download_base, to_dir,
+ download_delay)
+ finally:
+ if not no_fake:
+ _create_fake_setuptools_pkg_info(to_dir)
+
+def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
+ to_dir=os.curdir, delay=15):
+ """Download distribute from a specified location and return its filename
+
+ `version` should be a valid distribute version number that is available
+ as an egg for download under the `download_base` URL (which should end
+ with a '/'). `to_dir` is the directory where the egg will be downloaded.
+ `delay` is the number of seconds to pause before an actual download
+ attempt.
+ """
+ # making sure we use the absolute path
+ to_dir = os.path.abspath(to_dir)
+ try:
+ from urllib.request import urlopen
+ except ImportError:
+ from urllib2 import urlopen
+ tgz_name = "distribute-%s.tar.gz" % version
+ url = download_base + tgz_name
+ saveto = os.path.join(to_dir, tgz_name)
+ src = dst = None
+ if not os.path.exists(saveto): # Avoid repeated downloads
+ try:
+ log.warn("Downloading %s", url)
+ src = urlopen(url)
+ # Read/write all in one block, so we don't create a corrupt file
+ # if the download is interrupted.
+ data = src.read()
+ dst = open(saveto, "wb")
+ dst.write(data)
+ finally:
+ if src:
+ src.close()
+ if dst:
+ dst.close()
+ return os.path.realpath(saveto)
+
+def _no_sandbox(function):
+ def __no_sandbox(*args, **kw):
+ try:
+ from setuptools.sandbox import DirectorySandbox
+ if not hasattr(DirectorySandbox, '_old'):
+ def violation(*args):
+ pass
+ DirectorySandbox._old = DirectorySandbox._violation
+ DirectorySandbox._violation = violation
+ patched = True
+ else:
+ patched = False
+ except ImportError:
+ patched = False
+
+ try:
+ return function(*args, **kw)
+ finally:
+ if patched:
+ DirectorySandbox._violation = DirectorySandbox._old
+ del DirectorySandbox._old
+
+ return __no_sandbox
+
+def _patch_file(path, content):
+ """Will backup the file then patch it"""
+ existing_content = open(path).read()
+ if existing_content == content:
+ # already patched
+ log.warn('Already patched.')
+ return False
+ log.warn('Patching...')
+ _rename_path(path)
+ f = open(path, 'w')
+ try:
+ f.write(content)
+ finally:
+ f.close()
+ return True
+
+_patch_file = _no_sandbox(_patch_file)
+
+def _same_content(path, content):
+ return open(path).read() == content
+
+def _rename_path(path):
+ new_name = path + '.OLD.%s' % time.time()
+ log.warn('Renaming %s into %s', path, new_name)
+ os.rename(path, new_name)
+ return new_name
+
+def _remove_flat_installation(placeholder):
+ if not os.path.isdir(placeholder):
+ log.warn('Unkown installation at %s', placeholder)
+ return False
+ found = False
+ for file in os.listdir(placeholder):
+ if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
+ found = True
+ break
+ if not found:
+ log.warn('Could not locate setuptools*.egg-info')
+ return
+
+ log.warn('Removing elements out of the way...')
+ pkg_info = os.path.join(placeholder, file)
+ if os.path.isdir(pkg_info):
+ patched = _patch_egg_dir(pkg_info)
+ else:
+ patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
+
+ if not patched:
+ log.warn('%s already patched.', pkg_info)
+ return False
+ # now let's move the files out of the way
+ for element in ('setuptools', 'pkg_resources.py', 'site.py'):
+ element = os.path.join(placeholder, element)
+ if os.path.exists(element):
+ _rename_path(element)
+ else:
+ log.warn('Could not find the %s element of the '
+ 'Setuptools distribution', element)
+ return True
+
+_remove_flat_installation = _no_sandbox(_remove_flat_installation)
+
+def _after_install(dist):
+ log.warn('After install bootstrap.')
+ placeholder = dist.get_command_obj('install').install_purelib
+ _create_fake_setuptools_pkg_info(placeholder)
+
+def _create_fake_setuptools_pkg_info(placeholder):
+ if not placeholder or not os.path.exists(placeholder):
+ log.warn('Could not find the install location')
+ return
+ pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
+ setuptools_file = 'setuptools-%s-py%s.egg-info' % \
+ (SETUPTOOLS_FAKED_VERSION, pyver)
+ pkg_info = os.path.join(placeholder, setuptools_file)
+ if os.path.exists(pkg_info):
+ log.warn('%s already exists', pkg_info)
+ return
+
+ log.warn('Creating %s', pkg_info)
+ f = open(pkg_info, 'w')
+ try:
+ f.write(SETUPTOOLS_PKG_INFO)
+ finally:
+ f.close()
+
+ pth_file = os.path.join(placeholder, 'setuptools.pth')
+ log.warn('Creating %s', pth_file)
+ f = open(pth_file, 'w')
+ try:
+ f.write(os.path.join(os.curdir, setuptools_file))
+ finally:
+ f.close()
+
+_create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info)
+
+def _patch_egg_dir(path):
+ # let's check if it's already patched
+ pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
+ if os.path.exists(pkg_info):
+ if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
+ log.warn('%s already patched.', pkg_info)
+ return False
+ _rename_path(path)
+ os.mkdir(path)
+ os.mkdir(os.path.join(path, 'EGG-INFO'))
+ pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
+ f = open(pkg_info, 'w')
+ try:
+ f.write(SETUPTOOLS_PKG_INFO)
+ finally:
+ f.close()
+ return True
+
+_patch_egg_dir = _no_sandbox(_patch_egg_dir)
+
+def _before_install():
+ log.warn('Before install bootstrap.')
+ _fake_setuptools()
+
+
+def _under_prefix(location):
+ if 'install' not in sys.argv:
+ return True
+ args = sys.argv[sys.argv.index('install')+1:]
+ for index, arg in enumerate(args):
+ for option in ('--root', '--prefix'):
+ if arg.startswith('%s=' % option):
+ top_dir = arg.split('root=')[-1]
+ return location.startswith(top_dir)
+ elif arg == option:
+ if len(args) > index:
+ top_dir = args[index+1]
+ return location.startswith(top_dir)
+ if arg == '--user' and USER_SITE is not None:
+ return location.startswith(USER_SITE)
+ return True
+
+
+def _fake_setuptools():
+ log.warn('Scanning installed packages')
+ try:
+ import pkg_resources
+ except ImportError:
+ # we're cool
+ log.warn('Setuptools or Distribute does not seem to be installed.')
+ return
+ ws = pkg_resources.working_set
+ try:
+ setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools',
+ replacement=False))
+ except TypeError:
+ # old distribute API
+ setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools'))
+
+ if setuptools_dist is None:
+ log.warn('No setuptools distribution found')
+ return
+ # detecting if it was already faked
+ setuptools_location = setuptools_dist.location
+ log.warn('Setuptools installation detected at %s', setuptools_location)
+
+ # if --root or --preix was provided, and if
+ # setuptools is not located in them, we don't patch it
+ if not _under_prefix(setuptools_location):
+ log.warn('Not patching, --root or --prefix is installing Distribute'
+ ' in another location')
+ return
+
+ # let's see if its an egg
+ if not setuptools_location.endswith('.egg'):
+ log.warn('Non-egg installation')
+ res = _remove_flat_installation(setuptools_location)
+ if not res:
+ return
+ else:
+ log.warn('Egg installation')
+ pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
+ if (os.path.exists(pkg_info) and
+ _same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
+ log.warn('Already patched.')
+ return
+ log.warn('Patching...')
+ # let's create a fake egg replacing setuptools one
+ res = _patch_egg_dir(setuptools_location)
+ if not res:
+ return
+ log.warn('Patched done.')
+ _relaunch()
+
+
+def _relaunch():
+ log.warn('Relaunching...')
+ # we have to relaunch the process
+ # pip marker to avoid a relaunch bug
+ if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']:
+ sys.argv[0] = 'setup.py'
+ args = [sys.executable] + sys.argv
+ sys.exit(subprocess.call(args))
+
+
+def _extractall(self, path=".", members=None):
+ """Extract all members from the archive to the current working
+ directory and set owner, modification time and permissions on
+ directories afterwards. `path' specifies a different directory
+ to extract to. `members' is optional and must be a subset of the
+ list returned by getmembers().
+ """
+ import copy
+ import operator
+ from tarfile import ExtractError
+ directories = []
+
+ if members is None:
+ members = self
+
+ for tarinfo in members:
+ if tarinfo.isdir():
+ # Extract directories with a safe mode.
+ directories.append(tarinfo)
+ tarinfo = copy.copy(tarinfo)
+ tarinfo.mode = 448 # decimal for oct 0700
+ self.extract(tarinfo, path)
+
+ # Reverse sort directories.
+ if sys.version_info < (2, 4):
+ def sorter(dir1, dir2):
+ return cmp(dir1.name, dir2.name)
+ directories.sort(sorter)
+ directories.reverse()
+ else:
+ directories.sort(key=operator.attrgetter('name'), reverse=True)
+
+ # Set correct owner, mtime and filemode on directories.
+ for tarinfo in directories:
+ dirpath = os.path.join(path, tarinfo.name)
+ try:
+ self.chown(tarinfo, dirpath)
+ self.utime(tarinfo, dirpath)
+ self.chmod(tarinfo, dirpath)
+ except ExtractError:
+ e = sys.exc_info()[1]
+ if self.errorlevel > 1:
+ raise
+ else:
+ self._dbg(1, "tarfile: %s" % e)
+
+
+def main(argv, version=DEFAULT_VERSION):
+ """Install or upgrade setuptools and EasyInstall"""
+ tarball = download_setuptools()
+ _install(tarball)
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/doc/.static/nose.css b/doc/.static/nose.css
new file mode 100644
index 0000000..38602e2
--- /dev/null
+++ b/doc/.static/nose.css
@@ -0,0 +1,74 @@
+@import url(default.css);
+
+body {
+ padding-left: 20px;
+ background-color: #fff;
+ font: x-small Georgia,Serif;
+ font-size/* */:/**/small;
+ font-size: /**/small;
+}
+
+div.body { border-right: 1px solid #ccc; }
+
+div.body h1 { margin-top: 0; font-size: 130%; margin-right: 0px; }
+div.body h2 { font-size: 120%; }
+div.body h3 { font-size: 115%; }
+div.body h4 { font-size: 110%; }
+div.body h5 { font-size: 106%; }
+div.body h6 { font-size: 103%; }
+
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+ border: none;
+ background-color: #fff;
+}
+
+.new {
+ color: #f00;
+ font-weight: bold;
+}
+
+pre, tt {
+ background-color: #ffe;
+}
+
+div.body h1.big {
+ font-family: courier, "courier new", monospace;
+ font-weight: bold;
+ font-size: 800%;
+ background-color: #fff;
+ margin: 0px -20px 0px -25px;
+ padding: 0px 0px 0px 10px;
+ border: none;
+ color: #000;
+}
+
+div.body h2.big {
+ font-weight: bold;
+ margin: -10px -20px 0px -20px;
+}
+
+p.big {
+ font-family: 'Trebuchet MS', sans-serif;
+ font-weight: bold;
+ font-size: 200%;
+ margin-left: -20px;
+ padding-left: 10px;
+}
+
+span.biglink {
+ font-size: 1.3em
+}
+
+table.contentstable td {
+ vertical-align: top
+ padding-left: 0px;
+ padding-right: 10px;
+}
+
+table.contentstable td p {
+ text-align: left;
+}
\ No newline at end of file
diff --git a/doc/.templates/index.html b/doc/.templates/index.html
new file mode 100644
index 0000000..affb29e
--- /dev/null
+++ b/doc/.templates/index.html
@@ -0,0 +1,52 @@
+
diff --git a/doc/.templates/layout.html b/doc/.templates/layout.html
new file mode 100644
index 0000000..e49c1e9
--- /dev/null
+++ b/doc/.templates/layout.html
@@ -0,0 +1,16 @@
+{% extends "!layout.html" %}
+
+{%- block relbar1 %}
+{% if pagename != 'index' %}{{ super() }}{% endif %}
+{% endblock %}
+
+{%- block footer %}
+{{ super() }}
+
+
+{%- endblock %}
diff --git a/doc/.templates/page.html b/doc/.templates/page.html
new file mode 100644
index 0000000..3416437
--- /dev/null
+++ b/doc/.templates/page.html
@@ -0,0 +1,7 @@
+{% extends "!page.html" %}
+{% block body %}
+{% if pagename == 'index' %}
+{% include "index.html" %}
+{% else %}
+{{ super() }}
+{% endif %}{% endblock %}
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..2a1d23b
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,89 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d .build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html web pickle htmlhelp latex changes linkcheck man readme
+
+help:
+ @echo "Please use \`make ' where is one of"
+ @echo " html to make standalone HTML files"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " changes to make an overview over all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+
+clean:
+ -rm -rf .build/*
+
+html:
+ mkdir -p .build/html .build/doctrees
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) .build/html
+ @echo
+ @echo "Build finished. The HTML pages are in .build/html."
+
+pickle:
+ mkdir -p .build/pickle .build/doctrees
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) .build/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+web: pickle
+
+json:
+ mkdir -p .build/json .build/doctrees
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) .build/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ mkdir -p .build/htmlhelp .build/doctrees
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) .build/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in .build/htmlhelp."
+
+latex:
+ mkdir -p .build/latex .build/doctrees
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) .build/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in .build/latex."
+ @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+ "run these through (pdf)latex."
+
+changes:
+ mkdir -p .build/changes .build/doctrees
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) .build/changes
+ @echo
+ @echo "The overview file is in .build/changes."
+
+linkcheck:
+ mkdir -p .build/linkcheck .build/doctrees
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) .build/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in .build/linkcheck/output.txt."
+
+man:
+ mkdir -p .build/man ./build/doctrees
+ $(SPHINXBUILD) -b manpage $(ALLSPHINXOPTS) .build/man man.rst
+ cp .build/man/man.man ../nosetests.1
+ @echo
+ @echo "Generated man page copied to ../nosetests.1"
+
+readme:
+ mkdir -p .build/text .build/doctrees$
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) .build/text usage.rst
+ cp .build/text/usage.txt ../README.txt
+ @echo
+ @echo "Updated ../README.txt"
diff --git a/doc/api.rst b/doc/api.rst
new file mode 100644
index 0000000..b2dd665
--- /dev/null
+++ b/doc/api.rst
@@ -0,0 +1,20 @@
+nose internals
+==============
+
+.. toctree ::
+ :maxdepth: 2
+
+ api/core
+ api/loader
+ api/selector
+ api/config
+ api/test_cases
+ api/suite
+ api/result
+ api/proxy
+ api/plugin_manager
+ api/importer
+ api/commands
+ api/twistedtools
+ api/inspector
+ api/util
diff --git a/doc/api/commands.rst b/doc/api/commands.rst
new file mode 100644
index 0000000..c9ae14a
--- /dev/null
+++ b/doc/api/commands.rst
@@ -0,0 +1,2 @@
+.. automodule :: nose.commands
+ :members:
\ No newline at end of file
diff --git a/doc/api/config.rst b/doc/api/config.rst
new file mode 100644
index 0000000..077cf9b
--- /dev/null
+++ b/doc/api/config.rst
@@ -0,0 +1,5 @@
+Configuration
+=============
+
+.. automodule :: nose.config
+ :members:
\ No newline at end of file
diff --git a/doc/api/core.rst b/doc/api/core.rst
new file mode 100644
index 0000000..6e58329
--- /dev/null
+++ b/doc/api/core.rst
@@ -0,0 +1,5 @@
+Test runner and main()
+======================
+
+.. automodule :: nose.core
+ :members:
diff --git a/doc/api/importer.rst b/doc/api/importer.rst
new file mode 100644
index 0000000..956fdb3
--- /dev/null
+++ b/doc/api/importer.rst
@@ -0,0 +1,5 @@
+Importer
+========
+
+.. automodule :: nose.importer
+ :members:
\ No newline at end of file
diff --git a/doc/api/inspector.rst b/doc/api/inspector.rst
new file mode 100644
index 0000000..e204985
--- /dev/null
+++ b/doc/api/inspector.rst
@@ -0,0 +1,5 @@
+Traceback inspector
+===================
+
+.. automodule :: nose.inspector
+ :members:
\ No newline at end of file
diff --git a/doc/api/loader.rst b/doc/api/loader.rst
new file mode 100644
index 0000000..741dd22
--- /dev/null
+++ b/doc/api/loader.rst
@@ -0,0 +1,2 @@
+.. automodule :: nose.loader
+ :members:
\ No newline at end of file
diff --git a/doc/api/plugin_manager.rst b/doc/api/plugin_manager.rst
new file mode 100644
index 0000000..5c1e393
--- /dev/null
+++ b/doc/api/plugin_manager.rst
@@ -0,0 +1,2 @@
+.. automodule :: nose.plugins.manager
+ :members:
\ No newline at end of file
diff --git a/doc/api/proxy.rst b/doc/api/proxy.rst
new file mode 100644
index 0000000..1802074
--- /dev/null
+++ b/doc/api/proxy.rst
@@ -0,0 +1,2 @@
+.. automodule :: nose.proxy
+ :members:
\ No newline at end of file
diff --git a/doc/api/result.rst b/doc/api/result.rst
new file mode 100644
index 0000000..75b110d
--- /dev/null
+++ b/doc/api/result.rst
@@ -0,0 +1,2 @@
+.. automodule :: nose.result
+ :members:
\ No newline at end of file
diff --git a/doc/api/selector.rst b/doc/api/selector.rst
new file mode 100644
index 0000000..d3de5a4
--- /dev/null
+++ b/doc/api/selector.rst
@@ -0,0 +1,2 @@
+.. automodule :: nose.selector
+ :members:
\ No newline at end of file
diff --git a/doc/api/suite.rst b/doc/api/suite.rst
new file mode 100644
index 0000000..9b764b0
--- /dev/null
+++ b/doc/api/suite.rst
@@ -0,0 +1,2 @@
+.. automodule :: nose.suite
+ :members:
\ No newline at end of file
diff --git a/doc/api/test_cases.rst b/doc/api/test_cases.rst
new file mode 100644
index 0000000..2508f54
--- /dev/null
+++ b/doc/api/test_cases.rst
@@ -0,0 +1,8 @@
+Test Cases
+==========
+
+.. automodule :: nose.case
+ :members:
+
+.. autoclass :: nose.failure.Failure
+ :members:
diff --git a/doc/api/twistedtools.rst b/doc/api/twistedtools.rst
new file mode 100644
index 0000000..584d9c7
--- /dev/null
+++ b/doc/api/twistedtools.rst
@@ -0,0 +1,2 @@
+.. automodule :: nose.twistedtools
+ :members:
\ No newline at end of file
diff --git a/doc/api/util.rst b/doc/api/util.rst
new file mode 100644
index 0000000..f4b683e
--- /dev/null
+++ b/doc/api/util.rst
@@ -0,0 +1,5 @@
+Utility functions
+=================
+
+.. automodule :: nose.util
+ :members:
\ No newline at end of file
diff --git a/doc/conf.py b/doc/conf.py
new file mode 100644
index 0000000..5623175
--- /dev/null
+++ b/doc/conf.py
@@ -0,0 +1,237 @@
+# -*- coding: utf-8 -*-
+#
+# nose documentation build configuration file, created by
+# sphinx-quickstart on Thu Mar 26 16:49:00 2009.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+
+# need to be brutal because of easy_install's pth hacks:
+sys.path.insert(0,
+ os.path.join(os.path.dirname(__file__), '..'))
+sys.path.insert(0, os.path.abspath('.'))
+
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx',
+ 'nose.sphinx.pluginopts', 'manbuilder']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['.templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'nose'
+copyright = u'2009, Jason Pellerin'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '1.2'
+# The full version, including alpha/beta/rc tags.
+release = '1.2.1'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = ['.build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'trac'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'nose.css'
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# " v documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['.static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+html_sidebars = {
+ 'index': 'indexsidebar.html'
+ }
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+# html_additional_pages = {'index': 'index.html'}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, the reST sources are included in the HTML build as _sources/.
+#html_copy_source = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'nosedoc'
+
+"""
+footerbgcolor (CSS color): Background color for the footer line.
+footertextcolor (CSS color): Text color for the footer line.
+sidebarbgcolor (CSS color): Background color for the sidebar.
+sidebartextcolor (CSS color): Text color for the sidebar.
+sidebarlinkcolor (CSS color): Link color for the sidebar.
+relbarbgcolor (CSS color): Background color for the relation bar.
+relbartextcolor (CSS color): Text color for the relation bar.
+relbarlinkcolor (CSS color): Link color for the relation bar.
+bgcolor (CSS color): Body background color.
+textcolor (CSS color): Body text color.
+linkcolor (CSS color): Body link color.
+headbgcolor (CSS color): Background color for headings.
+headtextcolor (CSS color): Text color for headings.
+headlinkcolor (CSS color): Link color for headings.
+codebgcolor (CSS color): Background color for code blocks.
+codetextcolor (CSS color): Default text color for code blocks, if not set differently by the highlighting style.
+bodyfont (CSS font-family): Font for normal text.
+headfont (CSS font-family): Font for headings.
+"""
+html_theme_options = {
+ 'rightsidebar': 'true',
+ 'sidebarbgcolor': '#fff',
+ 'sidebartextcolor': '#20435c',
+ 'sidebarlinkcolor': '#355f7c',
+ 'bgcolor': '#fff',
+ 'codebgcolor': '#ffe',
+ 'headbgcolor': '#fff',
+ 'relbarbgcolor': '#fff',
+ 'relbartextcolor': '#20435c',
+ 'relbarlinkcolor': '#355f7c',
+}
+
+# the css mostly overrides this:
+html_theme = 'default'
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+latex_documents = [
+ ('index', 'nose.tex', ur'nose Documentation',
+ ur'Jason Pellerin', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/dev': None}
diff --git a/doc/contributing.rst b/doc/contributing.rst
new file mode 100644
index 0000000..ac96fcb
--- /dev/null
+++ b/doc/contributing.rst
@@ -0,0 +1,50 @@
+Contributing to nose
+====================
+
+You'd like to contribute to nose? Great! Now that nose is hosted under
+`GitHub `__, contributing is even easier.
+
+Get the code!
+-------------
+
+Start by getting a local working copy of nose from github::
+
+ git clone https://github.com/nose-devs/nose
+
+If you plan to submit changes back to the core repository, you should set up a
+public fork of your own somewhere (`GitHub `__ is a good
+place to do that). See GitHub's `help `__ for details
+on how to contribute to a Git hosted project like nose.
+
+Running nose's tests
+--------------------
+
+nose runs its own test suite with `tox
+`. You don't have to install tox to run
+nose's test suite, but you should, because tox makes it easy to run
+all tests on all supported python versions. You'll also need python
+2.4, 2.5, 2.6, 2.7, 3.1 and jython installed somewhere in your $PATH.
+
+Discuss
+-------
+
+Join the `nose developer list
+`__ at google groups. It's
+low-traffic and mostly signal.
+
+What to work on?
+----------------
+
+You can find a list of open issues at nose's `issue tracker
+`__. If you'd like to
+work on an issue, leave a comment on the issue detailing how you plan
+to fix it, or simply submit a pull request.
+
+I have a great idea for a plugin...
+-----------------------------------
+
+Great! :doc:`Write it `. Release it on `pypi
+`__. If it gains a large following, and
+becomes stable enough to work with nose's 6+ month release cycles, it
+may be a good candidate for inclusion in nose's builtin plugins.
+
diff --git a/doc/developing.rst b/doc/developing.rst
new file mode 100644
index 0000000..32c5680
--- /dev/null
+++ b/doc/developing.rst
@@ -0,0 +1,25 @@
+Developing with nose
+====================
+
+Get the code
+------------
+
+nose is hosted at `GitHub
+`__. You should clone this
+repository if you're developing a plugin or working on bug fixes for nose::
+
+ git clone https://github.com/nose-devs/nose
+
+You should **fork** this repository if you are developing new features for
+nose. Then submit your changes as a pull request.
+
+
+Read
+----
+
+.. toctree ::
+ :maxdepth: 2
+
+ plugins
+ api
+ contributing
diff --git a/doc/docstring.py b/doc/docstring.py
new file mode 100644
index 0000000..5652bd2
--- /dev/null
+++ b/doc/docstring.py
@@ -0,0 +1,25 @@
+from docutils import nodes
+from docutils.statemachine import ViewList
+from nose.util import resolve_name
+
+
+def docstring_directive(dirname, arguments, options, content, lineno,
+ content_offset, block_text, state, state_machine):
+ obj_name = arguments[0]
+ obj = resolve_name(obj_name)
+ rst = ViewList()
+ rst.append(obj.__doc__, '')
+ print "CALLED", obj_name, obj, rst
+ node = nodes.section()
+ surrounding_title_styles = state.memo.title_styles
+ surrounding_section_level = state.memo.section_level
+ state.memo.title_styles = []
+ state.memo.section_level = 0
+ state.nested_parse(rst, 0, node, match_titles=1)
+ state.memo.title_styles = surrounding_title_styles
+ state.memo.section_level = surrounding_section_level
+ return node.children
+
+
+def setup(app):
+ app.add_directive('docstring', docstring_directive, 1, (1, 0, 1))
diff --git a/doc/finding_tests.rst b/doc/finding_tests.rst
new file mode 100644
index 0000000..5f9cb74
--- /dev/null
+++ b/doc/finding_tests.rst
@@ -0,0 +1,32 @@
+Finding and running tests
+-------------------------
+
+nose, by default, follows a few simple rules for test discovery.
+
+* If it looks like a test, it's a test. Names of directories, modules,
+ classes and functions are compared against the testMatch regular
+ expression, and those that match are considered tests. Any class that is a
+ `unittest.TestCase` subclass is also collected, so long as it is inside of a
+ module that looks like a test.
+
+* Directories that don't look like tests and aren't packages are not
+ inspected.
+
+* Packages are always inspected, but they are only collected if they look
+ like tests. This means that you can include your tests inside of your
+ packages (somepackage/tests) and nose will collect the tests without
+ running package code inappropriately.
+
+* When a project appears to have library and test code organized into
+ separate directories, library directories are examined first.
+
+* When nose imports a module, it adds that module's directory to sys.path;
+ when the module is inside of a package, like package.module, it will be
+ loaded as package.module and the directory of *package* will be added to
+ sys.path.
+
+* If an object defines a __test__ attribute that does not evaluate to
+ True, that object will not be collected, nor will any objects it
+ contains.
+
+Be aware that plugins and command line options can change any of those rules.
\ No newline at end of file
diff --git a/doc/further_reading.rst b/doc/further_reading.rst
new file mode 100644
index 0000000..4a93553
--- /dev/null
+++ b/doc/further_reading.rst
@@ -0,0 +1,34 @@
+Further reading
+===============
+
+.. toctree ::
+ :maxdepth: 2
+
+ doc_tests/test_addplugins/test_addplugins.rst
+ doc_tests/test_coverage_html/coverage_html.rst
+ doc_tests/test_doctest_fixtures/doctest_fixtures.rst
+ doc_tests/test_init_plugin/init_plugin.rst
+ doc_tests/test_issue089/unwanted_package.rst
+ doc_tests/test_issue097/plugintest_environment.rst
+ doc_tests/test_issue107/plugin_exceptions.rst
+ doc_tests/test_issue119/empty_plugin.rst
+ doc_tests/test_issue142/errorclass_failure.rst
+ doc_tests/test_issue145/imported_tests.rst
+ doc_tests/test_multiprocess/multiprocess.rst
+ doc_tests/test_restricted_plugin_options/restricted_plugin_options.rst
+ doc_tests/test_selector_plugin/selector_plugin.rst
+ doc_tests/test_allmodules/test_allmodules.rst
+ more_info
+
+Articles, etc
+-------------
+
+* `An Extended Introduction to the nose Unit Testing Framework`_:
+ Titus Brown's excellent article provides a great overview of
+ nose and its uses.
+* `My blog`_
+* `Tweets`_
+
+.. _`An Extended Introduction to the nose Unit Testing Framework` : http://ivory.idyll.org/articles/nose-intro.html
+.. _`My blog` : http://somethingaboutorange.com/mrl/
+.. _`Tweets` : http://twitter.com/jpellerin
\ No newline at end of file
diff --git a/doc/index.html b/doc/index.html
new file mode 100644
index 0000000..cd80895
--- /dev/null
+++ b/doc/index.html
@@ -0,0 +1,8 @@
+
+ Redirecting to nose 0.11 docs
+
+
+
+
%s' % self.context.pop())
+
+ def visit_legend(self, node):
+ raise NotImplementedError, node.astext()
+ self.body.append(self.starttag(node, 'div', CLASS='legend'))
+
+ def depart_legend(self, node):
+ raise NotImplementedError, node.astext()
+ self.body.append('\n')
+
+ def visit_line_block(self, node):
+ self.body.append('\n')
+
+ def depart_line_block(self, node):
+ self.body.append('\n')
+
+ def visit_line(self, node):
+ pass
+
+ def depart_line(self, node):
+ self.body.append('\n.br\n')
+
+ def visit_list_item(self, node):
+ # man 7 man argues to use ".IP" instead of ".TP"
+ self.body.append('\n.IP %s %d\n' % (
+ self._list_char[-1].next(),
+ self._list_char[-1].get_width(),) )
+
+ def depart_list_item(self, node):
+ pass
+
+ def visit_literal(self, node):
+ self.body.append(self.defs['literal'][0])
+
+ def depart_literal(self, node):
+ self.body.append(self.defs['literal'][1])
+
+ def visit_literal_block(self, node):
+ self.body.append(self.defs['literal_block'][0])
+
+ def depart_literal_block(self, node):
+ self.body.append(self.defs['literal_block'][1])
+
+ def visit_meta(self, node):
+ raise NotImplementedError, node.astext()
+ self.head.append(self.emptytag(node, 'meta', **node.attributes))
+
+ def depart_meta(self, node):
+ pass
+
+ def visit_note(self, node):
+ self.visit_admonition(node, 'note')
+
+ def depart_note(self, node):
+ self.depart_admonition()
+
+ def indent(self, by=0.5):
+ # if we are in a section ".SH" there already is a .RS
+ #self.body.append('\n[[debug: listchar: %r]]\n' % map(repr, self._list_char))
+ #self.body.append('\n[[debug: indent %r]]\n' % self._indent)
+ step = self._indent[-1]
+ self._indent.append(by)
+ self.body.append(self.defs['indent'][0] % step)
+
+ def dedent(self, name=''):
+ #self.body.append('\n[[debug: dedent %s %r]]\n' % (name, self._indent))
+ self._indent.pop()
+ self.body.append(self.defs['indent'][1])
+
+ def visit_option_list(self, node):
+ self.indent(OPTION_LIST_INDENT)
+
+ def depart_option_list(self, node):
+ self.dedent()
+
+ def visit_option_list_item(self, node):
+ # one item of the list
+ self.body.append(self.defs['option_list_item'][0])
+
+ def depart_option_list_item(self, node):
+ self.body.append(self.defs['option_list_item'][1])
+
+ def visit_option_group(self, node):
+ # as one option could have several forms it is a group
+ # options without parameter bold only, .B, -v
+ # options with parameter bold italic, .BI, -f file
+
+ # we do not know if .B or .BI
+ self.context.append('.B') # blind guess
+ self.context.append(len(self.body)) # to be able to insert later
+ self.context.append(0) # option counter
+
+ def depart_option_group(self, node):
+ self.context.pop() # the counter
+ start_position = self.context.pop()
+ text = self.body[start_position:]
+ del self.body[start_position:]
+ self.body.append('\n%s%s' % (self.context.pop(), ''.join(text)))
+
+ def visit_option(self, node):
+ # each form of the option will be presented separately
+ if self.context[-1]>0:
+ self.body.append(' ,')
+ if self.context[-3] == '.BI':
+ self.body.append('\\')
+ self.body.append(' ')
+
+ def depart_option(self, node):
+ self.context[-1] += 1
+
+ def visit_option_string(self, node):
+ # do not know if .B or .BI
+ pass
+
+ def depart_option_string(self, node):
+ pass
+
+ def visit_option_argument(self, node):
+ self.context[-3] = '.BI' # bold/italic alternate
+ if node['delimiter'] != ' ':
+ self.body.append('\\fn%s ' % node['delimiter'] )
+ elif self.body[len(self.body)-1].endswith('='):
+ # a blank only means no blank in output, just changing font
+ self.body.append(' ')
+ else:
+ # backslash blank blank
+ self.body.append('\\ ')
+
+ def depart_option_argument(self, node):
+ pass
+
+ def visit_organization(self, node):
+ self._docinfo['organization'] = node.astext()
+ raise nodes.SkipNode
+
+ def depart_organization(self, node):
+ pass
+
+ def visit_paragraph(self, node):
+ # BUG every but the first paragraph in a list must be intended
+ # TODO .PP or new line
+ return
+
+ def depart_paragraph(self, node):
+ # TODO .PP or an empty line
+ if not self._in_entry:
+ self.body.append('\n\n')
+
+ def visit_problematic(self, node):
+ self.body.append(self.defs['problematic'][0])
+
+ def depart_problematic(self, node):
+ self.body.append(self.defs['problematic'][1])
+
+ def visit_raw(self, node):
+ if node.get('format') == 'manpage':
+ self.body.append(node.astext())
+ # Keep non-manpage raw text out of output:
+ raise nodes.SkipNode
+
+ def visit_reference(self, node):
+ """E.g. link or email address."""
+ self.body.append(self.defs['reference'][0])
+
+ def depart_reference(self, node):
+ self.body.append(self.defs['reference'][1])
+
+ def visit_revision(self, node):
+ self.visit_docinfo_item(node, 'revision')
+
+ def depart_revision(self, node):
+ self.depart_docinfo_item()
+
+ def visit_row(self, node):
+ self._active_table.new_row()
+
+ def depart_row(self, node):
+ pass
+
+ def visit_section(self, node):
+ self.section_level += 1
+
+ def depart_section(self, node):
+ self.section_level -= 1
+
+ def visit_status(self, node):
+ raise NotImplementedError, node.astext()
+ self.visit_docinfo_item(node, 'status', meta=None)
+
+ def depart_status(self, node):
+ self.depart_docinfo_item()
+
+ def visit_strong(self, node):
+ self.body.append(self.defs['strong'][1])
+
+ def depart_strong(self, node):
+ self.body.append(self.defs['strong'][1])
+
+ def visit_substitution_definition(self, node):
+ """Internal only."""
+ raise nodes.SkipNode
+
+ def visit_substitution_reference(self, node):
+ self.unimplemented_visit(node)
+
+ def visit_subtitle(self, node):
+ self._docinfo["subtitle"] = node.astext()
+ raise nodes.SkipNode
+
+ def visit_system_message(self, node):
+ # TODO add report_level
+ #if node['level'] < self.document.reporter['writer'].report_level:
+ # Level is too low to display:
+ # raise nodes.SkipNode
+ self.body.append('\.SH system-message\n')
+ attr = {}
+ backref_text = ''
+ if node.hasattr('id'):
+ attr['name'] = node['id']
+ if node.hasattr('line'):
+ line = ', line %s' % node['line']
+ else:
+ line = ''
+ self.body.append('System Message: %s/%s (%s:%s)\n'
+ % (node['type'], node['level'], node['source'], line))
+
+ def depart_system_message(self, node):
+ self.body.append('\n')
+
+ def visit_table(self, node):
+ self._active_table = Table()
+
+ def depart_table(self, node):
+ self.body.append(self._active_table.astext())
+ self._active_table = None
+
+ def visit_target(self, node):
+ self.body.append(self.comment('visit_target'))
+ #self.body.append(self.defs['target'][0])
+ #self.body.append(node['refuri'])
+
+ def depart_target(self, node):
+ self.body.append(self.comment('depart_target'))
+ #self.body.append(self.defs['target'][1])
+
+ def visit_tbody(self, node):
+ pass
+
+ def depart_tbody(self, node):
+ pass
+
+ def visit_term(self, node):
+ self.body.append(self.defs['term'][0])
+
+ def depart_term(self, node):
+ self.body.append(self.defs['term'][1])
+
+ def visit_tgroup(self, node):
+ pass
+
+ def depart_tgroup(self, node):
+ pass
+
+ def visit_compound(self, node):
+ pass
+
+ def depart_compound(self, node):
+ pass
+
+ def visit_thead(self, node):
+ raise NotImplementedError, node.astext()
+ self.write_colspecs()
+ self.body.append(self.context.pop()) # '\n'
+ # There may or may not be a ; this is for
to use:
+ self.context.append('')
+ self.body.append(self.starttag(node, 'thead', valign='bottom'))
+
+ def depart_thead(self, node):
+ raise NotImplementedError, node.astext()
+ self.body.append('\n')
+
+ def visit_tip(self, node):
+ self.visit_admonition(node, 'tip')
+
+ def depart_tip(self, node):
+ self.depart_admonition()
+
+ def visit_title(self, node):
+ if isinstance(node.parent, nodes.topic):
+ self.body.append(self.comment('topic-title'))
+ elif isinstance(node.parent, nodes.sidebar):
+ self.body.append(self.comment('sidebar-title'))
+ elif isinstance(node.parent, nodes.admonition):
+ self.body.append(self.comment('admonition-title'))
+ elif self.section_level == 0:
+ # document title for .TH
+ self._docinfo['title'] = node.astext()
+ raise nodes.SkipNode
+ elif self.section_level == 1:
+ self._docinfo['subtitle'] = node.astext()
+ raise nodes.SkipNode
+ elif self.section_level == 2:
+ self.body.append('\n.SH ')
+ else:
+ self.body.append('\n.SS ')
+
+ def depart_title(self, node):
+ self.body.append('\n')
+
+ def visit_title_reference(self, node):
+ """inline citation reference"""
+ self.body.append(self.defs['title_reference'][0])
+
+ def depart_title_reference(self, node):
+ self.body.append(self.defs['title_reference'][1])
+
+ def visit_topic(self, node):
+ self.body.append(self.comment('topic: '+node.astext()))
+ raise nodes.SkipNode
+ ##self.topic_class = node.get('class')
+
+ def depart_topic(self, node):
+ ##self.topic_class = ''
+ pass
+
+ def visit_transition(self, node):
+ # .PP Begin a new paragraph and reset prevailing indent.
+ # .sp N leaves N lines of blank space.
+ # .ce centers the next line
+ self.body.append('\n.sp\n.ce\n----\n')
+
+ def depart_transition(self, node):
+ self.body.append('\n.ce 0\n.sp\n')
+
+ def visit_version(self, node):
+ self._docinfo["version"] = node.astext()
+ raise nodes.SkipNode
+
+ def visit_warning(self, node):
+ self.visit_admonition(node, 'warning')
+
+ def depart_warning(self, node):
+ self.depart_admonition()
+
+ def visit_index(self, node):
+ pass
+
+ def depart_index(self, node):
+ pass
+
+ def visit_desc(self, node):
+ pass
+
+ def depart_desc(self, node):
+ pass
+
+ def visit_desc_signature(self, node):
+ # .. cmdoption makes options look like this
+ self.body.append('\n')
+ self.body.append('.TP')
+ self.body.append('\n')
+
+ def depart_desc_signature(self, node):
+ pass
+
+ def visit_desc_name(self, node):
+ self.body.append(r'\fB') # option name
+
+ def depart_desc_name(self, node):
+ self.body.append(r'\fR')
+
+ def visit_desc_addname(self, node):
+ self.body.append(r'\fR')
+
+ def depart_desc_addname(self, node):
+ # self.body.append(r'\fR')
+ pass
+
+ def visit_desc_content(self, node):
+ self.body.append('\n') # option help
+
+ def depart_desc_content(self, node):
+ pass
+
+ def unimplemented_visit(self, node):
+ pass
+
+# vim: set et ts=4 ai :
diff --git a/doc/manpage.pyc b/doc/manpage.pyc
new file mode 100644
index 0000000..76c43f6
Binary files /dev/null and b/doc/manpage.pyc differ
diff --git a/doc/more_info.rst b/doc/more_info.rst
new file mode 100644
index 0000000..a37aeb2
--- /dev/null
+++ b/doc/more_info.rst
@@ -0,0 +1,48 @@
+About the name
+==============
+
+* nose is the least silly short synonym for discover in the dictionary.com
+ thesaurus that does not contain the word 'spy.'
+* Pythons have noses
+* The nose knows where to find your tests
+* Nose Obviates Suite Employment
+
+Contact the author
+==================
+
+You can email me at jpellerin+nose at gmail dot com.
+
+To report bugs, ask questions, or request features, please use the *issues*
+tab at the Google code site: http://code.google.com/p/python-nose/issues/list.
+Patches are welcome!
+
+Similar test runners
+====================
+
+nose was inspired mainly by py.test_, which is a great test runner, but
+formerly was not all that easy to install, and is not based on unittest.
+
+Test suites written for use with nose should work equally well with py.test,
+and vice versa, except for the differences in output capture and command line
+arguments for the respective tools.
+
+.. _py.test: http://codespeak.net/py/current/doc/test.html
+
+License and copyright
+=====================
+
+nose is copyright Jason Pellerin 2005-2009
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\ No newline at end of file
diff --git a/doc/news.rst b/doc/news.rst
new file mode 100644
index 0000000..089b935
--- /dev/null
+++ b/doc/news.rst
@@ -0,0 +1,4 @@
+What's new
+==========
+
+.. include :: ../CHANGELOG
diff --git a/doc/plugins.rst b/doc/plugins.rst
new file mode 100644
index 0000000..4053b8c
--- /dev/null
+++ b/doc/plugins.rst
@@ -0,0 +1,70 @@
+Extending and customizing nose with plugins
+===========================================
+
+nose has plugin hooks for loading, running, watching and reporting on tests and
+test runs. If you don't like the default collection scheme, or it doesn't suit
+the layout of your project, or you need reports in a format different from the
+unittest standard, or you need to collect some additional information about
+tests (like code coverage or profiling data), you can write a plugin to do so.
+See the section on `writing plugins`_ for more.
+
+nose also comes with a number of built-in plugins, such as:
+
+* Output capture
+
+ Unless called with the ``-s`` (``--nocapture``) switch, nose will capture
+ stdout during each test run, and print the captured output only for tests
+ that fail or have errors. The captured output is printed immediately
+ following the error or failure output for the test. (Note that output in
+ teardown methods is captured, but can't be output with failing tests, because
+ teardown has not yet run at the time of the failure.)
+
+* Assert introspection
+
+ When run with the ``-d`` (``--detailed-errors``) switch, nose will try to
+ output additional information about the assert expression that failed with
+ each failing test. Currently, this means that names in the assert expression
+ will be expanded into any values found for them in the locals or globals in
+ the frame in which the expression executed.
+
+ In other words, if you have a test like::
+
+ def test_integers():
+ a = 2
+ assert a == 4, "assert 2 is 4"
+
+ You will get output like::
+
+ File "/path/to/file.py", line XX, in test_integers:
+ assert a == 4, "assert 2 is 4"
+ AssertionError: assert 2 is 4
+ >> assert 2 == 4, "assert 2 is 4"
+
+ Please note that dotted names are not expanded, and callables are not called
+ in the expansion.
+
+See below for the rest of the built-in plugins.
+
+Using Builtin plugins
+---------------------
+
+See :doc:`plugins/builtin`
+
+Writing plugins
+---------------
+
+.. toctree ::
+ :maxdepth: 2
+
+ plugins/writing
+ plugins/interface
+ plugins/errorclasses
+ plugins/documenting
+
+Testing plugins
+---------------
+
+.. toctree ::
+ :maxdepth: 2
+
+ plugins/testing
\ No newline at end of file
diff --git a/doc/plugins/allmodules.rst b/doc/plugins/allmodules.rst
new file mode 100644
index 0000000..ad6d034
--- /dev/null
+++ b/doc/plugins/allmodules.rst
@@ -0,0 +1,4 @@
+AllModules: collect tests in all modules
+========================================
+
+.. autoplugin :: nose.plugins.allmodules
\ No newline at end of file
diff --git a/doc/plugins/attrib.rst b/doc/plugins/attrib.rst
new file mode 100644
index 0000000..beaa834
--- /dev/null
+++ b/doc/plugins/attrib.rst
@@ -0,0 +1,4 @@
+Attrib: tag and select tests with attributes
+============================================
+
+.. autoplugin :: nose.plugins.attrib
diff --git a/doc/plugins/builtin.rst b/doc/plugins/builtin.rst
new file mode 100644
index 0000000..8d2147f
--- /dev/null
+++ b/doc/plugins/builtin.rst
@@ -0,0 +1,30 @@
+Batteries included: builtin nose plugins
+========================================
+
+nose includes a number of builtin plugins that can make testing faster and easier.
+
+.. note ::
+
+ nose 0.11.2 includes a change to default plugin loading. Now, a 3rd party
+ plugin with *the same name* as a builtin *will be loaded instead*
+ of the builtin plugin.
+
+.. toctree ::
+ :maxdepth: 2
+
+ allmodules
+ attrib
+ capture
+ collect
+ cover
+ debug
+ deprecated
+ doctests
+ failuredetail
+ isolate
+ logcapture
+ multiprocess
+ prof
+ skip
+ testid
+ xunit
diff --git a/doc/plugins/capture.rst b/doc/plugins/capture.rst
new file mode 100644
index 0000000..27a0c2e
--- /dev/null
+++ b/doc/plugins/capture.rst
@@ -0,0 +1,5 @@
+Capture: capture stdout during tests
+====================================
+
+.. autoplugin :: nose.plugins.capture
+
diff --git a/doc/plugins/collect.rst b/doc/plugins/collect.rst
new file mode 100644
index 0000000..011a96d
--- /dev/null
+++ b/doc/plugins/collect.rst
@@ -0,0 +1,4 @@
+Collect: Collect tests quickly
+==============================
+
+.. autoplugin :: nose.plugins.collect
\ No newline at end of file
diff --git a/doc/plugins/cover.rst b/doc/plugins/cover.rst
new file mode 100644
index 0000000..e970b2c
--- /dev/null
+++ b/doc/plugins/cover.rst
@@ -0,0 +1,14 @@
+Cover: code coverage
+====================
+
+.. note ::
+
+ Newer versions of coverage contain their own nose plugin which is
+ superior to the builtin plugin. It exposes more of coverage's
+ options and uses coverage's native html output. Depending on the
+ version of coverage installed, the included plugin may override the
+ nose builtin plugin, or be available under a different name. Check
+ ``nosetests --help`` or ``nosetests --plugins`` to find out which
+ coverage plugin is available on your system.
+
+.. autoplugin :: nose.plugins.cover
diff --git a/doc/plugins/debug.rst b/doc/plugins/debug.rst
new file mode 100644
index 0000000..cac67f3
--- /dev/null
+++ b/doc/plugins/debug.rst
@@ -0,0 +1,4 @@
+Debug: drop into pdb on errors or failures
+==========================================
+
+.. autoplugin :: nose.plugins.debug
\ No newline at end of file
diff --git a/doc/plugins/deprecated.rst b/doc/plugins/deprecated.rst
new file mode 100644
index 0000000..ebb8140
--- /dev/null
+++ b/doc/plugins/deprecated.rst
@@ -0,0 +1,4 @@
+Deprecated: mark tests as deprecated
+====================================
+
+.. autoplugin :: nose.plugins.deprecated
diff --git a/doc/plugins/doctests.rst b/doc/plugins/doctests.rst
new file mode 100644
index 0000000..9763765
--- /dev/null
+++ b/doc/plugins/doctests.rst
@@ -0,0 +1,4 @@
+Doctests: run doctests with nose
+================================
+
+.. autoplugin :: nose.plugins.doctests
diff --git a/doc/plugins/documenting.rst b/doc/plugins/documenting.rst
new file mode 100644
index 0000000..c841f76
--- /dev/null
+++ b/doc/plugins/documenting.rst
@@ -0,0 +1,62 @@
+Documenting plugins
+===================
+
+A parable. If a plugin is released on pypi without any documentation, does
+anyone care?
+
+To make it easy to document your plugins, nose includes a `Sphinx`_ extension
+that will automatically generate plugin docs like those for nose's builtin
+plugins. Simply add 'nose.sphinx.pluginopts' to the list of extensions in your
+conf.py::
+
+ extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx',
+ 'nose.sphinx.pluginopts']
+
+Then in your plugin documents, include a title and the ``.. autoplugin``
+directive::
+
+ My Cool Plugin
+ ==============
+
+ .. autoplugin :: package.module.with.plugin
+ :plugin: PluginClass
+
+The ``:plugin:`` option is optional. In most cases, the directive will
+automatically detect which class in the named module is the plugin to be
+documented.
+
+The output of the directive includes the docstring of the plugin module, the
+options defined by the plugin, `autodoc`_ generated for the plugin class, and
+the plugin module source. This is roughly equivalent to::
+
+ My Cool Plugin
+ ==============
+
+ .. automodule :: package.module.with.plugin
+
+ Options
+ -------
+
+ .. cmdoption :: --with-coolness
+
+ Help text of the coolness option.
+
+ .. cmdoption ::
+
+ Plugin
+ -------
+
+ .. autoclass :: package.module.with.plugin.PluginClass
+ :members:
+
+ Source
+ ------
+
+ .. include :: path/to/package/module/with/plugin.py
+ :literal:
+
+Document your plugins! Your users might not thank you -- but at least you'll
+*have* some users.
+
+.. _`Sphinx` : http://sphinx.pocoo.org/
+.. _`autodoc`: http://sphinx.pocoo.org/ext/autodoc.html
\ No newline at end of file
diff --git a/doc/plugins/errorclasses.rst b/doc/plugins/errorclasses.rst
new file mode 100644
index 0000000..1e758f4
--- /dev/null
+++ b/doc/plugins/errorclasses.rst
@@ -0,0 +1,7 @@
+.. automodule :: nose.plugins.errorclass
+
+Error class methods
+-------------------
+
+.. autoclass :: nose.plugins.errorclass.ErrorClassPlugin
+ :members:
diff --git a/doc/plugins/failuredetail.rst b/doc/plugins/failuredetail.rst
new file mode 100644
index 0000000..5a3d0df
--- /dev/null
+++ b/doc/plugins/failuredetail.rst
@@ -0,0 +1,4 @@
+Failure Detail: introspect asserts
+==================================
+
+.. autoplugin :: nose.plugins.failuredetail
diff --git a/doc/plugins/interface.rst b/doc/plugins/interface.rst
new file mode 100644
index 0000000..cab8b9d
--- /dev/null
+++ b/doc/plugins/interface.rst
@@ -0,0 +1,122 @@
+
+.. _plugin-interface:
+
+Plugin Interface
+================
+
+Plugin base class
+-----------------
+
+.. autoclass :: nose.plugins.base.Plugin
+ :members:
+
+Nose plugin API
+---------------
+
+Plugins may implement any or all of the methods documented below. Please note
+that they *must not* subclass `IPluginInterface`; `IPluginInterface` is only a
+description of the plugin API.
+
+When plugins are called, the first plugin that implements a method and returns
+a non-None value wins, and plugin processing ends. The exceptions to this are
+methods marked as `generative` or `chainable`. `generative` methods combine
+the output of all plugins that respond with an iterable into a single
+flattened iterable response (a generator, really). `chainable` methods pass
+the results of calling plugin A as the input to plugin B, where the positions
+in the chain are determined by the plugin sort order, which is in order by
+`score` descending.
+
+In general, plugin methods correspond directly to methods of
+`nose.selector.Selector`, `nose.loader.TestLoader` and
+`nose.result.TextTestResult` are called by those methods when they are
+called. In some cases, the plugin hook doesn't neatly match the method in
+which it is called; for those, the documentation for the hook will tell you
+where in the test process it is called.
+
+Plugin hooks fall into four broad categories: selecting and loading tests,
+handling errors raised by tests, preparing objects used in the testing
+process, and watching and reporting on test results.
+
+Selecting and loading tests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To alter test selection behavior, implement any necessary `want*` methods as
+outlined below. Keep in mind, though, that when your plugin returns True from
+a `want*` method, you will send the requested object through the normal test
+collection process. If the object represents something from which normal tests
+can't be collected, you must also implement a loader method to load the tests.
+
+Examples:
+
+* The builtin :doc:`doctests plugin ` implements `wantFile` to
+ enable loading of doctests from files that are not python modules. It
+ also implements `loadTestsFromModule` to load doctests from
+ python modules, and `loadTestsFromFile` to load tests from the
+ non-module files selected by `wantFile`.
+
+* The builtin :doc:`attrib plugin ` implements `wantFunction` and
+ `wantMethod` so that it can reject tests that don't match the
+ specified attributes.
+
+Handling errors
+^^^^^^^^^^^^^^^
+
+To alter error handling behavior -- for instance to catch a certain class of
+exception and handle it differently from the normal error or failure handling
+-- you should subclass :class:`nose.plugins.errorclass.ErrorClassPlugin`. See
+:doc:`the section on ErrorClass plugins ` for more details.
+
+Examples:
+
+* The builtin :doc:`skip ` and :doc:`deprecated ` plugins are
+ ErrorClass plugins.
+
+
+Preparing test objects
+^^^^^^^^^^^^^^^^^^^^^^
+
+To alter, get a handle on, or replace test framework objects such as the
+loader, result, runner, and test cases, use the appropriate prepare methods.
+The simplest reason to use prepare is in the case that you need to use an
+object yourself. For example, the isolate plugin implements `prepareTestLoader`
+so that it can use the loader later on to load tests. If you return a value
+from a prepare method, that value will be used in place of the loader, result,
+runner or test case, depending on which prepare method you use. Be aware that
+when replacing test cases, you are replacing the *entire* test case -- including
+the whole `run(result)` method of the `unittest.TestCase` -- so if you want
+normal unittest test result reporting, you must implement the same calls to
+result as `unittest.TestCase.run`.
+
+Examples:
+
+* The builtin :doc:`isolate plugin ` implements `prepareTestLoader`
+ but does not replace the test loader.
+
+* The builtin :doc:`profile plugin ` implements `prepareTest` and does
+ replace the top-level test case by returning the case wrapped in
+ the profiler function.
+
+Watching or reporting on tests
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To record information about tests or other modules imported during
+the testing process, output additional reports, or entirely change
+test report output, implement any of the methods outlined below that
+correspond to TextTestResult methods.
+
+Examples:
+
+* The builtin :doc:`cover plugin ` implements `begin` and `report` to
+ capture and report code coverage metrics for all or selected modules
+ loaded during testing.
+
+* The builtin :doc:`profile plugin ` implements `begin`, `prepareTest`
+ and `report` to record and output profiling information. In this
+ case, the plugin's `prepareTest` method constructs a function that
+ runs the test through the hotshot profiler's runcall() method.
+
+Plugin interface methods
+------------------------
+
+.. autoclass :: nose.plugins.base.IPluginInterface
+ :members:
\ No newline at end of file
diff --git a/doc/plugins/isolate.rst b/doc/plugins/isolate.rst
new file mode 100644
index 0000000..94b5641
--- /dev/null
+++ b/doc/plugins/isolate.rst
@@ -0,0 +1,4 @@
+Isolate: protect tests from (some) side-effects
+-----------------------------------------------
+
+.. autoplugin :: nose.plugins.isolate
\ No newline at end of file
diff --git a/doc/plugins/logcapture.rst b/doc/plugins/logcapture.rst
new file mode 100644
index 0000000..4bf09c3
--- /dev/null
+++ b/doc/plugins/logcapture.rst
@@ -0,0 +1,4 @@
+Logcapture: capture logging during tests
+========================================
+
+.. autoplugin :: nose.plugins.logcapture
\ No newline at end of file
diff --git a/doc/plugins/multiprocess.rst b/doc/plugins/multiprocess.rst
new file mode 100644
index 0000000..c9f4aa7
--- /dev/null
+++ b/doc/plugins/multiprocess.rst
@@ -0,0 +1,5 @@
+------------------------------
+Multiprocess: parallel testing
+------------------------------
+
+.. autoplugin :: nose.plugins.multiprocess
diff --git a/doc/plugins/other.rst b/doc/plugins/other.rst
new file mode 100644
index 0000000..47490c3
--- /dev/null
+++ b/doc/plugins/other.rst
@@ -0,0 +1,6 @@
+Third-party nose plugins
+------------------------
+
+Visit http://nose-plugins.jottit.com/ for a list of third-party nose plugins
+compatible with nose 0.9 through 0.11. If you have released a plugin that you
+don't see in the list, please add it!
diff --git a/doc/plugins/prof.rst b/doc/plugins/prof.rst
new file mode 100644
index 0000000..f778942
--- /dev/null
+++ b/doc/plugins/prof.rst
@@ -0,0 +1,4 @@
+Prof: enable profiling using the hotshot profiler
+=================================================
+
+.. autoplugin :: nose.plugins.prof
diff --git a/doc/plugins/skip.rst b/doc/plugins/skip.rst
new file mode 100644
index 0000000..07f9207
--- /dev/null
+++ b/doc/plugins/skip.rst
@@ -0,0 +1,5 @@
+Skip: mark tests as skipped
+===========================
+
+.. autoplugin :: nose.plugins.skip
+ :plugin: Skip
\ No newline at end of file
diff --git a/doc/plugins/testid.rst b/doc/plugins/testid.rst
new file mode 100644
index 0000000..377e2e7
--- /dev/null
+++ b/doc/plugins/testid.rst
@@ -0,0 +1,4 @@
+Testid: add a test id to each test name output
+==============================================
+
+.. autoplugin :: nose.plugins.testid
diff --git a/doc/plugins/testing.rst b/doc/plugins/testing.rst
new file mode 100644
index 0000000..1e17fb2
--- /dev/null
+++ b/doc/plugins/testing.rst
@@ -0,0 +1,7 @@
+.. automodule :: nose.plugins.plugintest
+
+PluginTester methods
+--------------------
+
+.. autoclass :: nose.plugins.plugintest.PluginTester
+ :members:
\ No newline at end of file
diff --git a/doc/plugins/writing.rst b/doc/plugins/writing.rst
new file mode 100644
index 0000000..ed73b9f
--- /dev/null
+++ b/doc/plugins/writing.rst
@@ -0,0 +1 @@
+.. automodule :: nose.plugins
\ No newline at end of file
diff --git a/doc/plugins/xunit.rst b/doc/plugins/xunit.rst
new file mode 100644
index 0000000..5602e5d
--- /dev/null
+++ b/doc/plugins/xunit.rst
@@ -0,0 +1,4 @@
+Xunit: output test results in xunit format
+==========================================
+
+.. autoplugin :: nose.plugins.xunit
\ No newline at end of file
diff --git a/doc/rtd-requirements.txt b/doc/rtd-requirements.txt
new file mode 100644
index 0000000..2872958
--- /dev/null
+++ b/doc/rtd-requirements.txt
@@ -0,0 +1,3 @@
+# requirements file for Read The Docs
+# http://readthedocs.org/docs/nose/
+sphinx>=1.0
diff --git a/doc/setuptools_integration.rst b/doc/setuptools_integration.rst
new file mode 100644
index 0000000..b886e76
--- /dev/null
+++ b/doc/setuptools_integration.rst
@@ -0,0 +1,38 @@
+Setuptools integration
+======================
+
+.. warning :: Please note that when run under the setuptools test command,
+ many plugins will not be available, including the builtin
+ coverage and profiler plugins. If you want to access to all
+ available plugins, use the :doc:`nosetests `
+ command instead.
+
+nose may be used with the setuptools_ test command. Simply specify
+nose.collector as the test suite in your setup file::
+
+ setup (
+ # ...
+ test_suite = 'nose.collector'
+ )
+
+Then to find and run tests, you can run::
+
+ python setup.py test
+
+When running under setuptools, you can configure nose settings via the
+environment variables detailed in the nosetests script usage message,
+or the setup.cfg, ~/.noserc or ~/.nose.cfg config files.
+
+`nosetests` command
+-------------------
+
+nose also includes its own setuptools command, ``nosetests``, that provides
+support for all plugins and command line options. It works just like the
+``test`` command::
+
+ python setup.py nosetests
+
+See :doc:`api/commands` for more information about the ``nosetests`` command.
+
+.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
+
diff --git a/doc/testing.rst b/doc/testing.rst
new file mode 100644
index 0000000..42bf6fe
--- /dev/null
+++ b/doc/testing.rst
@@ -0,0 +1,55 @@
+Testing with nose
+=================
+
+Writing tests is easier
+-----------------------
+
+nose collects tests from :class:`unittest.TestCase` subclasses, of course. But
+you can also write simple test functions, as well as test classes that are
+*not* subclasses of :class:`unittest.TestCase`. nose also supplies a number of
+helpful functions for writing timed tests, testing for exceptions, and other
+common use cases. See :doc:`writing_tests` and :doc:`testing_tools` for more.
+
+Running tests is easier
+-----------------------
+
+nose collects tests automatically, as long as you follow some simple
+guidelines for organizing your library and test code. There's no need
+to manually collect test cases into test suites. Running tests is
+responsive, since nose begins running tests as soon as the first test
+module is loaded. See :doc:`finding_tests` for more.
+
+Setting up your test environment is easier
+------------------------------------------
+
+nose supports fixtures at the package, module, class, and test case
+level, so expensive initialization can be done as infrequently as
+possible. See :ref:`fixtures` for more.
+
+Doing what you want to do is easier
+-----------------------------------
+
+nose comes with a number of :doc:`builtin plugins ` to help
+you with output capture, error introspection, code coverage, doctests, and
+more. It also comes with plugin hooks for loading, running, watching and
+reporting on tests and test runs. If you don't like the default collection
+scheme, or it doesn't suit the layout of your project, or you need reports in
+a format different from the unittest standard, or you need to collect some
+additional information about tests (like code coverage or profiling data), you
+can write a plugin to make nose do what you want. See the section on
+:doc:`plugins/writing` for more. There are also many
+`third-party nose plugins `_ available.
+
+Details
+-------
+
+.. toctree ::
+ :maxdepth: 2
+
+ usage
+ writing_tests
+ finding_tests
+ testing_tools
+ plugins/builtin
+ plugins/other
+ setuptools_integration
diff --git a/doc/testing_tools.rst b/doc/testing_tools.rst
new file mode 100644
index 0000000..45e2958
--- /dev/null
+++ b/doc/testing_tools.rst
@@ -0,0 +1,11 @@
+Testing tools
+-------------
+
+The nose.tools module provides a number of testing aids that you may
+find useful, including decorators for restricting test execution time
+and testing for exceptions, and all of the same assertX methods found
+in `unittest.TestCase` (only spelled in pep08 fashion, so `assert_equal`
+rather than `assertEqual`).
+
+.. automodule :: nose.tools
+ :members:
\ No newline at end of file
diff --git a/doc/usage.rst b/doc/usage.rst
new file mode 100644
index 0000000..11e682b
--- /dev/null
+++ b/doc/usage.rst
@@ -0,0 +1,42 @@
+Basic usage
+-----------
+
+Use the nosetests script (after installation by setuptools)::
+
+ nosetests [options] [(optional) test files or directories]
+
+In addition to passing command-line options, you may also put configuration
+options in a .noserc or nose.cfg file in your home directory. These are
+standard .ini-style config files. Put your nosetests configuration in a
+[nosetests] section, with the -- prefix removed::
+
+ [nosetests]
+ verbosity=3
+ with-doctest=1
+
+There are several other ways to use the nose test runner besides the
+`nosetests` script. You may use nose in a test script::
+
+ import nose
+ nose.main()
+
+If you don't want the test script to exit with 0 on success and 1 on failure
+(like unittest.main), use nose.run() instead::
+
+ import nose
+ result = nose.run()
+
+`result` will be true if the test run succeeded, or false if any test failed
+or raised an uncaught exception. Lastly, you can run nose.core directly, which
+will run nose.main()::
+
+ python /path/to/nose/core.py
+
+Please see the usage message for the nosetests script for information
+about how to control which tests nose runs, which plugins are loaded,
+and the test output.
+
+Extended usage
+^^^^^^^^^^^^^^
+
+.. autohelp ::
diff --git a/doc/writing_tests.rst b/doc/writing_tests.rst
new file mode 100644
index 0000000..d2418bd
--- /dev/null
+++ b/doc/writing_tests.rst
@@ -0,0 +1,172 @@
+Writing tests
+-------------
+
+As with py.test_, nose tests need not be subclasses of
+:class:`unittest.TestCase`. Any function or class that matches the configured
+testMatch regular expression (``(?:^|[\\b_\\.-])[Tt]est)`` by default -- that
+is, has test or Test at a word boundary or following a - or _) and lives in a
+module that also matches that expression will be run as a test. For the sake
+of compatibility with legacy unittest test cases, nose will also load tests
+from :class:`unittest.TestCase` subclasses just like unittest does. Like
+py.test, nose runs functional tests in the order in which they appear in the
+module file. TestCase-derived tests and other test classes are run in
+alphabetical order.
+
+.. _py.test: http://codespeak.net/py/current/doc/test.html
+
+.. _fixtures:
+
+Fixtures
+========
+
+nose supports fixtures (setup and teardown methods) at the package,
+module, class, and test level. As with py.test or unittest fixtures,
+setup always runs before any test (or collection of tests for test
+packages and modules); teardown runs if setup has completed
+successfully, regardless of the status of the test run. For more detail
+on fixtures at each level, see below.
+
+Test packages
+=============
+
+nose allows tests to be grouped into test packages. This allows
+package-level setup; for instance, if you need to create a test database
+or other data fixture for your tests, you may create it in package setup
+and remove it in package teardown once per test run, rather than having to
+create and tear it down once per test module or test case.
+
+To create package-level setup and teardown methods, define setup and/or
+teardown functions in the ``__init__.py`` of a test package. Setup methods may
+be named `setup`, `setup_package`, `setUp`, or `setUpPackage`; teardown may
+be named `teardown`, `teardown_package`, `tearDown` or `tearDownPackage`.
+Execution of tests in a test package begins as soon as the first test
+module is loaded from the test package.
+
+Test modules
+============
+
+A test module is a python module that matches the testMatch regular
+expression. Test modules offer module-level setup and teardown; define the
+method `setup`, `setup_module`, `setUp` or `setUpModule` for setup,
+`teardown`, `teardown_module`, or `tearDownModule` for teardown. Execution
+of tests in a test module begins after all tests are collected.
+
+Test classes
+============
+
+A test class is a class defined in a test module that matches testMatch or is
+a subclass of :class:`unittest.TestCase`. All test classes are run the same
+way: Methods in the class that match testMatch are discovered, and a test
+case is constructed to run each method with a fresh instance of the test
+class. Like :class:`unittest.TestCase` subclasses, other test classes can
+define setUp and tearDown methods that will be run before and after each test
+method. Test classes that do not descend from `unittest.TestCase` may also
+include generator methods and class-level fixtures. Class-level setup fixtures
+may be named `setup_class`, `setupClass`, `setUpClass`, `setupAll` or
+`setUpAll`; teardown fixtures may be named `teardown_class`, `teardownClass`,
+`tearDownClass`, `teardownAll` or `tearDownAll`. Class-level setup and teardown
+fixtures must be class methods.
+
+Test functions
+==============
+
+Any function in a test module that matches testMatch will be wrapped in a
+`FunctionTestCase` and run as a test. The simplest possible failing test is
+therefore::
+
+ def test():
+ assert False
+
+And the simplest passing test::
+
+ def test():
+ pass
+
+Test functions may define setup and/or teardown attributes, which will be
+run before and after the test function, respectively. A convenient way to
+do this, especially when several test functions in the same module need
+the same setup, is to use the provided `with_setup` decorator::
+
+ def setup_func():
+ "set up test fixtures"
+
+ def teardown_func():
+ "tear down test fixtures"
+
+ @with_setup(setup_func, teardown_func)
+ def test():
+ "test ..."
+
+For python 2.3 or earlier, add the attributes by calling the decorator
+function like so::
+
+ def test():
+ "test ... "
+ test = with_setup(setup_func, teardown_func)(test)
+
+or by direct assignment::
+
+ test.setup = setup_func
+ test.teardown = teardown_func
+
+Please note that `with_setup` is useful *only* for test functions, not
+for test methods in `unittest.TestCase` subclasses or other test
+classes. For those cases, define `setUp` and `tearDown` methods in the
+class.
+
+Test generators
+===============
+
+nose supports test functions and methods that are generators. A simple
+example from nose's selftest suite is probably the best explanation::
+
+ def test_evens():
+ for i in range(0, 5):
+ yield check_even, i, i*3
+
+ def check_even(n, nn):
+ assert n % 2 == 0 or nn % 2 == 0
+
+This will result in five tests. nose will iterate the generator, creating a
+function test case wrapper for each tuple it yields. As in the example, test
+generators must yield tuples, the first element of which must be a callable
+and the remaining elements the arguments to be passed to the callable.
+
+By default, the test name output for a generated test in verbose mode
+will be the name of the generator function or method, followed by the
+args passed to the yielded callable. If you want to show a different test
+name, set the ``description`` attribute of the yielded callable.
+
+Setup and teardown functions may be used with test generators. However, please
+note that setup and teardown attributes attached to the *generator function*
+will execute only once. To *execute fixtures for each yielded test*, attach
+the setup and teardown attributes to the function that is yielded, or yield a
+callable object instance with setup and teardown attributes.
+
+For example::
+
+ @with_setup(setup_func, teardown_func)
+ def test_generator():
+ # ...
+ yield func, arg, arg # ...
+
+Here, the setup and teardown functions will be executed *once*. Compare to::
+
+ def test_generator():
+ # ...
+ yield func, arg, arg # ...
+
+ @with_setup(setup_func, teardown_func)
+ def func(arg):
+ assert something_about(arg)
+
+In the latter case the setup and teardown functions will execute once for each
+yielded test.
+
+For generator methods, the setUp and tearDown methods of the class (if any)
+will be run before and after each generated test case. The setUp and tearDown
+methods *do not* run before the generator method itself, as this would cause
+setUp to run twice before the first test without an intervening tearDown.
+
+Please note that method generators *are not* supported in `unittest.TestCase`
+subclasses.
\ No newline at end of file
diff --git a/examples/attrib_plugin.py b/examples/attrib_plugin.py
new file mode 100644
index 0000000..c1f8458
--- /dev/null
+++ b/examples/attrib_plugin.py
@@ -0,0 +1,82 @@
+"""
+Examples of test function/method attribute usage with patched nose
+
+Simple syntax (-a, --attr) examples:
+ * nosetests -a status=stable
+ => only test cases with attribute "status" having value "stable"
+
+ * nosetests -a priority=2,status=stable
+ => both attributes must match
+
+ * nosetests -a tags=http
+ => attribute list "tags" must contain value "http" (see test_foobar()
+ below for definition)
+
+ * nosetests -a slow
+ => attribute "slow" must be defined and its value cannot equal to False
+ (False, [], "", etc...)
+
+ * nosetests -a !slow
+ => attribute "slow" must NOT be defined or its value must be equal to False
+
+Eval expression syntax (-A, --eval-attr) examples:
+ * nosetests -A "not slow"
+ * nosetests -A "(priority > 5) and not slow"
+
+This example and the accompanied patch is in public domain, free for any use.
+
+email: mika.eloranta@gmail.com
+
+"""
+
+__author__ = 'Mika Eloranta'
+
+def attr(**kwargs):
+ """Add attributes to a test function/method/class"""
+ def wrap(func):
+ func.__dict__.update(kwargs)
+ return func
+ return wrap
+
+# test function with single attribute
+@attr(priority = 1)
+def test_dummy():
+ print "dummy"
+
+# test function with multiple attributes
+@attr(status = "stable", # simple string attribute
+ slow = True, # attributes can be of any type
+ # (e.g. bool)
+ priority = 1, # ...or int
+ tags = ["http", "pop", "imap"]) # will be run if any of the list items
+ # matches
+def test_foobar():
+ print "foobar"
+
+# another way of adding attributes...
+def test_fluffy():
+ print "fluffy"
+test_fluffy.status = "unstable"
+test_fluffy.slow = True
+test_fluffy.priority = 2
+
+# works for class methods, too
+class TestSomething:
+ @attr(status = "stable", priority = 2)
+ def test_xyz(self):
+ print "xyz"
+
+# class methods "inherit" attributes from the class but can override them
+class TestOverride:
+ value = "class"
+ # run all methods with "nosetests -a value"
+
+ @attr(value = "method")
+ def test_override(self):
+ # run with "nosetests -a value=method"
+ print "override"
+
+ def test_inherit(self):
+ # run with "nosetests -a value=class"
+ print "inherit"
+
diff --git a/examples/html_plugin/htmlplug.py b/examples/html_plugin/htmlplug.py
new file mode 100644
index 0000000..aa1bcb6
--- /dev/null
+++ b/examples/html_plugin/htmlplug.py
@@ -0,0 +1,92 @@
+"""This is a very basic example of a plugin that controls all test
+output. In this case, it formats the output as ugly unstyled html.
+
+Upgrading this plugin into one that uses a template and css to produce
+nice-looking, easily-modifiable html output is left as an exercise for
+the reader who would like to see his or her name in the nose AUTHORS file.
+"""
+import traceback
+from nose.plugins import Plugin
+
+class HtmlOutput(Plugin):
+ """Output test results as ugly, unstyled html.
+ """
+
+ name = 'html-output'
+ score = 2 # run late
+
+ def __init__(self):
+ super(HtmlOutput, self).__init__()
+ self.html = [ '',
+ 'Test output',
+ '' ]
+
+ def addSuccess(self, test):
+ self.html.append('ok')
+
+ def addError(self, test, err):
+ err = self.formatErr(err)
+ self.html.append('ERROR')
+ self.html.append('
')
diff --git a/examples/html_plugin/setup.py b/examples/html_plugin/setup.py
new file mode 100644
index 0000000..3caa08d
--- /dev/null
+++ b/examples/html_plugin/setup.py
@@ -0,0 +1,24 @@
+import sys
+try:
+ import ez_setup
+ ez_setup.use_setuptools()
+except ImportError:
+ pass
+
+from setuptools import setup
+
+setup(
+ name='Example html output plugin',
+ version='0.1',
+ author='Jason Pellerin',
+ author_email = 'jpellerin+nose@gmail.com',
+ description = 'Example nose html output plugin',
+ license = 'GNU LGPL',
+ py_modules = ['htmlplug'],
+ entry_points = {
+ 'nose.plugins.0.10': [
+ 'htmlout = htmlplug:HtmlOutput'
+ ]
+ }
+
+ )
diff --git a/examples/plugin/plug.py b/examples/plugin/plug.py
new file mode 100644
index 0000000..444226d
--- /dev/null
+++ b/examples/plugin/plug.py
@@ -0,0 +1,4 @@
+from nose.plugins import Plugin
+
+class ExamplePlugin(Plugin):
+ pass
diff --git a/examples/plugin/setup.py b/examples/plugin/setup.py
new file mode 100644
index 0000000..4dd5dad
--- /dev/null
+++ b/examples/plugin/setup.py
@@ -0,0 +1,27 @@
+"""
+An example of how to create a simple nose plugin.
+
+"""
+try:
+ import ez_setup
+ ez_setup.use_setuptools()
+except ImportError:
+ pass
+
+from setuptools import setup
+
+setup(
+ name='Example plugin',
+ version='0.1',
+ author='Jason Pellerin',
+ author_email = 'jpellerin+nose@gmail.com',
+ description = 'Example nose plugin',
+ license = 'GNU LGPL',
+ py_modules = ['plug'],
+ entry_points = {
+ 'nose.plugins.0.10': [
+ 'example = plug:ExamplePlugin'
+ ]
+ }
+
+ )
diff --git a/functional_tests/doc_tests/test_addplugins/support/test.py b/functional_tests/doc_tests/test_addplugins/support/test.py
new file mode 100644
index 0000000..f174823
--- /dev/null
+++ b/functional_tests/doc_tests/test_addplugins/support/test.py
@@ -0,0 +1,2 @@
+def test():
+ pass
diff --git a/functional_tests/doc_tests/test_addplugins/support/test.pyc b/functional_tests/doc_tests/test_addplugins/support/test.pyc
new file mode 100644
index 0000000..712c5ea
Binary files /dev/null and b/functional_tests/doc_tests/test_addplugins/support/test.pyc differ
diff --git a/functional_tests/doc_tests/test_addplugins/test_addplugins.rst b/functional_tests/doc_tests/test_addplugins/test_addplugins.rst
new file mode 100644
index 0000000..8e8da91
--- /dev/null
+++ b/functional_tests/doc_tests/test_addplugins/test_addplugins.rst
@@ -0,0 +1,80 @@
+Using custom plugins without setuptools
+---------------------------------------
+
+If you have one or more custom plugins that you'd like to use with nose, but
+can't or don't want to register that plugin as a setuptools entrypoint, you
+can use the ``addplugins`` keyword argument to :func:`nose.core.main` or
+:func:`nose.core.run` to make the plugins available.
+
+To do this you would construct a launcher script for nose, something like::
+
+ from nose import main
+ from yourpackage import YourPlugin, YourOtherPlugin
+
+ if __name__ == '__main__':
+ nose.main(addplugins=[YourPlugin(), YourOtherPlugin()])
+
+Here's an example. Say that you don't like the fact that the collect-only
+plugin outputs 'ok' for each test it finds; instead you want it to output
+'maybe.' You could modify the plugin itself, or instead, create a Maybe plugin
+that transforms the output into your desired shape.
+
+Without the plugin, we get 'ok.'
+
+>>> import os
+>>> support = os.path.join(os.path.dirname(__file__), 'support')
+>>> from nose.plugins.plugintest import run_buffered as run
+>>> argv = [__file__, '-v', support] # --collect-only
+>>> run(argv=argv)
+test.test ... ok
+
+----------------------------------------------------------------------
+Ran 1 test in ...s
+
+OK
+
+Without '-v', we get a dot.
+
+>>> run(argv=[__file__, support])
+.
+----------------------------------------------------------------------
+Ran 1 test in ...s
+
+OK
+
+The plugin is simple. It captures and wraps the test result output stream and
+replaces 'ok' with 'maybe' and '.' with '?'.
+
+>>> from nose.plugins.base import Plugin
+>>> class Maybe(Plugin):
+... def setOutputStream(self, stream):
+... self.stream = stream
+... return self
+... def flush(self):
+... self.stream.flush()
+... def writeln(self, out=""):
+... self.write(out + "\n")
+... def write(self, out):
+... if out == "ok\n":
+... out = "maybe\n"
+... elif out == ".":
+... out = "?"
+... self.stream.write(out)
+
+To activate the plugin, we pass an instance in the addplugins list.
+
+>>> run(argv=argv + ['--with-maybe'], addplugins=[Maybe()])
+test.test ... maybe
+
+----------------------------------------------------------------------
+Ran 1 test in ...s
+
+OK
+
+>>> run(argv=[__file__, support, '--with-maybe'], addplugins=[Maybe()])
+?
+----------------------------------------------------------------------
+Ran 1 test in ...s
+
+OK
+
diff --git a/functional_tests/doc_tests/test_allmodules/support/mod.py b/functional_tests/doc_tests/test_allmodules/support/mod.py
new file mode 100644
index 0000000..e136d56
--- /dev/null
+++ b/functional_tests/doc_tests/test_allmodules/support/mod.py
@@ -0,0 +1,5 @@
+def test():
+ pass
+
+def test_fails():
+ assert False, "This test fails"
diff --git a/functional_tests/doc_tests/test_allmodules/support/mod.pyc b/functional_tests/doc_tests/test_allmodules/support/mod.pyc
new file mode 100644
index 0000000..a53311a
Binary files /dev/null and b/functional_tests/doc_tests/test_allmodules/support/mod.pyc differ
diff --git a/functional_tests/doc_tests/test_allmodules/support/test.py b/functional_tests/doc_tests/test_allmodules/support/test.py
new file mode 100644
index 0000000..f174823
--- /dev/null
+++ b/functional_tests/doc_tests/test_allmodules/support/test.py
@@ -0,0 +1,2 @@
+def test():
+ pass
diff --git a/functional_tests/doc_tests/test_allmodules/support/test.pyc b/functional_tests/doc_tests/test_allmodules/support/test.pyc
new file mode 100644
index 0000000..8556899
Binary files /dev/null and b/functional_tests/doc_tests/test_allmodules/support/test.pyc differ
diff --git a/functional_tests/doc_tests/test_allmodules/test_allmodules.rst b/functional_tests/doc_tests/test_allmodules/test_allmodules.rst
new file mode 100644
index 0000000..b541987
--- /dev/null
+++ b/functional_tests/doc_tests/test_allmodules/test_allmodules.rst
@@ -0,0 +1,67 @@
+Finding tests in all modules
+============================
+
+Normally, nose only looks for tests in modules whose names match testMatch. By
+default that means modules with 'test' or 'Test' at the start of the name
+after an underscore (_) or dash (-) or other non-alphanumeric character.
+
+If you want to collect tests from all modules, use the ``--all-modules``
+command line argument to activate the :doc:`allmodules plugin
+<../../plugins/allmodules>`.
+
+.. Note ::
+
+ The function :func:`nose.plugins.plugintest.run` reformats test result
+ output to remove timings, which will vary from run to run, and
+ redirects the output to stdout.
+
+ >>> from nose.plugins.plugintest import run_buffered as run
+
+..
+
+ >>> import os
+ >>> support = os.path.join(os.path.dirname(__file__), 'support')
+ >>> argv = [__file__, '-v', support]
+
+The target directory contains a test module and a normal module.
+
+ >>> support_files = [d for d in os.listdir(support)
+ ... if not d.startswith('.')
+ ... and d.endswith('.py')]
+ >>> support_files.sort()
+ >>> support_files
+ ['mod.py', 'test.py']
+
+When run without ``--all-modules``, only the test module is examined for tests.
+
+ >>> run(argv=argv)
+ test.test ... ok
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ OK
+
+When ``--all-modules`` is active, both modules are examined.
+
+ >>> from nose.plugins.allmodules import AllModules
+ >>> argv = [__file__, '-v', '--all-modules', support]
+ >>> run(argv=argv, plugins=[AllModules()]) # doctest: +REPORT_NDIFF
+ mod.test ... ok
+ mod.test_fails ... FAIL
+ test.test ... ok
+
+ ======================================================================
+ FAIL: mod.test_fails
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ AssertionError: This test fails
+
+ ----------------------------------------------------------------------
+ Ran 3 tests in ...s
+
+ FAILED (failures=1)
+
+
+
diff --git a/functional_tests/doc_tests/test_coverage_html/coverage_html_fixtures.pyc b/functional_tests/doc_tests/test_coverage_html/coverage_html_fixtures.pyc
new file mode 100644
index 0000000..1b79401
Binary files /dev/null and b/functional_tests/doc_tests/test_coverage_html/coverage_html_fixtures.pyc differ
diff --git a/functional_tests/doc_tests/test_coverage_html/support/blah.pyc b/functional_tests/doc_tests/test_coverage_html/support/blah.pyc
new file mode 100644
index 0000000..cb8c284
Binary files /dev/null and b/functional_tests/doc_tests/test_coverage_html/support/blah.pyc differ
diff --git a/functional_tests/doc_tests/test_coverage_html/support/tests/test_covered.pyc b/functional_tests/doc_tests/test_coverage_html/support/tests/test_covered.pyc
new file mode 100644
index 0000000..51582f2
Binary files /dev/null and b/functional_tests/doc_tests/test_coverage_html/support/tests/test_covered.pyc differ
diff --git a/functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures.rst b/functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures.rst
new file mode 100644
index 0000000..6ff8fed
--- /dev/null
+++ b/functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures.rst
@@ -0,0 +1,122 @@
+Doctest Fixtures
+----------------
+
+Doctest files, like other tests, can be made more efficient or meaningful or
+at least easier to write by judicious use of fixtures. nose supports limited
+fixtures for use with doctest files.
+
+Module-level fixtures
+=====================
+
+Fixtures for a doctest file may define any or all of the following methods for
+module-level setup:
+
+* setup
+* setup_module
+* setupModule
+* setUpModule
+
+Each module-level setup function may optionally take a single argument, the
+fixtures module itself.
+
+Example::
+
+ def setup_module(module):
+ module.called[:] = []
+
+Similarly, module-level teardown methods are available, which also optionally
+take the fixtures module as an argument:
+
+* teardown
+* teardown_module
+* teardownModule
+* tearDownModule
+
+Example::
+
+ def teardown_module(module):
+ module.called[:] = []
+ module.done = True
+
+Module-level setup executes **before any tests are loaded** from the doctest
+file. This is the right place to raise :class:`nose.plugins.skip.SkipTest`,
+for example.
+
+Test-level fixtures
+===================
+
+In addition to module-level fixtures, *test*-level fixtures are
+supported. Keep in mind that in the doctest lexicon, the *test* is the *entire
+doctest file* -- not each individual example within the file. So, like the
+module-level fixtures, test-level fixtures execute *once per file*. The
+differences are that:
+
+- test-level fixtures execute **after** tests have been loaded, but **before**
+ any tests have executed.
+- test-level fixtures receive the doctest :class:`doctest.DocFileCase` loaded
+ from the file as their one *required* argument.
+
+**setup_test(test)** is called before the test is run.
+
+Example::
+
+ def setup_test(test):
+ called.append(test)
+ test.globs['count'] = len(called)
+ setup_test.__test__ = False
+
+**teardown_test(test)** is alled after the test, unless setup raised an
+uncaught exception. The argument is the :class:`doctest.DocFileCase` object,
+*not* a unittest.TestCase.
+
+Example::
+
+ def teardown_test(test):
+ pass
+ teardown_test.__test__ = False
+
+Bottom line: setup_test, teardown_test have access to the *doctest test*,
+while setup, setup_module, etc have access to the *fixture*
+module. setup_module runs before tests are loaded, setup_test after.
+
+.. note ::
+
+ As in the examples, it's a good idea to tag your setup_test/teardown_test
+ functions with ``__test__ = False`` to avoid them being collected as tests.
+
+Lastly, the fixtures for a doctest file may supply a **globs(globs)**
+function. The dict returned by this function will be passed to the doctest
+runner as the globals available to the test. You can use this, for example, to
+easily inject a module's globals into a doctest that has been moved from the
+module to a separate file.
+
+Example
+=======
+
+This doctest has some simple fixtures:
+
+.. include :: doctest_fixtures_fixtures.py
+ :literal:
+
+The ``globs`` defined in the fixtures make the variable ``something``
+available in all examples.
+
+ >>> something
+ 'Something?'
+
+The ``count`` variable is injected by the test-level fixture.
+
+ >>> count
+ 1
+
+.. warning ::
+
+ This whole file is one doctest test. setup_test doesn't do what you think!
+ It exists to give you access to the test case and examples, but it runs
+ *once*, before all of them, not before each.
+
+ >>> count
+ 1
+
+ Thus, ``count`` stays 1 throughout the test, no matter how many examples it
+ includes.
\ No newline at end of file
diff --git a/functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures_fixtures.py b/functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures_fixtures.py
new file mode 100644
index 0000000..72fbfd7
--- /dev/null
+++ b/functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures_fixtures.py
@@ -0,0 +1,17 @@
+called = []
+
+def globs(globs):
+ globs['something'] = 'Something?'
+ return globs
+
+def setup_module(module):
+ module.called[:] = []
+
+def setup_test(test):
+ called.append(test)
+ test.globs['count'] = len(called)
+setup_test.__test__ = False
+
+def teardown_test(test):
+ pass
+teardown_test.__test__ = False
diff --git a/functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures_fixtures.pyc b/functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures_fixtures.pyc
new file mode 100644
index 0000000..a48431d
Binary files /dev/null and b/functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures_fixtures.pyc differ
diff --git a/functional_tests/doc_tests/test_init_plugin/example.cfg b/functional_tests/doc_tests/test_init_plugin/example.cfg
new file mode 100644
index 0000000..b02ac0e
--- /dev/null
+++ b/functional_tests/doc_tests/test_init_plugin/example.cfg
@@ -0,0 +1,3 @@
+[DEFAULT]
+can_frobnicate = 1
+likes_cheese = 0
diff --git a/functional_tests/doc_tests/test_init_plugin/init_plugin.rst b/functional_tests/doc_tests/test_init_plugin/init_plugin.rst
new file mode 100644
index 0000000..6c64029
--- /dev/null
+++ b/functional_tests/doc_tests/test_init_plugin/init_plugin.rst
@@ -0,0 +1,164 @@
+Running Initialization Code Before the Test Run
+-----------------------------------------------
+
+Many applications, especially those using web frameworks like Pylons_
+or Django_, can't be tested without first being configured or
+otherwise initialized. Plugins can fulfill this requirement by
+implementing :meth:`begin() `.
+
+In this example, we'll use a very simple example: a widget class that
+can't be tested without a configuration.
+
+Here's the widget class. It's configured at the class or instance
+level by setting the ``cfg`` attribute to a dictionary.
+
+ >>> class ConfigurableWidget(object):
+ ... cfg = None
+ ... def can_frobnicate(self):
+ ... return self.cfg.get('can_frobnicate', True)
+ ... def likes_cheese(self):
+ ... return self.cfg.get('likes_cheese', True)
+
+The tests verify that the widget's methods can be called without
+raising any exceptions.
+
+ >>> import unittest
+ >>> class TestConfigurableWidget(unittest.TestCase):
+ ... longMessage = False
+ ... def setUp(self):
+ ... self.widget = ConfigurableWidget()
+ ... def test_can_frobnicate(self):
+ ... """Widgets can frobnicate (or not)"""
+ ... self.widget.can_frobnicate()
+ ... def test_likes_cheese(self):
+ ... """Widgets might like cheese"""
+ ... self.widget.likes_cheese()
+ ... def shortDescription(self): # 2.7 compat
+ ... try:
+ ... doc = self._testMethodDoc
+ ... except AttributeError:
+ ... # 2.4 compat
+ ... doc = self._TestCase__testMethodDoc
+ ... return doc and doc.split("\n")[0].strip() or None
+
+The tests are bundled into a suite that we can pass to the test runner.
+
+ >>> def suite():
+ ... return unittest.TestSuite([
+ ... TestConfigurableWidget('test_can_frobnicate'),
+ ... TestConfigurableWidget('test_likes_cheese')])
+
+When we run tests without first configuring the ConfigurableWidget,
+the tests fail.
+
+.. Note ::
+
+ The function :func:`nose.plugins.plugintest.run` reformats test result
+ output to remove timings, which will vary from run to run, and
+ redirects the output to stdout.
+
+ >>> from nose.plugins.plugintest import run_buffered as run
+
+..
+
+ >>> argv = [__file__, '-v']
+ >>> run(argv=argv, suite=suite()) # doctest: +REPORT_NDIFF
+ Widgets can frobnicate (or not) ... ERROR
+ Widgets might like cheese ... ERROR
+
+ ======================================================================
+ ERROR: Widgets can frobnicate (or not)
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'NoneType' object has no attribute 'get'
+
+ ======================================================================
+ ERROR: Widgets might like cheese
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'NoneType' object has no attribute 'get'
+
+ ----------------------------------------------------------------------
+ Ran 2 tests in ...s
+
+ FAILED (errors=2)
+
+To configure the widget system before running tests, write a plugin
+that implements :meth:`begin() `
+and initializes the system with a hard-coded configuration. (Later, we'll
+write a better plugin that accepts a command-line argument specifying the
+configuration file.)
+
+ >>> from nose.plugins import Plugin
+ >>> class ConfiguringPlugin(Plugin):
+ ... enabled = True
+ ... def configure(self, options, conf):
+ ... pass # always on
+ ... def begin(self):
+ ... ConfigurableWidget.cfg = {}
+
+Now configure and execute a new test run using the plugin, which will
+inject the hard-coded configuration.
+
+ >>> run(argv=argv, suite=suite(),
+ ... plugins=[ConfiguringPlugin()]) # doctest: +REPORT_NDIFF
+ Widgets can frobnicate (or not) ... ok
+ Widgets might like cheese ... ok
+
+ ----------------------------------------------------------------------
+ Ran 2 tests in ...s
+
+ OK
+
+This time the tests pass, because the widget class is configured.
+
+But the ConfiguringPlugin is pretty lame -- the configuration it
+installs is hard coded. A better plugin would allow the user to
+specify a configuration file on the command line:
+
+ >>> class BetterConfiguringPlugin(Plugin):
+ ... def options(self, parser, env={}):
+ ... parser.add_option('--widget-config', action='store',
+ ... dest='widget_config', default=None,
+ ... help='Specify path to widget config file')
+ ... def configure(self, options, conf):
+ ... if options.widget_config:
+ ... self.load_config(options.widget_config)
+ ... self.enabled = True
+ ... def begin(self):
+ ... ConfigurableWidget.cfg = self.cfg
+ ... def load_config(self, path):
+ ... from ConfigParser import ConfigParser
+ ... p = ConfigParser()
+ ... p.read([path])
+ ... self.cfg = dict(p.items('DEFAULT'))
+
+To use the plugin, we need a config file.
+
+ >>> import os
+ >>> cfg_file = os.path.join(os.path.dirname(__file__), 'example.cfg')
+ >>> bytes = open(cfg_file, 'w').write("""\
+ ... [DEFAULT]
+ ... can_frobnicate = 1
+ ... likes_cheese = 0
+ ... """)
+
+Now we can execute a test run using that configuration, after first
+resetting the widget system to an unconfigured state.
+
+ >>> ConfigurableWidget.cfg = None
+ >>> argv = [__file__, '-v', '--widget-config', cfg_file]
+ >>> run(argv=argv, suite=suite(),
+ ... plugins=[BetterConfiguringPlugin()]) # doctest: +REPORT_NDIFF
+ Widgets can frobnicate (or not) ... ok
+ Widgets might like cheese ... ok
+
+ ----------------------------------------------------------------------
+ Ran 2 tests in ...s
+
+ OK
+
+.. _Pylons: http://pylonshq.com/
+.. _Django: http://www.djangoproject.com/
diff --git a/functional_tests/doc_tests/test_init_plugin/init_plugin.rst.py3.patch b/functional_tests/doc_tests/test_init_plugin/init_plugin.rst.py3.patch
new file mode 100644
index 0000000..90a0a44
--- /dev/null
+++ b/functional_tests/doc_tests/test_init_plugin/init_plugin.rst.py3.patch
@@ -0,0 +1,10 @@
+--- init_plugin.rst.orig 2010-08-31 10:36:54.000000000 -0700
++++ init_plugin.rst 2010-08-31 10:37:30.000000000 -0700
+@@ -143,6 +143,7 @@
+ ... can_frobnicate = 1
+ ... likes_cheese = 0
+ ... """)
++ 46
+
+ Now we can execute a test run using that configuration, after first
+ resetting the widget system to an unconfigured state.
diff --git a/functional_tests/doc_tests/test_issue089/support/unwanted_package/__init__.py b/functional_tests/doc_tests/test_issue089/support/unwanted_package/__init__.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue089/support/unwanted_package/__init__.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/doc_tests/test_issue089/support/unwanted_package/__init__.pyc b/functional_tests/doc_tests/test_issue089/support/unwanted_package/__init__.pyc
new file mode 100644
index 0000000..0fffbc4
Binary files /dev/null and b/functional_tests/doc_tests/test_issue089/support/unwanted_package/__init__.pyc differ
diff --git a/functional_tests/doc_tests/test_issue089/support/unwanted_package/test_spam.py b/functional_tests/doc_tests/test_issue089/support/unwanted_package/test_spam.py
new file mode 100644
index 0000000..cfd1cc1
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue089/support/unwanted_package/test_spam.py
@@ -0,0 +1,3 @@
+def test_spam():
+ assert True
+
diff --git a/functional_tests/doc_tests/test_issue089/support/unwanted_package/test_spam.pyc b/functional_tests/doc_tests/test_issue089/support/unwanted_package/test_spam.pyc
new file mode 100644
index 0000000..8688796
Binary files /dev/null and b/functional_tests/doc_tests/test_issue089/support/unwanted_package/test_spam.pyc differ
diff --git a/functional_tests/doc_tests/test_issue089/support/wanted_package/__init__.py b/functional_tests/doc_tests/test_issue089/support/wanted_package/__init__.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue089/support/wanted_package/__init__.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/doc_tests/test_issue089/support/wanted_package/__init__.pyc b/functional_tests/doc_tests/test_issue089/support/wanted_package/__init__.pyc
new file mode 100644
index 0000000..7475436
Binary files /dev/null and b/functional_tests/doc_tests/test_issue089/support/wanted_package/__init__.pyc differ
diff --git a/functional_tests/doc_tests/test_issue089/support/wanted_package/test_eggs.py b/functional_tests/doc_tests/test_issue089/support/wanted_package/test_eggs.py
new file mode 100644
index 0000000..bb65550
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue089/support/wanted_package/test_eggs.py
@@ -0,0 +1,3 @@
+def test_eggs():
+ assert True
+
diff --git a/functional_tests/doc_tests/test_issue089/support/wanted_package/test_eggs.pyc b/functional_tests/doc_tests/test_issue089/support/wanted_package/test_eggs.pyc
new file mode 100644
index 0000000..8ad2dc1
Binary files /dev/null and b/functional_tests/doc_tests/test_issue089/support/wanted_package/test_eggs.pyc differ
diff --git a/functional_tests/doc_tests/test_issue089/unwanted_package.rst b/functional_tests/doc_tests/test_issue089/unwanted_package.rst
new file mode 100644
index 0000000..c7efc27
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue089/unwanted_package.rst
@@ -0,0 +1,70 @@
+Excluding Unwanted Packages
+---------------------------
+
+Normally, nose discovery descends into all packages. Plugins can
+change this behavior by implementing :meth:`IPluginInterface.wantDirectory()`.
+
+In this example, we have a wanted package called ``wanted_package``
+and an unwanted package called ``unwanted_package``.
+
+ >>> import os
+ >>> support = os.path.join(os.path.dirname(__file__), 'support')
+ >>> support_files = [d for d in os.listdir(support)
+ ... if not d.startswith('.')]
+ >>> support_files.sort()
+ >>> support_files
+ ['unwanted_package', 'wanted_package']
+
+When we run nose normally, tests are loaded from both packages.
+
+.. Note ::
+
+ The function :func:`nose.plugins.plugintest.run` reformats test result
+ output to remove timings, which will vary from run to run, and
+ redirects the output to stdout.
+
+ >>> from nose.plugins.plugintest import run_buffered as run
+
+..
+
+ >>> argv = [__file__, '-v', support]
+ >>> run(argv=argv) # doctest: +REPORT_NDIFF
+ unwanted_package.test_spam.test_spam ... ok
+ wanted_package.test_eggs.test_eggs ... ok
+
+ ----------------------------------------------------------------------
+ Ran 2 tests in ...s
+
+ OK
+
+To exclude the tests in the unwanted package, we can write a simple
+plugin that implements :meth:`IPluginInterface.wantDirectory()` and returns ``False`` if
+the basename of the directory is ``"unwanted_package"``. This will
+prevent nose from descending into the unwanted package.
+
+ >>> from nose.plugins import Plugin
+ >>> class UnwantedPackagePlugin(Plugin):
+ ... # no command line arg needed to activate plugin
+ ... enabled = True
+ ... name = "unwanted-package"
+ ...
+ ... def configure(self, options, conf):
+ ... pass # always on
+ ...
+ ... def wantDirectory(self, dirname):
+ ... want = None
+ ... if os.path.basename(dirname) == "unwanted_package":
+ ... want = False
+ ... return want
+
+In the next test run we use the plugin, and the unwanted package is
+not discovered.
+
+ >>> run(argv=argv,
+ ... plugins=[UnwantedPackagePlugin()]) # doctest: +REPORT_NDIFF
+ wanted_package.test_eggs.test_eggs ... ok
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ OK
\ No newline at end of file
diff --git a/functional_tests/doc_tests/test_issue097/plugintest_environment.rst b/functional_tests/doc_tests/test_issue097/plugintest_environment.rst
new file mode 100644
index 0000000..99b37cf
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue097/plugintest_environment.rst
@@ -0,0 +1,160 @@
+nose.plugins.plugintest, os.environ and sys.argv
+------------------------------------------------
+
+:class:`nose.plugins.plugintest.PluginTester` and
+:func:`nose.plugins.plugintest.run` are utilities for testing nose
+plugins. When testing plugins, it should be possible to control the
+environment seen plugins under test, and that environment should never
+be affected by ``os.environ`` or ``sys.argv``.
+
+ >>> import os
+ >>> import sys
+ >>> import unittest
+ >>> import nose.config
+ >>> from nose.plugins import Plugin
+ >>> from nose.plugins.builtin import FailureDetail, Capture
+ >>> from nose.plugins.plugintest import PluginTester
+
+Our test plugin takes no command-line arguments and simply prints the
+environment it's given by nose.
+
+ >>> class PrintEnvPlugin(Plugin):
+ ... name = "print-env"
+ ...
+ ... # no command line arg needed to activate plugin
+ ... enabled = True
+ ... def configure(self, options, conf):
+ ... if not self.can_configure:
+ ... return
+ ... self.conf = conf
+ ...
+ ... def options(self, parser, env={}):
+ ... print "env:", env
+
+To test the argv, we use a config class that prints the argv it's
+given by nose. We need to monkeypatch nose.config.Config, so that we
+can test the cases where that is used as the default.
+
+ >>> old_config = nose.config.Config
+ >>> class PrintArgvConfig(old_config):
+ ...
+ ... def configure(self, argv=None, doc=None):
+ ... print "argv:", argv
+ ... old_config.configure(self, argv, doc)
+ >>> nose.config.Config = PrintArgvConfig
+
+The class under test, PluginTester, is designed to be used by
+subclassing.
+
+ >>> class Tester(PluginTester):
+ ... activate = "-v"
+ ... plugins = [PrintEnvPlugin(),
+ ... FailureDetail(),
+ ... Capture(),
+ ... ]
+ ...
+ ... def makeSuite(self):
+ ... return unittest.TestSuite(tests=[])
+
+For the purposes of this test, we need a known ``os.environ`` and
+``sys.argv``.
+
+ >>> old_environ = os.environ
+ >>> old_argv = sys.argv
+ >>> os.environ = {"spam": "eggs"}
+ >>> sys.argv = ["spamtests"]
+
+PluginTester always uses the [nosetests, self.activate] as its argv.
+If ``env`` is not overridden, the default is an empty ``env``.
+
+ >>> tester = Tester()
+ >>> tester.setUp()
+ argv: ['nosetests', '-v']
+ env: {}
+
+An empty ``env`` is respected...
+
+ >>> class EmptyEnvTester(Tester):
+ ... env = {}
+ >>> tester = EmptyEnvTester()
+ >>> tester.setUp()
+ argv: ['nosetests', '-v']
+ env: {}
+
+... as is a non-empty ``env``.
+
+ >>> class NonEmptyEnvTester(Tester):
+ ... env = {"foo": "bar"}
+ >>> tester = NonEmptyEnvTester()
+ >>> tester.setUp()
+ argv: ['nosetests', '-v']
+ env: {'foo': 'bar'}
+
+
+``nose.plugins.plugintest.run()`` should work analogously.
+
+ >>> from nose.plugins.plugintest import run_buffered as run
+ >>> run(suite=unittest.TestSuite(tests=[]),
+ ... plugins=[PrintEnvPlugin()]) # doctest: +REPORT_NDIFF
+ argv: ['nosetests', '-v']
+ env: {}
+
+ ----------------------------------------------------------------------
+ Ran 0 tests in ...s
+
+ OK
+ >>> run(env={},
+ ... suite=unittest.TestSuite(tests=[]),
+ ... plugins=[PrintEnvPlugin()]) # doctest: +REPORT_NDIFF
+ argv: ['nosetests', '-v']
+ env: {}
+
+ ----------------------------------------------------------------------
+ Ran 0 tests in ...s
+
+ OK
+ >>> run(env={"foo": "bar"},
+ ... suite=unittest.TestSuite(tests=[]),
+ ... plugins=[PrintEnvPlugin()]) # doctest: +REPORT_NDIFF
+ argv: ['nosetests', '-v']
+ env: {'foo': 'bar'}
+
+ ----------------------------------------------------------------------
+ Ran 0 tests in ...s
+
+ OK
+
+An explicit argv parameter is honoured:
+
+ >>> run(argv=["spam"],
+ ... suite=unittest.TestSuite(tests=[]),
+ ... plugins=[PrintEnvPlugin()]) # doctest: +REPORT_NDIFF
+ argv: ['spam']
+ env: {}
+
+ ----------------------------------------------------------------------
+ Ran 0 tests in ...s
+
+ OK
+
+An explicit config parameter with an env is honoured:
+
+ >>> from nose.plugins.manager import PluginManager
+ >>> manager = PluginManager(plugins=[PrintEnvPlugin()])
+ >>> config = PrintArgvConfig(env={"foo": "bar"}, plugins=manager)
+ >>> run(config=config,
+ ... suite=unittest.TestSuite(tests=[])) # doctest: +REPORT_NDIFF
+ argv: ['nosetests', '-v']
+ env: {'foo': 'bar'}
+
+ ----------------------------------------------------------------------
+ Ran 0 tests in ...s
+
+ OK
+
+
+Clean up.
+
+ >>> os.environ = old_environ
+ >>> sys.argv = old_argv
+ >>> nose.config.Config = old_config
diff --git a/functional_tests/doc_tests/test_issue107/plugin_exceptions.rst b/functional_tests/doc_tests/test_issue107/plugin_exceptions.rst
new file mode 100644
index 0000000..2c595f0
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue107/plugin_exceptions.rst
@@ -0,0 +1,149 @@
+When Plugins Fail
+-----------------
+
+Plugin methods should not fail silently. When a plugin method raises
+an exception before or during the execution of a test, the exception
+will be wrapped in a :class:`nose.failure.Failure` instance and appear as a
+failing test. Exceptions raised at other times, such as in the
+preparation phase with ``prepareTestLoader`` or ``prepareTestResult``,
+or after a test executes, in ``afterTest`` will stop the entire test
+run.
+
+ >>> import os
+ >>> import sys
+ >>> from nose.plugins import Plugin
+ >>> from nose.plugins.plugintest import run_buffered as run
+
+Our first test plugins take no command-line arguments and raises
+AttributeError in beforeTest and afterTest.
+
+ >>> class EnabledPlugin(Plugin):
+ ... """Plugin that takes no command-line arguments"""
+ ...
+ ... enabled = True
+ ...
+ ... def configure(self, options, conf):
+ ... pass
+ ... def options(self, parser, env={}):
+ ... pass
+ >>> class FailBeforePlugin(EnabledPlugin):
+ ... name = "fail-before"
+ ...
+ ... def beforeTest(self, test):
+ ... raise AttributeError()
+ >>> class FailAfterPlugin(EnabledPlugin):
+ ... name = "fail-after"
+ ...
+ ... def afterTest(self, test):
+ ... raise AttributeError()
+
+Running tests with the fail-before plugin enabled will result in all
+tests failing.
+
+ >>> support = os.path.join(os.path.dirname(__file__), 'support')
+ >>> suitepath = os.path.join(support, 'test_spam.py')
+ >>> run(argv=['nosetests', suitepath],
+ ... plugins=[FailBeforePlugin()])
+ EE
+ ======================================================================
+ ERROR: test_spam.test_spam
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ AttributeError
+
+ ======================================================================
+ ERROR: test_spam.test_eggs
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ AttributeError
+
+ ----------------------------------------------------------------------
+ Ran 0 tests in ...s
+
+ FAILED (errors=2)
+
+But with the fail-after plugin, the entire test run will fail.
+
+ >>> run(argv=['nosetests', suitepath],
+ ... plugins=[FailAfterPlugin()])
+ Traceback (most recent call last):
+ ...
+ AttributeError
+
+Likewise, since the next plugin fails in a preparatory method, outside
+of test execution, the entire test run fails when the plugin is used.
+
+ >>> class FailPreparationPlugin(EnabledPlugin):
+ ... name = "fail-prepare"
+ ...
+ ... def prepareTestLoader(self, loader):
+ ... raise TypeError("That loader is not my type")
+ >>> run(argv=['nosetests', suitepath],
+ ... plugins=[FailPreparationPlugin()])
+ Traceback (most recent call last):
+ ...
+ TypeError: That loader is not my type
+
+
+Even AttributeErrors and TypeErrors are not silently suppressed as
+they used to be for some generative plugin methods (issue152).
+
+These methods caught TypeError and AttributeError and did not record
+the exception, before issue152 was fixed: .loadTestsFromDir(),
+.loadTestsFromModule(), .loadTestsFromTestCase(),
+loadTestsFromTestClass, and .makeTest(). Now, the exception is
+caught, but logged as a Failure.
+
+ >>> class FailLoadPlugin(EnabledPlugin):
+ ... name = "fail-load"
+ ...
+ ... def loadTestsFromModule(self, module):
+ ... # we're testing exception handling behaviour during
+ ... # iteration, so be a generator function, without
+ ... # actually yielding any tests
+ ... if False:
+ ... yield None
+ ... raise TypeError("bug in plugin")
+ >>> run(argv=['nosetests', suitepath],
+ ... plugins=[FailLoadPlugin()])
+ ..E
+ ======================================================================
+ ERROR: Failure: TypeError (bug in plugin)
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ TypeError: bug in plugin
+
+ ----------------------------------------------------------------------
+ Ran 3 tests in ...s
+
+ FAILED (errors=1)
+
+
+Also, before issue152 was resolved, .loadTestsFromFile() and
+.loadTestsFromName() didn't catch these errors at all, so the
+following test would crash nose:
+
+ >>> class FailLoadFromNamePlugin(EnabledPlugin):
+ ... name = "fail-load-from-name"
+ ...
+ ... def loadTestsFromName(self, name, module=None, importPath=None):
+ ... if False:
+ ... yield None
+ ... raise TypeError("bug in plugin")
+ >>> run(argv=['nosetests', suitepath],
+ ... plugins=[FailLoadFromNamePlugin()])
+ E
+ ======================================================================
+ ERROR: Failure: TypeError (bug in plugin)
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ TypeError: bug in plugin
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ FAILED (errors=1)
diff --git a/functional_tests/doc_tests/test_issue107/support/test_spam.py b/functional_tests/doc_tests/test_issue107/support/test_spam.py
new file mode 100644
index 0000000..4c1b8fb
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue107/support/test_spam.py
@@ -0,0 +1,5 @@
+def test_spam():
+ assert True
+
+def test_eggs():
+ pass
diff --git a/functional_tests/doc_tests/test_issue107/support/test_spam.pyc b/functional_tests/doc_tests/test_issue107/support/test_spam.pyc
new file mode 100644
index 0000000..5565d94
Binary files /dev/null and b/functional_tests/doc_tests/test_issue107/support/test_spam.pyc differ
diff --git a/functional_tests/doc_tests/test_issue119/empty_plugin.rst b/functional_tests/doc_tests/test_issue119/empty_plugin.rst
new file mode 100644
index 0000000..6194c19
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue119/empty_plugin.rst
@@ -0,0 +1,57 @@
+Minimal plugin
+--------------
+
+Plugins work as long as they implement the minimal interface required
+by nose.plugins.base. They do not have to derive from
+nose.plugins.Plugin.
+
+ >>> class NullPlugin(object):
+ ...
+ ... enabled = True
+ ... name = "null"
+ ... score = 100
+ ...
+ ... def options(self, parser, env):
+ ... pass
+ ...
+ ... def configure(self, options, conf):
+ ... pass
+ >>> import unittest
+ >>> from nose.plugins.plugintest import run_buffered as run
+ >>> run(suite=unittest.TestSuite(tests=[]),
+ ... plugins=[NullPlugin()]) # doctest: +REPORT_NDIFF
+ ----------------------------------------------------------------------
+ Ran 0 tests in ...s
+
+ OK
+
+Plugins can derive from nose.plugins.base and do nothing except set a
+name.
+
+ >>> import os
+ >>> from nose.plugins import Plugin
+ >>> class DerivedNullPlugin(Plugin):
+ ...
+ ... name = "derived-null"
+
+Enabled plugin that's otherwise empty
+
+ >>> class EnabledDerivedNullPlugin(Plugin):
+ ...
+ ... enabled = True
+ ... name = "enabled-derived-null"
+ ...
+ ... def options(self, parser, env=os.environ):
+ ... pass
+ ...
+ ... def configure(self, options, conf):
+ ... if not self.can_configure:
+ ... return
+ ... self.conf = conf
+ >>> run(suite=unittest.TestSuite(tests=[]),
+ ... plugins=[DerivedNullPlugin(), EnabledDerivedNullPlugin()])
+ ... # doctest: +REPORT_NDIFF
+ ----------------------------------------------------------------------
+ Ran 0 tests in ...s
+
+ OK
diff --git a/functional_tests/doc_tests/test_issue119/test_zeronine.py b/functional_tests/doc_tests/test_issue119/test_zeronine.py
new file mode 100644
index 0000000..6a4f450
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue119/test_zeronine.py
@@ -0,0 +1,26 @@
+import os
+import unittest
+from nose.plugins import Plugin
+from nose.plugins.plugintest import PluginTester
+from nose.plugins.manager import ZeroNinePlugin
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+support = os.path.join(os.path.dirname(os.path.dirname(here)), 'support')
+
+
+class EmptyPlugin(Plugin):
+ pass
+
+class TestEmptyPlugin(PluginTester, unittest.TestCase):
+ activate = '--with-empty'
+ plugins = [ZeroNinePlugin(EmptyPlugin())]
+ suitepath = os.path.join(here, 'empty_plugin.rst')
+
+ def test_empty_zero_nine_does_not_crash(self):
+ print self.output
+ assert "'EmptyPlugin' object has no attribute 'loadTestsFromPath'" \
+ not in self.output
+
+
+
diff --git a/functional_tests/doc_tests/test_issue119/test_zeronine.pyc b/functional_tests/doc_tests/test_issue119/test_zeronine.pyc
new file mode 100644
index 0000000..6a33e05
Binary files /dev/null and b/functional_tests/doc_tests/test_issue119/test_zeronine.pyc differ
diff --git a/functional_tests/doc_tests/test_issue142/errorclass_failure.rst b/functional_tests/doc_tests/test_issue142/errorclass_failure.rst
new file mode 100644
index 0000000..c4ce287
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue142/errorclass_failure.rst
@@ -0,0 +1,124 @@
+Failure of Errorclasses
+-----------------------
+
+Errorclasses (skips, deprecations, etc.) define whether or not they
+represent test failures.
+
+ >>> import os
+ >>> import sys
+ >>> from nose.plugins.plugintest import run_buffered as run
+ >>> from nose.plugins.skip import Skip
+ >>> from nose.plugins.deprecated import Deprecated
+ >>> support = os.path.join(os.path.dirname(__file__), 'support')
+ >>> sys.path.insert(0, support)
+ >>> from errorclass_failure_plugin import Todo, TodoPlugin, \
+ ... NonFailureTodoPlugin
+ >>> todo_test = os.path.join(support, 'errorclass_failing_test.py')
+ >>> misc_test = os.path.join(support, 'errorclass_tests.py')
+
+nose.plugins.errorclass.ErrorClass has an argument ``isfailure``. With a
+true isfailure, when the errorclass' exception is raised by a test,
+tracebacks are printed.
+
+ >>> run(argv=["nosetests", "-v", "--with-todo", todo_test],
+ ... plugins=[TodoPlugin()]) # doctest: +REPORT_NDIFF
+ errorclass_failing_test.test_todo ... TODO: fix me
+ errorclass_failing_test.test_2 ... ok
+
+ ======================================================================
+ TODO: errorclass_failing_test.test_todo
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ Todo: fix me
+
+ ----------------------------------------------------------------------
+ Ran 2 tests in ...s
+
+ FAILED (TODO=1)
+
+
+Also, ``--stop`` stops the test run.
+
+ >>> run(argv=["nosetests", "-v", "--with-todo", "--stop", todo_test],
+ ... plugins=[TodoPlugin()]) # doctest: +REPORT_NDIFF
+ errorclass_failing_test.test_todo ... TODO: fix me
+
+ ======================================================================
+ TODO: errorclass_failing_test.test_todo
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ Todo: fix me
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ FAILED (TODO=1)
+
+
+With a false .isfailure, errorclass exceptions raised by tests are
+treated as "ignored errors." For ignored errors, tracebacks are not
+printed, and the test run does not stop.
+
+ >>> run(argv=["nosetests", "-v", "--with-non-failure-todo", "--stop",
+ ... todo_test],
+ ... plugins=[NonFailureTodoPlugin()]) # doctest: +REPORT_NDIFF
+ errorclass_failing_test.test_todo ... TODO: fix me
+ errorclass_failing_test.test_2 ... ok
+
+ ----------------------------------------------------------------------
+ Ran 2 tests in ...s
+
+ OK (TODO=1)
+
+
+Exception detail strings of errorclass errors are always printed when
+-v is in effect, regardless of whether the error is ignored. Note
+that exception detail strings may have more than one line.
+
+ >>> run(argv=["nosetests", "-v", "--with-todo", misc_test],
+ ... plugins=[TodoPlugin(), Skip(), Deprecated()])
+ ... # doctest: +REPORT_NDIFF
+ errorclass_tests.test_todo ... TODO: fix me
+ errorclass_tests.test_2 ... ok
+ errorclass_tests.test_3 ... SKIP: skipety-skip
+ errorclass_tests.test_4 ... SKIP
+ errorclass_tests.test_5 ... DEPRECATED: spam
+ eggs
+
+ spam
+ errorclass_tests.test_6 ... DEPRECATED: spam
+
+ ======================================================================
+ TODO: errorclass_tests.test_todo
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ Todo: fix me
+
+ ----------------------------------------------------------------------
+ Ran 6 tests in ...s
+
+ FAILED (DEPRECATED=2, SKIP=2, TODO=1)
+
+Without -v, the exception detail strings are only displayed if the
+error is not ignored (otherwise, there's no traceback).
+
+ >>> run(argv=["nosetests", "--with-todo", misc_test],
+ ... plugins=[TodoPlugin(), Skip(), Deprecated()])
+ ... # doctest: +REPORT_NDIFF
+ T.SSDD
+ ======================================================================
+ TODO: errorclass_tests.test_todo
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ Todo: fix me
+
+ ----------------------------------------------------------------------
+ Ran 6 tests in ...s
+
+ FAILED (DEPRECATED=2, SKIP=2, TODO=1)
+
+>>> sys.path.remove(support)
diff --git a/functional_tests/doc_tests/test_issue142/support/errorclass_failing_test.py b/functional_tests/doc_tests/test_issue142/support/errorclass_failing_test.py
new file mode 100644
index 0000000..fae3c75
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue142/support/errorclass_failing_test.py
@@ -0,0 +1,7 @@
+from errorclass_failure_plugin import Todo
+
+def test_todo():
+ raise Todo("fix me")
+
+def test_2():
+ pass
diff --git a/functional_tests/doc_tests/test_issue142/support/errorclass_failing_test.pyc b/functional_tests/doc_tests/test_issue142/support/errorclass_failing_test.pyc
new file mode 100644
index 0000000..a476a5c
Binary files /dev/null and b/functional_tests/doc_tests/test_issue142/support/errorclass_failing_test.pyc differ
diff --git a/functional_tests/doc_tests/test_issue142/support/errorclass_failure_plugin.py b/functional_tests/doc_tests/test_issue142/support/errorclass_failure_plugin.py
new file mode 100644
index 0000000..927c986
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue142/support/errorclass_failure_plugin.py
@@ -0,0 +1,16 @@
+from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin
+
+class Todo(Exception):
+ pass
+
+class TodoPlugin(ErrorClassPlugin):
+
+ name = "todo"
+
+ todo = ErrorClass(Todo, label='TODO', isfailure=True)
+
+class NonFailureTodoPlugin(ErrorClassPlugin):
+
+ name = "non-failure-todo"
+
+ todo = ErrorClass(Todo, label='TODO', isfailure=False)
diff --git a/functional_tests/doc_tests/test_issue142/support/errorclass_failure_plugin.pyc b/functional_tests/doc_tests/test_issue142/support/errorclass_failure_plugin.pyc
new file mode 100644
index 0000000..df746cc
Binary files /dev/null and b/functional_tests/doc_tests/test_issue142/support/errorclass_failure_plugin.pyc differ
diff --git a/functional_tests/doc_tests/test_issue142/support/errorclass_tests.py b/functional_tests/doc_tests/test_issue142/support/errorclass_tests.py
new file mode 100644
index 0000000..4981224
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue142/support/errorclass_tests.py
@@ -0,0 +1,20 @@
+from errorclass_failure_plugin import Todo
+from nose import SkipTest, DeprecatedTest
+
+def test_todo():
+ raise Todo('fix me')
+
+def test_2():
+ pass
+
+def test_3():
+ raise SkipTest('skipety-skip')
+
+def test_4():
+ raise SkipTest()
+
+def test_5():
+ raise DeprecatedTest('spam\neggs\n\nspam')
+
+def test_6():
+ raise DeprecatedTest('spam')
diff --git a/functional_tests/doc_tests/test_issue142/support/errorclass_tests.pyc b/functional_tests/doc_tests/test_issue142/support/errorclass_tests.pyc
new file mode 100644
index 0000000..2fd336d
Binary files /dev/null and b/functional_tests/doc_tests/test_issue142/support/errorclass_tests.pyc differ
diff --git a/functional_tests/doc_tests/test_issue145/imported_tests.rst b/functional_tests/doc_tests/test_issue145/imported_tests.rst
new file mode 100644
index 0000000..c4eee78
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue145/imported_tests.rst
@@ -0,0 +1,117 @@
+Importing Tests
+---------------
+
+When a package imports tests from another package, the tests are
+**completely** relocated into the importing package. This means that the
+fixtures from the source package are **not** run when the tests in the
+importing package are executed.
+
+For example, consider this collection of packages:
+
+ >>> import os
+ >>> support = os.path.join(os.path.dirname(__file__), 'support')
+ >>> from nose.util import ls_tree
+ >>> print ls_tree(support) # doctest: +REPORT_NDIFF
+ |-- package1
+ | |-- __init__.py
+ | `-- test_module.py
+ |-- package2c
+ | |-- __init__.py
+ | `-- test_module.py
+ `-- package2f
+ |-- __init__.py
+ `-- test_module.py
+
+In these packages, the tests are all defined in package1, and are imported
+into package2f and package2c.
+
+.. Note ::
+
+ The run() function in :mod:`nose.plugins.plugintest` reformats test result
+ output to remove timings, which will vary from run to run, and
+ redirects the output to stdout.
+
+ >>> from nose.plugins.plugintest import run_buffered as run
+
+..
+
+package1 has fixtures, which we can see by running all of the tests. Note
+below that the test names reflect the modules into which the tests are
+imported, not the source modules.
+
+ >>> argv = [__file__, '-v', support]
+ >>> run(argv=argv) # doctest: +REPORT_NDIFF
+ package1 setup
+ test (package1.test_module.TestCase) ... ok
+ package1.test_module.TestClass.test_class ... ok
+ package1.test_module.test_function ... ok
+ package2c setup
+ test (package2c.test_module.TestCase) ... ok
+ package2c.test_module.TestClass.test_class ... ok
+ package2f setup
+ package2f.test_module.test_function ... ok
+
+ ----------------------------------------------------------------------
+ Ran 6 tests in ...s
+
+ OK
+
+When tests are run in package2f or package2c, only the fixtures from those
+packages are executed.
+
+ >>> argv = [__file__, '-v', os.path.join(support, 'package2f')]
+ >>> run(argv=argv) # doctest: +REPORT_NDIFF
+ package2f setup
+ package2f.test_module.test_function ... ok
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ OK
+ >>> argv = [__file__, '-v', os.path.join(support, 'package2c')]
+ >>> run(argv=argv) # doctest: +REPORT_NDIFF
+ package2c setup
+ test (package2c.test_module.TestCase) ... ok
+ package2c.test_module.TestClass.test_class ... ok
+
+ ----------------------------------------------------------------------
+ Ran 2 tests in ...s
+
+ OK
+
+This also applies when only the specific tests are selected via the
+command-line.
+
+ >>> argv = [__file__, '-v',
+ ... os.path.join(support, 'package2c', 'test_module.py') +
+ ... ':TestClass.test_class']
+ >>> run(argv=argv) # doctest: +REPORT_NDIFF
+ package2c setup
+ package2c.test_module.TestClass.test_class ... ok
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ OK
+ >>> argv = [__file__, '-v',
+ ... os.path.join(support, 'package2c', 'test_module.py') +
+ ... ':TestCase.test']
+ >>> run(argv=argv) # doctest: +REPORT_NDIFF
+ package2c setup
+ test (package2c.test_module.TestCase) ... ok
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ OK
+ >>> argv = [__file__, '-v',
+ ... os.path.join(support, 'package2f', 'test_module.py') +
+ ... ':test_function']
+ >>> run(argv=argv) # doctest: +REPORT_NDIFF
+ package2f setup
+ package2f.test_module.test_function ... ok
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ OK
diff --git a/functional_tests/doc_tests/test_issue145/support/package1/__init__.py b/functional_tests/doc_tests/test_issue145/support/package1/__init__.py
new file mode 100644
index 0000000..c715fdb
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue145/support/package1/__init__.py
@@ -0,0 +1,2 @@
+def setup():
+ print 'package1 setup'
diff --git a/functional_tests/doc_tests/test_issue145/support/package1/__init__.pyc b/functional_tests/doc_tests/test_issue145/support/package1/__init__.pyc
new file mode 100644
index 0000000..66cb7d3
Binary files /dev/null and b/functional_tests/doc_tests/test_issue145/support/package1/__init__.pyc differ
diff --git a/functional_tests/doc_tests/test_issue145/support/package1/test_module.py b/functional_tests/doc_tests/test_issue145/support/package1/test_module.py
new file mode 100644
index 0000000..0c5ac78
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue145/support/package1/test_module.py
@@ -0,0 +1,12 @@
+import unittest
+
+def test_function():
+ pass
+
+class TestClass:
+ def test_class(self):
+ pass
+
+class TestCase(unittest.TestCase):
+ def test(self):
+ pass
diff --git a/functional_tests/doc_tests/test_issue145/support/package1/test_module.pyc b/functional_tests/doc_tests/test_issue145/support/package1/test_module.pyc
new file mode 100644
index 0000000..fbbb583
Binary files /dev/null and b/functional_tests/doc_tests/test_issue145/support/package1/test_module.pyc differ
diff --git a/functional_tests/doc_tests/test_issue145/support/package2c/__init__.py b/functional_tests/doc_tests/test_issue145/support/package2c/__init__.py
new file mode 100644
index 0000000..106401f
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue145/support/package2c/__init__.py
@@ -0,0 +1,2 @@
+def setup():
+ print 'package2c setup'
diff --git a/functional_tests/doc_tests/test_issue145/support/package2c/__init__.pyc b/functional_tests/doc_tests/test_issue145/support/package2c/__init__.pyc
new file mode 100644
index 0000000..c43bf46
Binary files /dev/null and b/functional_tests/doc_tests/test_issue145/support/package2c/__init__.pyc differ
diff --git a/functional_tests/doc_tests/test_issue145/support/package2c/test_module.py b/functional_tests/doc_tests/test_issue145/support/package2c/test_module.py
new file mode 100644
index 0000000..6affbf1
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue145/support/package2c/test_module.py
@@ -0,0 +1 @@
+from package1.test_module import TestClass, TestCase
diff --git a/functional_tests/doc_tests/test_issue145/support/package2c/test_module.pyc b/functional_tests/doc_tests/test_issue145/support/package2c/test_module.pyc
new file mode 100644
index 0000000..59d0732
Binary files /dev/null and b/functional_tests/doc_tests/test_issue145/support/package2c/test_module.pyc differ
diff --git a/functional_tests/doc_tests/test_issue145/support/package2f/__init__.py b/functional_tests/doc_tests/test_issue145/support/package2f/__init__.py
new file mode 100644
index 0000000..fc203eb
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue145/support/package2f/__init__.py
@@ -0,0 +1,2 @@
+def setup():
+ print 'package2f setup'
diff --git a/functional_tests/doc_tests/test_issue145/support/package2f/__init__.pyc b/functional_tests/doc_tests/test_issue145/support/package2f/__init__.pyc
new file mode 100644
index 0000000..920c873
Binary files /dev/null and b/functional_tests/doc_tests/test_issue145/support/package2f/__init__.pyc differ
diff --git a/functional_tests/doc_tests/test_issue145/support/package2f/test_module.py b/functional_tests/doc_tests/test_issue145/support/package2f/test_module.py
new file mode 100644
index 0000000..e353c62
--- /dev/null
+++ b/functional_tests/doc_tests/test_issue145/support/package2f/test_module.py
@@ -0,0 +1 @@
+from package1.test_module import test_function
diff --git a/functional_tests/doc_tests/test_issue145/support/package2f/test_module.pyc b/functional_tests/doc_tests/test_issue145/support/package2f/test_module.pyc
new file mode 100644
index 0000000..0bfdaf3
Binary files /dev/null and b/functional_tests/doc_tests/test_issue145/support/package2f/test_module.pyc differ
diff --git a/functional_tests/doc_tests/test_multiprocess/multiprocess.rst b/functional_tests/doc_tests/test_multiprocess/multiprocess.rst
new file mode 100644
index 0000000..d463ba0
--- /dev/null
+++ b/functional_tests/doc_tests/test_multiprocess/multiprocess.rst
@@ -0,0 +1,269 @@
+Parallel Testing with nose
+--------------------------
+
+.. Note ::
+
+ Use of the multiprocess plugin on python 2.5 or earlier requires
+ the multiprocessing_ module, available from PyPI and at
+ http://code.google.com/p/python-multiprocessing/.
+
+..
+
+Using the `nose.plugin.multiprocess` plugin, you can parallelize a
+test run across a configurable number of worker processes. While this can
+speed up CPU-bound test runs, it is mainly useful for IO-bound tests
+that spend most of their time waiting for data to arrive from someplace
+else and can benefit from parallelization.
+
+.. _multiprocessing : http://code.google.com/p/python-multiprocessing/
+
+How tests are distributed
+=========================
+
+The ideal case would be to dispatch each test to a worker process separately,
+and to have enough worker processes that the entire test run takes only as
+long as the slowest test. This ideal is not attainable in all cases, however,
+because many test suites depend on context (class, module or package)
+fixtures.
+
+Some context fixtures are re-entrant -- that is, they can be called many times
+concurrently. Other context fixtures can be shared among tests running in
+different processes. Still others must be run once and only once for a given
+set of tests, and must be in the same process as the tests themselves.
+
+The plugin can't know the difference between these types of context fixtures
+unless you tell it, so the default behavior is to dispatch the entire context
+suite to a worker as a unit. This way, the fixtures are run once, in the same
+process as the tests. (That, of course, is how they are run when the plugin
+is not active: All tests are run in a single process.)
+
+Controlling distribution
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+There are two context-level variables that you can use to control this default
+behavior.
+
+If a context's fixtures are re-entrant, set ``_multiprocess_can_split_ = True``
+in the context, and the plugin will dispatch tests in suites bound to that
+context as if the context had no fixtures. This means that the fixtures will
+execute multiple times, typically once per test, and concurrently.
+
+For example, a module that contains re-entrant fixtures might look like::
+
+ _multiprocess_can_split_ = True
+
+ def setup():
+ ...
+
+A class might look like::
+
+ class TestClass:
+ _multiprocess_can_split_ = True
+
+ @classmethod
+ def setup_class(cls):
+ ...
+
+Alternatively, if a context's fixtures may only be run once, or may not run
+concurrently, but *may* be shared by tests running in different processes
+-- for instance a package-level fixture that starts an external http server or
+initializes a shared database -- then set ``_multiprocess_shared_ = True`` in
+the context. Fixtures for contexts so marked will execute in the primary nose
+process, and tests in those contexts will be individually dispatched to run in
+parallel.
+
+A module with shareable fixtures might look like::
+
+ _multiprocess_shared_ = True
+
+ def setup():
+ ...
+
+A class might look like::
+
+ class TestClass:
+ _multiprocess_shared_ = True
+
+ @classmethod
+ def setup_class(cls):
+ ...
+
+These options are mutually exclusive: you can't mark a context as both
+splittable and shareable.
+
+Example
+~~~~~~~
+
+Consider three versions of the same test suite. One
+is marked ``_multiprocess_shared_``, another ``_multiprocess_can_split_``,
+and the third is unmarked. They all define the same fixtures:
+
+ called = []
+
+ def setup():
+ print "setup called"
+ called.append('setup')
+
+ def teardown():
+ print "teardown called"
+ called.append('teardown')
+
+And each has two tests that just test that ``setup()`` has been called
+once and only once.
+
+When run without the multiprocess plugin, fixtures for the shared,
+can-split and not-shared test suites execute at the same times, and
+all tests pass.
+
+.. Note ::
+
+ The run() function in :mod:`nose.plugins.plugintest` reformats test result
+ output to remove timings, which will vary from run to run, and
+ redirects the output to stdout.
+
+ >>> from nose.plugins.plugintest import run_buffered as run
+
+..
+
+ >>> import os
+ >>> support = os.path.join(os.path.dirname(__file__), 'support')
+ >>> test_not_shared = os.path.join(support, 'test_not_shared.py')
+ >>> test_shared = os.path.join(support, 'test_shared.py')
+ >>> test_can_split = os.path.join(support, 'test_can_split.py')
+
+The module with shared fixtures passes.
+
+ >>> run(argv=['nosetests', '-v', test_shared]) #doctest: +REPORT_NDIFF
+ setup called
+ test_shared.TestMe.test_one ... ok
+ test_shared.test_a ... ok
+ test_shared.test_b ... ok
+ teardown called
+
+ ----------------------------------------------------------------------
+ Ran 3 tests in ...s
+
+ OK
+
+As does the module with no fixture annotations.
+
+ >>> run(argv=['nosetests', '-v', test_not_shared]) #doctest: +REPORT_NDIFF
+ setup called
+ test_not_shared.TestMe.test_one ... ok
+ test_not_shared.test_a ... ok
+ test_not_shared.test_b ... ok
+ teardown called
+
+ ----------------------------------------------------------------------
+ Ran 3 tests in ...s
+
+ OK
+
+And the module that marks its fixtures as re-entrant.
+
+ >>> run(argv=['nosetests', '-v', test_can_split]) #doctest: +REPORT_NDIFF
+ setup called
+ test_can_split.TestMe.test_one ... ok
+ test_can_split.test_a ... ok
+ test_can_split.test_b ... ok
+ teardown called
+
+ ----------------------------------------------------------------------
+ Ran 3 tests in ...s
+
+ OK
+
+However, when run with the ``--processes=2`` switch, each test module
+behaves differently.
+
+ >>> from nose.plugins.multiprocess import MultiProcess
+
+The module marked ``_multiprocess_shared_`` executes correctly, although as with
+any use of the multiprocess plugin, the order in which the tests execute is
+indeterminate.
+
+First we have to reset all of the test modules.
+
+ >>> import sys
+ >>> sys.modules['test_not_shared'].called[:] = []
+ >>> sys.modules['test_can_split'].called[:] = []
+
+Then we can run the tests again with the multiprocess plugin active.
+
+ >>> run(argv=['nosetests', '-v', '--processes=2', test_shared],
+ ... plugins=[MultiProcess()]) #doctest: +ELLIPSIS
+ setup called
+ test_shared.... ok
+ teardown called
+
+ ----------------------------------------------------------------------
+ Ran 3 tests in ...s
+
+ OK
+
+As does the one not marked -- however in this case, ``--processes=2``
+will do *nothing at all*: since the tests are in a module with
+unmarked fixtures, the entire test module will be dispatched to a
+single runner process.
+
+However, the module marked ``_multiprocess_can_split_`` will fail, since
+the fixtures *are not reentrant*. A module such as this *must not* be
+marked ``_multiprocess_can_split_``, or tests will fail in one or more
+runner processes as fixtures are re-executed.
+
+We have to reset all of the test modules again.
+
+ >>> import sys
+ >>> sys.modules['test_not_shared'].called[:] = []
+ >>> sys.modules['test_can_split'].called[:] = []
+
+Then we can run again and see the failures.
+
+ >>> run(argv=['nosetests', '-v', '--processes=2', test_can_split],
+ ... plugins=[MultiProcess()]) #doctest: +ELLIPSIS
+ setup called
+ teardown called
+ test_can_split....
+ ...
+ FAILED (failures=...)
+
+Other differences in test running
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The main difference between using the multiprocess plugin and not doing so
+is obviously that tests run concurrently under multiprocess. However, there
+are a few other differences that may impact your test suite:
+
+* More tests may be found
+
+ Because tests are dispatched to worker processes by name, a worker
+ process may find and run tests in a module that would not be found during a
+ normal test run. For instance, if a non-test module contains a test-like
+ function, that function would be discovered as a test in a worker process
+ if the entire module is dispatched to the worker. This is because worker
+ processes load tests in *directed* mode -- the same way that nose loads
+ tests when you explicitly name a module -- rather than in *discovered* mode,
+ the mode nose uses when looking for tests in a directory.
+
+* Out-of-order output
+
+ Test results are collected by workers and returned to the master process for
+ output. Since different processes may complete their tests at different
+ times, test result output order is not determinate.
+
+* Plugin interaction warning
+
+ The multiprocess plugin does not work well with other plugins that expect to
+ wrap or gain control of the test-running process. Examples from nose's
+ builtin plugins include coverage and profiling: a test run using
+ both multiprocess and either of those is likely to fail in some
+ confusing and spectacular way.
+
+* Python 2.6 warning
+
+ This is unlikely to impact you unless you are writing tests for nose itself,
+ but be aware that under python 2.6, the multiprocess plugin is not
+ re-entrant. For example, when running nose with the plugin active, you can't
+ use subprocess to launch another copy of nose that also uses the
+ multiprocess plugin. This is why this test is skipped under python 2.6 when
+ run with the ``--processes`` switch.
diff --git a/functional_tests/doc_tests/test_multiprocess/multiprocess_fixtures.py b/functional_tests/doc_tests/test_multiprocess/multiprocess_fixtures.py
new file mode 100644
index 0000000..8b4c3af
--- /dev/null
+++ b/functional_tests/doc_tests/test_multiprocess/multiprocess_fixtures.py
@@ -0,0 +1,16 @@
+from nose.plugins.skip import SkipTest
+from nose.plugins.multiprocess import MultiProcess
+
+_multiprocess_can_split_ = True
+
+def setup_module():
+ try:
+ import multiprocessing
+ if 'active' in MultiProcess.status:
+ raise SkipTest("Multiprocess plugin is active. Skipping tests of "
+ "plugin itself.")
+ except ImportError:
+ raise SkipTest("multiprocessing module not available")
+
+
+
diff --git a/functional_tests/doc_tests/test_multiprocess/multiprocess_fixtures.pyc b/functional_tests/doc_tests/test_multiprocess/multiprocess_fixtures.pyc
new file mode 100644
index 0000000..bbd8eb3
Binary files /dev/null and b/functional_tests/doc_tests/test_multiprocess/multiprocess_fixtures.pyc differ
diff --git a/functional_tests/doc_tests/test_multiprocess/support/test_can_split.py b/functional_tests/doc_tests/test_multiprocess/support/test_can_split.py
new file mode 100644
index 0000000..a7ae6e7
--- /dev/null
+++ b/functional_tests/doc_tests/test_multiprocess/support/test_can_split.py
@@ -0,0 +1,30 @@
+import sys
+called = []
+
+_multiprocess_can_split_ = 1
+
+def setup():
+ print >> sys.stderr, "setup called"
+ called.append('setup')
+
+
+def teardown():
+ print >> sys.stderr, "teardown called"
+ called.append('teardown')
+
+
+def test_a():
+ assert len(called) == 1, "len(%s) !=1" % called
+
+
+def test_b():
+ assert len(called) == 1, "len(%s) !=1" % called
+
+
+class TestMe:
+ def setup_class(cls):
+ cls._setup = True
+ setup_class = classmethod(setup_class)
+
+ def test_one(self):
+ assert self._setup, "Class was not set up"
diff --git a/functional_tests/doc_tests/test_multiprocess/support/test_can_split.pyc b/functional_tests/doc_tests/test_multiprocess/support/test_can_split.pyc
new file mode 100644
index 0000000..71a0524
Binary files /dev/null and b/functional_tests/doc_tests/test_multiprocess/support/test_can_split.pyc differ
diff --git a/functional_tests/doc_tests/test_multiprocess/support/test_not_shared.py b/functional_tests/doc_tests/test_multiprocess/support/test_not_shared.py
new file mode 100644
index 0000000..8542109
--- /dev/null
+++ b/functional_tests/doc_tests/test_multiprocess/support/test_not_shared.py
@@ -0,0 +1,30 @@
+import sys
+called = []
+
+_multiprocess_ = 1
+
+def setup():
+ print >> sys.stderr, "setup called"
+ called.append('setup')
+
+
+def teardown():
+ print >> sys.stderr, "teardown called"
+ called.append('teardown')
+
+
+def test_a():
+ assert len(called) == 1, "len(%s) !=1" % called
+
+
+def test_b():
+ assert len(called) == 1, "len(%s) !=1" % called
+
+
+class TestMe:
+ def setup_class(cls):
+ cls._setup = True
+ setup_class = classmethod(setup_class)
+
+ def test_one(self):
+ assert self._setup, "Class was not set up"
diff --git a/functional_tests/doc_tests/test_multiprocess/support/test_not_shared.pyc b/functional_tests/doc_tests/test_multiprocess/support/test_not_shared.pyc
new file mode 100644
index 0000000..6e7d0c7
Binary files /dev/null and b/functional_tests/doc_tests/test_multiprocess/support/test_not_shared.pyc differ
diff --git a/functional_tests/doc_tests/test_multiprocess/support/test_shared.py b/functional_tests/doc_tests/test_multiprocess/support/test_shared.py
new file mode 100644
index 0000000..d8617f8
--- /dev/null
+++ b/functional_tests/doc_tests/test_multiprocess/support/test_shared.py
@@ -0,0 +1,49 @@
+import os
+import sys
+
+here = os.path.dirname(__file__)
+flag = os.path.join(here, 'shared_flag')
+
+_multiprocess_shared_ = 1
+
+def _log(val):
+ ff = open(flag, 'a+')
+ ff.write(val)
+ ff.write("\n")
+ ff.close()
+
+
+def _clear():
+ if os.path.isfile(flag):
+ os.unlink(flag)
+
+
+def logged():
+ return [line for line in open(flag, 'r')]
+
+
+def setup():
+ print >> sys.stderr, "setup called"
+ _log('setup')
+
+
+def teardown():
+ print >> sys.stderr, "teardown called"
+ _clear()
+
+
+def test_a():
+ assert len(logged()) == 1, "len(%s) !=1" % called
+
+
+def test_b():
+ assert len(logged()) == 1, "len(%s) !=1" % called
+
+
+class TestMe:
+ def setup_class(cls):
+ cls._setup = True
+ setup_class = classmethod(setup_class)
+
+ def test_one(self):
+ assert self._setup, "Class was not set up"
diff --git a/functional_tests/doc_tests/test_multiprocess/support/test_shared.pyc b/functional_tests/doc_tests/test_multiprocess/support/test_shared.pyc
new file mode 100644
index 0000000..720ceb6
Binary files /dev/null and b/functional_tests/doc_tests/test_multiprocess/support/test_shared.pyc differ
diff --git a/functional_tests/doc_tests/test_restricted_plugin_options/restricted_plugin_options.rst b/functional_tests/doc_tests/test_restricted_plugin_options/restricted_plugin_options.rst
new file mode 100644
index 0000000..9513fdf
--- /dev/null
+++ b/functional_tests/doc_tests/test_restricted_plugin_options/restricted_plugin_options.rst
@@ -0,0 +1,89 @@
+Restricted Plugin Managers
+--------------------------
+
+In some cases, such as running under the ``python setup.py test`` command,
+nose is not able to use all available plugins. In those cases, a
+`nose.plugins.manager.RestrictedPluginManager` is used to exclude plugins that
+implement API methods that nose is unable to call.
+
+Support files for this test are in the support directory.
+
+ >>> import os
+ >>> support = os.path.join(os.path.dirname(__file__), 'support')
+
+For this test, we'll use a simple plugin that implements the ``startTest``
+method.
+
+ >>> from nose.plugins.base import Plugin
+ >>> from nose.plugins.manager import RestrictedPluginManager
+ >>> class StartPlugin(Plugin):
+ ... def startTest(self, test):
+ ... print "started %s" % test
+
+.. Note ::
+
+ The run() function in :mod:`nose.plugins.plugintest` reformats test result
+ output to remove timings, which will vary from run to run, and
+ redirects the output to stdout.
+
+ >>> from nose.plugins.plugintest import run_buffered as run
+
+..
+
+When run with a normal plugin manager, the plugin executes.
+
+ >>> argv = ['plugintest', '-v', '--with-startplugin', support]
+ >>> run(argv=argv, plugins=[StartPlugin()]) # doctest: +REPORT_NDIFF
+ started test.test
+ test.test ... ok
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ OK
+
+However, when run with a restricted plugin manager configured to exclude
+plugins implementing `startTest`, an exception is raised and nose exits.
+
+ >>> restricted = RestrictedPluginManager(
+ ... plugins=[StartPlugin()], exclude=('startTest',), load=False)
+ >>> run(argv=argv, plugins=restricted) #doctest: +REPORT_NDIFF +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ SystemExit: ...
+
+Errors are only raised when options defined by excluded plugins are used.
+
+ >>> argv = ['plugintest', '-v', support]
+ >>> run(argv=argv, plugins=restricted) # doctest: +REPORT_NDIFF
+ test.test ... ok
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ OK
+
+When a disabled option appears in a configuration file, instead of on the
+command line, a warning is raised instead of an exception.
+
+ >>> argv = ['plugintest', '-v', '-c', os.path.join(support, 'start.cfg'),
+ ... support]
+ >>> run(argv=argv, plugins=restricted) # doctest: +ELLIPSIS
+ RuntimeWarning: Option 'with-startplugin' in config file '...start.cfg' ignored: excluded by runtime environment
+ test.test ... ok
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ OK
+
+However, if an option appears in a configuration file that is not recognized
+either as an option defined by nose, or by an active or excluded plugin, an
+error is raised.
+
+ >>> argv = ['plugintest', '-v', '-c', os.path.join(support, 'bad.cfg'),
+ ... support]
+ >>> run(argv=argv, plugins=restricted) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ ConfigError: Error reading config file '...bad.cfg': no such option 'with-meltedcheese'
diff --git a/functional_tests/doc_tests/test_restricted_plugin_options/restricted_plugin_options.rst.py3.patch b/functional_tests/doc_tests/test_restricted_plugin_options/restricted_plugin_options.rst.py3.patch
new file mode 100644
index 0000000..51a09b4
--- /dev/null
+++ b/functional_tests/doc_tests/test_restricted_plugin_options/restricted_plugin_options.rst.py3.patch
@@ -0,0 +1,9 @@
+--- restricted_plugin_options.rst.orig 2010-08-31 10:57:04.000000000 -0700
++++ restricted_plugin_options.rst 2010-08-31 10:57:51.000000000 -0700
+@@ -86,5 +86,5 @@
+ >>> run(argv=argv, plugins=restricted) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+- ConfigError: Error reading config file '...bad.cfg': no such option 'with-meltedcheese'
++ nose.config.ConfigError: Error reading config file '...bad.cfg': no such option 'with-meltedcheese'
+
diff --git a/functional_tests/doc_tests/test_restricted_plugin_options/support/bad.cfg b/functional_tests/doc_tests/test_restricted_plugin_options/support/bad.cfg
new file mode 100644
index 0000000..c050ec4
--- /dev/null
+++ b/functional_tests/doc_tests/test_restricted_plugin_options/support/bad.cfg
@@ -0,0 +1,2 @@
+[nosetests]
+with-meltedcheese=1
\ No newline at end of file
diff --git a/functional_tests/doc_tests/test_restricted_plugin_options/support/start.cfg b/functional_tests/doc_tests/test_restricted_plugin_options/support/start.cfg
new file mode 100644
index 0000000..ea1e289
--- /dev/null
+++ b/functional_tests/doc_tests/test_restricted_plugin_options/support/start.cfg
@@ -0,0 +1,2 @@
+[nosetests]
+with-startplugin=1
\ No newline at end of file
diff --git a/functional_tests/doc_tests/test_restricted_plugin_options/support/test.py b/functional_tests/doc_tests/test_restricted_plugin_options/support/test.py
new file mode 100644
index 0000000..f174823
--- /dev/null
+++ b/functional_tests/doc_tests/test_restricted_plugin_options/support/test.py
@@ -0,0 +1,2 @@
+def test():
+ pass
diff --git a/functional_tests/doc_tests/test_restricted_plugin_options/support/test.pyc b/functional_tests/doc_tests/test_restricted_plugin_options/support/test.pyc
new file mode 100644
index 0000000..b0541be
Binary files /dev/null and b/functional_tests/doc_tests/test_restricted_plugin_options/support/test.pyc differ
diff --git a/functional_tests/doc_tests/test_selector_plugin/selector_plugin.rst b/functional_tests/doc_tests/test_selector_plugin/selector_plugin.rst
new file mode 100644
index 0000000..f5f7913
--- /dev/null
+++ b/functional_tests/doc_tests/test_selector_plugin/selector_plugin.rst
@@ -0,0 +1,119 @@
+Using a Custom Selector
+-----------------------
+
+By default, nose uses a `nose.selector.Selector` instance to decide
+what is and is not a test. The default selector is fairly simple: for
+the most part, if an object's name matches the ``testMatch`` regular
+expression defined in the active `nose.config.Config` instance, the
+object is selected as a test.
+
+This behavior is fine for new projects, but may be undesireable for
+older projects with a different test naming scheme. Fortunately, you
+can easily override this behavior by providing a custom selector using
+a plugin.
+
+ >>> import os
+ >>> support = os.path.join(os.path.dirname(__file__), 'support')
+
+In this example, the project to be tested consists of a module and
+package and associated tests, laid out like this::
+
+ >>> from nose.util import ls_tree
+ >>> print ls_tree(support)
+ |-- mymodule.py
+ |-- mypackage
+ | |-- __init__.py
+ | |-- strings.py
+ | `-- math
+ | |-- __init__.py
+ | `-- basic.py
+ `-- tests
+ |-- testlib.py
+ |-- math
+ | `-- basic.py
+ |-- mymodule
+ | `-- my_function.py
+ `-- strings
+ `-- cat.py
+
+Because the test modules do not include ``test`` in their names,
+nose's default selector is unable to discover this project's tests.
+
+.. Note ::
+
+ The run() function in :mod:`nose.plugins.plugintest` reformats test result
+ output to remove timings, which will vary from run to run, and
+ redirects the output to stdout.
+
+ >>> from nose.plugins.plugintest import run_buffered as run
+
+..
+
+ >>> argv = [__file__, '-v', support]
+ >>> run(argv=argv)
+ ----------------------------------------------------------------------
+ Ran 0 tests in ...s
+
+ OK
+
+The tests for the example project follow a few basic conventions:
+
+* The are all located under the tests/ directory.
+* Test modules are organized into groups under directories named for
+ the module or package they test.
+* testlib is *not* a test module, but it must be importable by the
+ test modules.
+* Test modules contain unitest.TestCase classes that are tests, and
+ may contain other functions or classes that are NOT tests, no matter
+ how they are named.
+
+We can codify those conventions in a selector class.
+
+ >>> from nose.selector import Selector
+ >>> import unittest
+ >>> class MySelector(Selector):
+ ... def wantDirectory(self, dirname):
+ ... # we want the tests directory and all directories
+ ... # beneath it, and no others
+ ... parts = dirname.split(os.path.sep)
+ ... return 'tests' in parts
+ ... def wantFile(self, filename):
+ ... # we want python modules under tests/, except testlib
+ ... parts = filename.split(os.path.sep)
+ ... base, ext = os.path.splitext(parts[-1])
+ ... return 'tests' in parts and ext == '.py' and base != 'testlib'
+ ... def wantModule(self, module):
+ ... # wantDirectory and wantFile above will ensure that
+ ... # we never see an unwanted module
+ ... return True
+ ... def wantFunction(self, function):
+ ... # never collect functions
+ ... return False
+ ... def wantClass(self, cls):
+ ... # only collect TestCase subclasses
+ ... return issubclass(cls, unittest.TestCase)
+
+To use our selector class, we need a plugin that can inject it into
+the test loader.
+
+ >>> from nose.plugins import Plugin
+ >>> class UseMySelector(Plugin):
+ ... enabled = True
+ ... def configure(self, options, conf):
+ ... pass # always on
+ ... def prepareTestLoader(self, loader):
+ ... loader.selector = MySelector(loader.config)
+
+Now we can execute a test run using the custom selector, and the
+project's tests will be collected.
+
+ >>> run(argv=argv, plugins=[UseMySelector()])
+ test_add (basic.TestBasicMath) ... ok
+ test_sub (basic.TestBasicMath) ... ok
+ test_tuple_groups (my_function.MyFunction) ... ok
+ test_cat (cat.StringsCat) ... ok
+
+ ----------------------------------------------------------------------
+ Ran 4 tests in ...s
+
+ OK
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/mymodule.py b/functional_tests/doc_tests/test_selector_plugin/support/mymodule.py
new file mode 100644
index 0000000..66b3c16
--- /dev/null
+++ b/functional_tests/doc_tests/test_selector_plugin/support/mymodule.py
@@ -0,0 +1,2 @@
+def my_function(a, b, c):
+ return (a, (b, c))
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/mymodule.pyc b/functional_tests/doc_tests/test_selector_plugin/support/mymodule.pyc
new file mode 100644
index 0000000..4fa6953
Binary files /dev/null and b/functional_tests/doc_tests/test_selector_plugin/support/mymodule.pyc differ
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/mypackage/__init__.py b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/__init__.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/__init__.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/mypackage/__init__.pyc b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/__init__.pyc
new file mode 100644
index 0000000..ee0e388
Binary files /dev/null and b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/__init__.pyc differ
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/__init__.py b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/__init__.py
new file mode 100644
index 0000000..04e0659
--- /dev/null
+++ b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/__init__.py
@@ -0,0 +1 @@
+from mypackage.math.basic import *
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/__init__.pyc b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/__init__.pyc
new file mode 100644
index 0000000..1b504ed
Binary files /dev/null and b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/__init__.pyc differ
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/basic.py b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/basic.py
new file mode 100644
index 0000000..6cddd28
--- /dev/null
+++ b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/basic.py
@@ -0,0 +1,5 @@
+def add(a, b):
+ return a + b
+
+def sub(a, b):
+ return a - b
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/basic.pyc b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/basic.pyc
new file mode 100644
index 0000000..4733dd8
Binary files /dev/null and b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/basic.pyc differ
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/mypackage/strings.py b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/strings.py
new file mode 100644
index 0000000..8ffc4cc
--- /dev/null
+++ b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/strings.py
@@ -0,0 +1,2 @@
+def cat(a, b):
+ return "%s%s" % (a, b)
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/mypackage/strings.pyc b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/strings.pyc
new file mode 100644
index 0000000..7be95ab
Binary files /dev/null and b/functional_tests/doc_tests/test_selector_plugin/support/mypackage/strings.pyc differ
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/tests/math/basic.py b/functional_tests/doc_tests/test_selector_plugin/support/tests/math/basic.py
new file mode 100644
index 0000000..7639ddc
--- /dev/null
+++ b/functional_tests/doc_tests/test_selector_plugin/support/tests/math/basic.py
@@ -0,0 +1,17 @@
+import testlib
+from mypackage import math
+
+
+class TestBasicMath(testlib.Base):
+
+ def test_add(self):
+ self.assertEqual(math.add(1, 2), 3)
+
+ def test_sub(self):
+ self.assertEqual(math.sub(3, 1), 2)
+
+
+class TestHelperClass:
+ def __init__(self):
+ raise Exception(
+ "This test helper class should not be collected")
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/tests/math/basic.pyc b/functional_tests/doc_tests/test_selector_plugin/support/tests/math/basic.pyc
new file mode 100644
index 0000000..9862bca
Binary files /dev/null and b/functional_tests/doc_tests/test_selector_plugin/support/tests/math/basic.pyc differ
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/tests/mymodule/my_function.py b/functional_tests/doc_tests/test_selector_plugin/support/tests/mymodule/my_function.py
new file mode 100644
index 0000000..85808c9
--- /dev/null
+++ b/functional_tests/doc_tests/test_selector_plugin/support/tests/mymodule/my_function.py
@@ -0,0 +1,7 @@
+import mymodule
+import testlib
+
+class MyFunction(testlib.Base):
+
+ def test_tuple_groups(self):
+ self.assertEqual(mymodule.my_function(1, 2, 3), (1, (2, 3)))
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/tests/mymodule/my_function.pyc b/functional_tests/doc_tests/test_selector_plugin/support/tests/mymodule/my_function.pyc
new file mode 100644
index 0000000..57968fd
Binary files /dev/null and b/functional_tests/doc_tests/test_selector_plugin/support/tests/mymodule/my_function.pyc differ
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/tests/strings/cat.py b/functional_tests/doc_tests/test_selector_plugin/support/tests/strings/cat.py
new file mode 100644
index 0000000..3b410e8
--- /dev/null
+++ b/functional_tests/doc_tests/test_selector_plugin/support/tests/strings/cat.py
@@ -0,0 +1,12 @@
+import testlib
+from mypackage import strings
+
+class StringsCat(testlib.Base):
+
+ def test_cat(self):
+ self.assertEqual(strings.cat('one', 'two'), 'onetwo')
+
+
+def test_helper_function():
+ raise Exception(
+ "This test helper function should not be collected")
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/tests/strings/cat.pyc b/functional_tests/doc_tests/test_selector_plugin/support/tests/strings/cat.pyc
new file mode 100644
index 0000000..36a91f2
Binary files /dev/null and b/functional_tests/doc_tests/test_selector_plugin/support/tests/strings/cat.pyc differ
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/tests/testlib.py b/functional_tests/doc_tests/test_selector_plugin/support/tests/testlib.py
new file mode 100644
index 0000000..92c4f96
--- /dev/null
+++ b/functional_tests/doc_tests/test_selector_plugin/support/tests/testlib.py
@@ -0,0 +1,6 @@
+import unittest
+
+class Base(unittest.TestCase):
+ """Use this base class for all tests.
+ """
+ pass
diff --git a/functional_tests/doc_tests/test_selector_plugin/support/tests/testlib.pyc b/functional_tests/doc_tests/test_selector_plugin/support/tests/testlib.pyc
new file mode 100644
index 0000000..bb47670
Binary files /dev/null and b/functional_tests/doc_tests/test_selector_plugin/support/tests/testlib.pyc differ
diff --git a/functional_tests/doc_tests/test_xunit_plugin/support/nosetests.xml b/functional_tests/doc_tests/test_xunit_plugin/support/nosetests.xml
new file mode 100644
index 0000000..1d242f5
--- /dev/null
+++ b/functional_tests/doc_tests/test_xunit_plugin/support/nosetests.xml
@@ -0,0 +1,25 @@
+
\ No newline at end of file
diff --git a/functional_tests/doc_tests/test_xunit_plugin/support/test_skip.py b/functional_tests/doc_tests/test_xunit_plugin/support/test_skip.py
new file mode 100644
index 0000000..cb26c41
--- /dev/null
+++ b/functional_tests/doc_tests/test_xunit_plugin/support/test_skip.py
@@ -0,0 +1,13 @@
+from nose.exc import SkipTest
+
+def test_ok():
+ pass
+
+def test_err():
+ raise Exception("oh no")
+
+def test_fail():
+ assert False, "bye"
+
+def test_skip():
+ raise SkipTest("not me")
diff --git a/functional_tests/doc_tests/test_xunit_plugin/support/test_skip.pyc b/functional_tests/doc_tests/test_xunit_plugin/support/test_skip.pyc
new file mode 100644
index 0000000..f9204ad
Binary files /dev/null and b/functional_tests/doc_tests/test_xunit_plugin/support/test_skip.pyc differ
diff --git a/functional_tests/doc_tests/test_xunit_plugin/test_skips.rst b/functional_tests/doc_tests/test_xunit_plugin/test_skips.rst
new file mode 100644
index 0000000..c0c3fbc
--- /dev/null
+++ b/functional_tests/doc_tests/test_xunit_plugin/test_skips.rst
@@ -0,0 +1,40 @@
+XUnit output supports skips
+---------------------------
+
+>>> import os
+>>> from nose.plugins.xunit import Xunit
+>>> from nose.plugins.skip import SkipTest, Skip
+>>> support = os.path.join(os.path.dirname(__file__), 'support')
+>>> outfile = os.path.join(support, 'nosetests.xml')
+>>> from nose.plugins.plugintest import run_buffered as run
+>>> argv = [__file__, '-v', '--with-xunit', support,
+... '--xunit-file=%s' % outfile]
+>>> run(argv=argv, plugins=[Xunit(), Skip()]) # doctest: +ELLIPSIS
+test_skip.test_ok ... ok
+test_skip.test_err ... ERROR
+test_skip.test_fail ... FAIL
+test_skip.test_skip ... SKIP: not me
+
+======================================================================
+ERROR: test_skip.test_err
+----------------------------------------------------------------------
+Traceback (most recent call last):
+...
+Exception: oh no
+
+======================================================================
+FAIL: test_skip.test_fail
+----------------------------------------------------------------------
+Traceback (most recent call last):
+...
+AssertionError: bye
+
+----------------------------------------------------------------------
+XML: ...nosetests.xml
+----------------------------------------------------------------------
+Ran 4 tests in ...s
+
+FAILED (SKIP=1, errors=1, failures=1)
+
+>>> open(outfile, 'r').read() # doctest: +ELLIPSIS
+'.........'
diff --git a/functional_tests/support/att/test_attr.py b/functional_tests/support/att/test_attr.py
new file mode 100644
index 0000000..dd2f292
--- /dev/null
+++ b/functional_tests/support/att/test_attr.py
@@ -0,0 +1,96 @@
+from nose.plugins.attrib import attr
+import unittest
+
+def test_one():
+ pass
+test_one.a = 1
+test_one.d = [1, 2]
+
+
+def test_two():
+ pass
+test_two.a = 1
+test_two.c = 20
+test_two.d = [2, 3]
+
+def test_three():
+ pass
+test_three.b = 1
+test_three.d = [1, 3]
+
+class TestClass:
+ a = 1
+ def test_class_one(self):
+ pass
+
+ def test_class_two(self):
+ pass
+ test_class_two.b = 2
+
+ def test_class_three(self):
+ pass
+
+
+class Something(unittest.TestCase):
+ b = 2
+ def test_case_one(self):
+ pass
+
+ def test_case_two(self):
+ pass
+ test_case_two.c = 50
+
+ def test_case_three(self):
+ pass
+
+
+class Superclass:
+ def test_method(self):
+ pass
+ test_method.from_super = True
+
+class TestSubclass(Superclass):
+ pass
+
+
+class Static:
+ def test_with_static(self):
+ pass
+ test_with_static.with_static = True
+
+ def static(self):
+ pass
+ static = staticmethod(static)
+
+
+class TestClassAndMethodAttrs(unittest.TestCase):
+ def test_method(self):
+ pass
+ test_method.meth_attr = 'method'
+TestClassAndMethodAttrs.cls_attr = 'class'
+
+
+class TestAttrClass:
+ from_super = True
+
+ def ends_with_test(self):
+ pass
+
+ def test_one(self):
+ pass
+
+ def test_two(self):
+ pass
+ test_two.from_super = False
+
+TestAttrClass = attr('a')(TestAttrClass)
+
+
+class TestAttrSubClass(TestAttrClass):
+ def test_sub_three(self):
+ pass
+
+def added_later_test(self):
+ pass
+
+TestAttrSubClass.added_later_test = added_later_test
diff --git a/functional_tests/support/att/test_attr.pyc b/functional_tests/support/att/test_attr.pyc
new file mode 100644
index 0000000..02c14fd
Binary files /dev/null and b/functional_tests/support/att/test_attr.pyc differ
diff --git a/functional_tests/support/coverage/blah.py b/functional_tests/support/coverage/blah.py
new file mode 100644
index 0000000..ef6657c
--- /dev/null
+++ b/functional_tests/support/coverage/blah.py
@@ -0,0 +1,6 @@
+def dostuff():
+ print 'hi'
+
+
+def notcov():
+ print 'not covered'
diff --git a/functional_tests/support/coverage/blah.pyc b/functional_tests/support/coverage/blah.pyc
new file mode 100644
index 0000000..6753b9f
Binary files /dev/null and b/functional_tests/support/coverage/blah.pyc differ
diff --git a/functional_tests/support/coverage/tests/test_covered.py b/functional_tests/support/coverage/tests/test_covered.py
new file mode 100644
index 0000000..c669c5c
--- /dev/null
+++ b/functional_tests/support/coverage/tests/test_covered.py
@@ -0,0 +1,4 @@
+import blah
+
+def test_blah():
+ blah.dostuff()
diff --git a/functional_tests/support/coverage/tests/test_covered.pyc b/functional_tests/support/coverage/tests/test_covered.pyc
new file mode 100644
index 0000000..29c6755
Binary files /dev/null and b/functional_tests/support/coverage/tests/test_covered.pyc differ
diff --git a/functional_tests/support/coverage2/blah.py b/functional_tests/support/coverage2/blah.py
new file mode 100644
index 0000000..ef6657c
--- /dev/null
+++ b/functional_tests/support/coverage2/blah.py
@@ -0,0 +1,6 @@
+def dostuff():
+ print 'hi'
+
+
+def notcov():
+ print 'not covered'
diff --git a/functional_tests/support/coverage2/moo.py b/functional_tests/support/coverage2/moo.py
new file mode 100644
index 0000000..7ad09bf
--- /dev/null
+++ b/functional_tests/support/coverage2/moo.py
@@ -0,0 +1,2 @@
+def moo():
+ print 'covered'
diff --git a/functional_tests/support/coverage2/moo.pyc b/functional_tests/support/coverage2/moo.pyc
new file mode 100644
index 0000000..303750b
Binary files /dev/null and b/functional_tests/support/coverage2/moo.pyc differ
diff --git a/functional_tests/support/coverage2/tests/test_covered.py b/functional_tests/support/coverage2/tests/test_covered.py
new file mode 100644
index 0000000..034f984
--- /dev/null
+++ b/functional_tests/support/coverage2/tests/test_covered.py
@@ -0,0 +1,8 @@
+import blah
+import moo
+
+def test_blah():
+ blah.dostuff()
+
+def test_moo():
+ moo.dostuff()
diff --git a/functional_tests/support/coverage2/tests/test_covered.pyc b/functional_tests/support/coverage2/tests/test_covered.pyc
new file mode 100644
index 0000000..0f94350
Binary files /dev/null and b/functional_tests/support/coverage2/tests/test_covered.pyc differ
diff --git a/functional_tests/support/ctx/mod_import_skip.py b/functional_tests/support/ctx/mod_import_skip.py
new file mode 100644
index 0000000..3a5af10
--- /dev/null
+++ b/functional_tests/support/ctx/mod_import_skip.py
@@ -0,0 +1,9 @@
+from nose import SkipTest
+
+raise SkipTest("Don't run me")
+
+def test():
+ assert False, "Should not be run"
+
+def test2():
+ assert False, "Should not be run"
diff --git a/functional_tests/support/ctx/mod_import_skip.pyc b/functional_tests/support/ctx/mod_import_skip.pyc
new file mode 100644
index 0000000..c541041
Binary files /dev/null and b/functional_tests/support/ctx/mod_import_skip.pyc differ
diff --git a/functional_tests/support/ctx/mod_setup_fails.py b/functional_tests/support/ctx/mod_setup_fails.py
new file mode 100644
index 0000000..d7f49bc
--- /dev/null
+++ b/functional_tests/support/ctx/mod_setup_fails.py
@@ -0,0 +1,12 @@
+def setup():
+ assert False, "Failure in mod setup"
+
+
+def test_a():
+ raise AssertionError("test_a should not run")
+
+
+def test_b():
+ raise AssertionError("test_b should not run")
+
+
diff --git a/functional_tests/support/ctx/mod_setup_fails.pyc b/functional_tests/support/ctx/mod_setup_fails.pyc
new file mode 100644
index 0000000..649bc11
Binary files /dev/null and b/functional_tests/support/ctx/mod_setup_fails.pyc differ
diff --git a/functional_tests/support/ctx/mod_setup_skip.py b/functional_tests/support/ctx/mod_setup_skip.py
new file mode 100644
index 0000000..6e5ec65
--- /dev/null
+++ b/functional_tests/support/ctx/mod_setup_skip.py
@@ -0,0 +1,14 @@
+from nose import SkipTest
+
+def setup():
+ raise SkipTest("no thanks")
+
+
+def test_a():
+ raise AssertionError("test_a should not run")
+
+
+def test_b():
+ raise AssertionError("test_b should not run")
+
+
diff --git a/functional_tests/support/ctx/mod_setup_skip.pyc b/functional_tests/support/ctx/mod_setup_skip.pyc
new file mode 100644
index 0000000..3085b29
Binary files /dev/null and b/functional_tests/support/ctx/mod_setup_skip.pyc differ
diff --git a/functional_tests/support/dir1/mod.py b/functional_tests/support/dir1/mod.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/support/dir1/mod.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/support/dir1/mod.pyc b/functional_tests/support/dir1/mod.pyc
new file mode 100644
index 0000000..31d316b
Binary files /dev/null and b/functional_tests/support/dir1/mod.pyc differ
diff --git a/functional_tests/support/dir1/pak/__init__.py b/functional_tests/support/dir1/pak/__init__.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/support/dir1/pak/__init__.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/support/dir1/pak/__init__.pyc b/functional_tests/support/dir1/pak/__init__.pyc
new file mode 100644
index 0000000..0afffa2
Binary files /dev/null and b/functional_tests/support/dir1/pak/__init__.pyc differ
diff --git a/functional_tests/support/dir1/pak/mod.py b/functional_tests/support/dir1/pak/mod.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/support/dir1/pak/mod.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/support/dir1/pak/mod.pyc b/functional_tests/support/dir1/pak/mod.pyc
new file mode 100644
index 0000000..0083bbc
Binary files /dev/null and b/functional_tests/support/dir1/pak/mod.pyc differ
diff --git a/functional_tests/support/dir1/pak/sub/__init__.py b/functional_tests/support/dir1/pak/sub/__init__.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/support/dir1/pak/sub/__init__.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/support/dir1/pak/sub/__init__.pyc b/functional_tests/support/dir1/pak/sub/__init__.pyc
new file mode 100644
index 0000000..cfe6b8a
Binary files /dev/null and b/functional_tests/support/dir1/pak/sub/__init__.pyc differ
diff --git a/functional_tests/support/dir2/mod.py b/functional_tests/support/dir2/mod.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/support/dir2/mod.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/support/dir2/mod.pyc b/functional_tests/support/dir2/mod.pyc
new file mode 100644
index 0000000..aacf3c0
Binary files /dev/null and b/functional_tests/support/dir2/mod.pyc differ
diff --git a/functional_tests/support/dir2/pak/__init__.py b/functional_tests/support/dir2/pak/__init__.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/support/dir2/pak/__init__.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/support/dir2/pak/__init__.pyc b/functional_tests/support/dir2/pak/__init__.pyc
new file mode 100644
index 0000000..020a6fc
Binary files /dev/null and b/functional_tests/support/dir2/pak/__init__.pyc differ
diff --git a/functional_tests/support/dir2/pak/mod.py b/functional_tests/support/dir2/pak/mod.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/support/dir2/pak/mod.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/support/dir2/pak/mod.pyc b/functional_tests/support/dir2/pak/mod.pyc
new file mode 100644
index 0000000..003d12b
Binary files /dev/null and b/functional_tests/support/dir2/pak/mod.pyc differ
diff --git a/functional_tests/support/dir2/pak/sub/__init__.py b/functional_tests/support/dir2/pak/sub/__init__.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/support/dir2/pak/sub/__init__.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/support/dir2/pak/sub/__init__.pyc b/functional_tests/support/dir2/pak/sub/__init__.pyc
new file mode 100644
index 0000000..9c72be0
Binary files /dev/null and b/functional_tests/support/dir2/pak/sub/__init__.pyc differ
diff --git a/functional_tests/support/dtt/docs/doc.txt b/functional_tests/support/dtt/docs/doc.txt
new file mode 100644
index 0000000..4cf3955
--- /dev/null
+++ b/functional_tests/support/dtt/docs/doc.txt
@@ -0,0 +1,6 @@
+This document is a doctest.
+
+ >>> 1 + 1
+ 2
+
+That's all
diff --git a/functional_tests/support/dtt/docs/errdoc.txt b/functional_tests/support/dtt/docs/errdoc.txt
new file mode 100644
index 0000000..a947b52
--- /dev/null
+++ b/functional_tests/support/dtt/docs/errdoc.txt
@@ -0,0 +1,7 @@
+This document contains an invalid doctest.
+
+ >>> def foo():
+ >>> def bar():
+ ... pass
+
+That is all.
diff --git a/functional_tests/support/dtt/docs/nodoc.txt b/functional_tests/support/dtt/docs/nodoc.txt
new file mode 100644
index 0000000..665f935
--- /dev/null
+++ b/functional_tests/support/dtt/docs/nodoc.txt
@@ -0,0 +1 @@
+This document contains no doctests.
diff --git a/functional_tests/support/dtt/some_mod.py b/functional_tests/support/dtt/some_mod.py
new file mode 100644
index 0000000..23880d5
--- /dev/null
+++ b/functional_tests/support/dtt/some_mod.py
@@ -0,0 +1,17 @@
+"""
+Top level
+---------
+
+Let's run a test.
+
+ >>> foo(1)
+ 2
+ >>> 2 + 2
+ 4
+"""
+def foo(a):
+ """
+ >>> foo(2)
+ 3
+ """
+ return a + 1
diff --git a/functional_tests/support/dtt/some_mod.pyc b/functional_tests/support/dtt/some_mod.pyc
new file mode 100644
index 0000000..10625c9
Binary files /dev/null and b/functional_tests/support/dtt/some_mod.pyc differ
diff --git a/functional_tests/support/empty/.hidden b/functional_tests/support/empty/.hidden
new file mode 100644
index 0000000..e69de29
diff --git a/functional_tests/support/ep/Some_plugin.egg-info/PKG-INFO b/functional_tests/support/ep/Some_plugin.egg-info/PKG-INFO
new file mode 100644
index 0000000..63420aa
--- /dev/null
+++ b/functional_tests/support/ep/Some_plugin.egg-info/PKG-INFO
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: Some-plugin
+Version: 0.0.0
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: UNKNOWN
+Author-email: UNKNOWN
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
diff --git a/functional_tests/support/ep/Some_plugin.egg-info/SOURCES.txt b/functional_tests/support/ep/Some_plugin.egg-info/SOURCES.txt
new file mode 100644
index 0000000..69e3e80
--- /dev/null
+++ b/functional_tests/support/ep/Some_plugin.egg-info/SOURCES.txt
@@ -0,0 +1,6 @@
+setup.py
+Some_plugin.egg-info/PKG-INFO
+Some_plugin.egg-info/SOURCES.txt
+Some_plugin.egg-info/dependency_links.txt
+Some_plugin.egg-info/entry_points.txt
+Some_plugin.egg-info/top_level.txt
diff --git a/functional_tests/support/ep/Some_plugin.egg-info/dependency_links.txt b/functional_tests/support/ep/Some_plugin.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/functional_tests/support/ep/Some_plugin.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/functional_tests/support/ep/Some_plugin.egg-info/entry_points.txt b/functional_tests/support/ep/Some_plugin.egg-info/entry_points.txt
new file mode 100644
index 0000000..3afd2db
--- /dev/null
+++ b/functional_tests/support/ep/Some_plugin.egg-info/entry_points.txt
@@ -0,0 +1,3 @@
+[nose.plugins.0.10]
+someplugin = someplugin:SomePlugin
+
diff --git a/functional_tests/support/ep/Some_plugin.egg-info/top_level.txt b/functional_tests/support/ep/Some_plugin.egg-info/top_level.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/functional_tests/support/ep/Some_plugin.egg-info/top_level.txt
@@ -0,0 +1 @@
+
diff --git a/functional_tests/support/ep/setup.py b/functional_tests/support/ep/setup.py
new file mode 100644
index 0000000..e751d18
--- /dev/null
+++ b/functional_tests/support/ep/setup.py
@@ -0,0 +1,10 @@
+from setuptools import setup, find_packages
+
+setup(
+ name='Some plugin',
+ packages = find_packages(),
+ entry_points = {
+ 'nose.plugins.0.10': [
+ 'someplugin = someplugin:SomePlugin'
+ ]
+ })
diff --git a/functional_tests/support/ep/someplugin.py b/functional_tests/support/ep/someplugin.py
new file mode 100644
index 0000000..3442a2d
--- /dev/null
+++ b/functional_tests/support/ep/someplugin.py
@@ -0,0 +1,4 @@
+from nose.plugins import Plugin
+
+class SomePlugin(Plugin):
+ pass
diff --git a/functional_tests/support/fdp/test_fdp.py b/functional_tests/support/fdp/test_fdp.py
new file mode 100644
index 0000000..bcaab0d
--- /dev/null
+++ b/functional_tests/support/fdp/test_fdp.py
@@ -0,0 +1,10 @@
+def test_err():
+ raise TypeError("I can't type")
+
+def test_fail():
+ print "Hello"
+ a = 2
+ assert a == 4, "a is not 4"
+
+def test_ok():
+ pass
diff --git a/functional_tests/support/fdp/test_fdp.pyc b/functional_tests/support/fdp/test_fdp.pyc
new file mode 100644
index 0000000..8d7554d
Binary files /dev/null and b/functional_tests/support/fdp/test_fdp.pyc differ
diff --git a/functional_tests/support/fdp/test_fdp_no_capt.py b/functional_tests/support/fdp/test_fdp_no_capt.py
new file mode 100644
index 0000000..30b7b99
--- /dev/null
+++ b/functional_tests/support/fdp/test_fdp_no_capt.py
@@ -0,0 +1,9 @@
+def test_err():
+ raise TypeError("I can't type")
+
+def test_fail():
+ a = 2
+ assert a == 4, "a is not 4"
+
+def test_ok():
+ pass
diff --git a/functional_tests/support/fdp/test_fdp_no_capt.pyc b/functional_tests/support/fdp/test_fdp_no_capt.pyc
new file mode 100644
index 0000000..c5179d0
Binary files /dev/null and b/functional_tests/support/fdp/test_fdp_no_capt.pyc differ
diff --git a/functional_tests/support/gen/test.py b/functional_tests/support/gen/test.py
new file mode 100644
index 0000000..13a0c3e
--- /dev/null
+++ b/functional_tests/support/gen/test.py
@@ -0,0 +1,12 @@
+"""This test will fail if generators bind too early."""
+
+from nose.tools import eq_
+
+def test1():
+
+ def func(_l, _n):
+ eq_(len(_l), _n)
+ l = []
+ for i in xrange(5):
+ yield func, l, i
+ l.append(None)
diff --git a/functional_tests/support/gen/test.pyc b/functional_tests/support/gen/test.pyc
new file mode 100644
index 0000000..04b68b0
Binary files /dev/null and b/functional_tests/support/gen/test.pyc differ
diff --git a/functional_tests/support/id_fails/test_a.py b/functional_tests/support/id_fails/test_a.py
new file mode 100644
index 0000000..8eac49a
--- /dev/null
+++ b/functional_tests/support/id_fails/test_a.py
@@ -0,0 +1 @@
+import apackagethatdoesntexist
diff --git a/functional_tests/support/id_fails/test_a.pyc b/functional_tests/support/id_fails/test_a.pyc
new file mode 100644
index 0000000..c4b1eb7
Binary files /dev/null and b/functional_tests/support/id_fails/test_a.pyc differ
diff --git a/functional_tests/support/id_fails/test_b.py b/functional_tests/support/id_fails/test_b.py
new file mode 100644
index 0000000..8999edc
--- /dev/null
+++ b/functional_tests/support/id_fails/test_b.py
@@ -0,0 +1,5 @@
+def test():
+ pass
+
+def test_fail():
+ assert False
diff --git a/functional_tests/support/id_fails/test_b.pyc b/functional_tests/support/id_fails/test_b.pyc
new file mode 100644
index 0000000..e4f2222
Binary files /dev/null and b/functional_tests/support/id_fails/test_b.pyc differ
diff --git a/functional_tests/support/idp/exm.py b/functional_tests/support/idp/exm.py
new file mode 100644
index 0000000..a5ae6e2
--- /dev/null
+++ b/functional_tests/support/idp/exm.py
@@ -0,0 +1,21 @@
+"""
+Module-level doctest
+
+ >>> 1
+ 1
+ >>> add_one(_)
+ 2
+"""
+
+def add_one(i):
+ """
+ function doctest
+
+ >>> add_one(1)
+ 2
+ >>> add_one(2)
+ 3
+ >>> add_one('steve')
+ joe
+ """
+ return i + 1
diff --git a/functional_tests/support/idp/exm.pyc b/functional_tests/support/idp/exm.pyc
new file mode 100644
index 0000000..55dc40c
Binary files /dev/null and b/functional_tests/support/idp/exm.pyc differ
diff --git a/functional_tests/support/idp/tests.py b/functional_tests/support/idp/tests.py
new file mode 100644
index 0000000..fc58278
--- /dev/null
+++ b/functional_tests/support/idp/tests.py
@@ -0,0 +1,38 @@
+import unittest
+
+def test_a():
+ pass
+
+def test_b():
+ raise TypeError("I am typeless")
+
+def test_c():
+ assert False, "I am contrary"
+
+def test_gen():
+ def tryit(i):
+ pass
+
+ for i in range(0, 4):
+ yield tryit, i
+
+
+class TestCase(unittest.TestCase):
+ def test_a(self):
+ pass
+ def test_b(self):
+ pass
+
+
+class TestCls:
+ def test_a(self):
+ pass
+
+ def test_gen(self):
+ def tryit(i):
+ pass
+ for i in range(0, 4):
+ yield tryit, i
+
+ def test_z(self):
+ pass
diff --git a/functional_tests/support/idp/tests.pyc b/functional_tests/support/idp/tests.pyc
new file mode 100644
index 0000000..a5281b5
Binary files /dev/null and b/functional_tests/support/idp/tests.pyc differ
diff --git a/functional_tests/support/ipt/test1/ipthelp.py b/functional_tests/support/ipt/test1/ipthelp.py
new file mode 100644
index 0000000..fdbe2e4
--- /dev/null
+++ b/functional_tests/support/ipt/test1/ipthelp.py
@@ -0,0 +1,4 @@
+print "1help imported"
+def help():
+ print "1help called"
+ pass
diff --git a/functional_tests/support/ipt/test1/ipthelp.pyc b/functional_tests/support/ipt/test1/ipthelp.pyc
new file mode 100644
index 0000000..b232451
Binary files /dev/null and b/functional_tests/support/ipt/test1/ipthelp.pyc differ
diff --git a/functional_tests/support/ipt/test1/tests.py b/functional_tests/support/ipt/test1/tests.py
new file mode 100644
index 0000000..a9595f7
--- /dev/null
+++ b/functional_tests/support/ipt/test1/tests.py
@@ -0,0 +1,7 @@
+import sys
+print 'ipthelp', sys.modules.get('ipthelp')
+import ipthelp
+print ipthelp
+
+def test1():
+ ipthelp.help()
diff --git a/functional_tests/support/ipt/test1/tests.pyc b/functional_tests/support/ipt/test1/tests.pyc
new file mode 100644
index 0000000..d7b3bee
Binary files /dev/null and b/functional_tests/support/ipt/test1/tests.pyc differ
diff --git a/functional_tests/support/ipt/test2/ipthelp.py b/functional_tests/support/ipt/test2/ipthelp.py
new file mode 100644
index 0000000..cafd917
--- /dev/null
+++ b/functional_tests/support/ipt/test2/ipthelp.py
@@ -0,0 +1,5 @@
+print "2help imported"
+
+def help(a):
+ print "2 help %s" % 1
+ pass
diff --git a/functional_tests/support/ipt/test2/ipthelp.pyc b/functional_tests/support/ipt/test2/ipthelp.pyc
new file mode 100644
index 0000000..2f069ea
Binary files /dev/null and b/functional_tests/support/ipt/test2/ipthelp.pyc differ
diff --git a/functional_tests/support/ipt/test2/tests.py b/functional_tests/support/ipt/test2/tests.py
new file mode 100644
index 0000000..1c95896
--- /dev/null
+++ b/functional_tests/support/ipt/test2/tests.py
@@ -0,0 +1,8 @@
+import sys
+
+print 'ipthelp', sys.modules.get('ipthelp')
+import ipthelp
+print ipthelp
+
+def test2():
+ ipthelp.help(1)
diff --git a/functional_tests/support/ipt/test2/tests.pyc b/functional_tests/support/ipt/test2/tests.pyc
new file mode 100644
index 0000000..b6e26f8
Binary files /dev/null and b/functional_tests/support/ipt/test2/tests.pyc differ
diff --git a/functional_tests/support/issue038/test.py b/functional_tests/support/issue038/test.py
new file mode 100644
index 0000000..c55e5a9
--- /dev/null
+++ b/functional_tests/support/issue038/test.py
@@ -0,0 +1,9 @@
+from nose.exc import SkipTest
+
+
+def test_a():
+ pass
+
+
+def test_b():
+ raise SkipTest("I'm not ready for test b")
diff --git a/functional_tests/support/issue038/test.pyc b/functional_tests/support/issue038/test.pyc
new file mode 100644
index 0000000..0fa5418
Binary files /dev/null and b/functional_tests/support/issue038/test.pyc differ
diff --git a/functional_tests/support/issue072/test.py b/functional_tests/support/issue072/test.py
new file mode 100644
index 0000000..2aab0bd
--- /dev/null
+++ b/functional_tests/support/issue072/test.py
@@ -0,0 +1,4 @@
+def test():
+ print "something"
+ a = 4
+ assert a == 2
diff --git a/functional_tests/support/issue072/test.pyc b/functional_tests/support/issue072/test.pyc
new file mode 100644
index 0000000..520ba85
Binary files /dev/null and b/functional_tests/support/issue072/test.pyc differ
diff --git a/functional_tests/support/issue082/_mypackage/__init__.py b/functional_tests/support/issue082/_mypackage/__init__.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/support/issue082/_mypackage/__init__.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/support/issue082/_mypackage/_eggs.py b/functional_tests/support/issue082/_mypackage/_eggs.py
new file mode 100644
index 0000000..81c65f7
--- /dev/null
+++ b/functional_tests/support/issue082/_mypackage/_eggs.py
@@ -0,0 +1,8 @@
+"""
+>>> True
+False
+"""
+"""
+>>> True
+False
+"""
diff --git a/functional_tests/support/issue082/_mypackage/bacon.py b/functional_tests/support/issue082/_mypackage/bacon.py
new file mode 100644
index 0000000..81c65f7
--- /dev/null
+++ b/functional_tests/support/issue082/_mypackage/bacon.py
@@ -0,0 +1,8 @@
+"""
+>>> True
+False
+"""
+"""
+>>> True
+False
+"""
diff --git a/functional_tests/support/issue082/mypublicpackage/__init__.py b/functional_tests/support/issue082/mypublicpackage/__init__.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/support/issue082/mypublicpackage/__init__.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/support/issue082/mypublicpackage/__init__.pyc b/functional_tests/support/issue082/mypublicpackage/__init__.pyc
new file mode 100644
index 0000000..9f28689
Binary files /dev/null and b/functional_tests/support/issue082/mypublicpackage/__init__.pyc differ
diff --git a/functional_tests/support/issue082/mypublicpackage/_foo.py b/functional_tests/support/issue082/mypublicpackage/_foo.py
new file mode 100644
index 0000000..81c65f7
--- /dev/null
+++ b/functional_tests/support/issue082/mypublicpackage/_foo.py
@@ -0,0 +1,8 @@
+"""
+>>> True
+False
+"""
+"""
+>>> True
+False
+"""
diff --git a/functional_tests/support/issue082/mypublicpackage/_foo.pyc b/functional_tests/support/issue082/mypublicpackage/_foo.pyc
new file mode 100644
index 0000000..b8e06e0
Binary files /dev/null and b/functional_tests/support/issue082/mypublicpackage/_foo.pyc differ
diff --git a/functional_tests/support/issue082/mypublicpackage/bar.py b/functional_tests/support/issue082/mypublicpackage/bar.py
new file mode 100644
index 0000000..81c65f7
--- /dev/null
+++ b/functional_tests/support/issue082/mypublicpackage/bar.py
@@ -0,0 +1,8 @@
+"""
+>>> True
+False
+"""
+"""
+>>> True
+False
+"""
diff --git a/functional_tests/support/issue082/mypublicpackage/bar.pyc b/functional_tests/support/issue082/mypublicpackage/bar.pyc
new file mode 100644
index 0000000..9a91793
Binary files /dev/null and b/functional_tests/support/issue082/mypublicpackage/bar.pyc differ
diff --git a/functional_tests/support/issue130/test.py b/functional_tests/support/issue130/test.py
new file mode 100644
index 0000000..9778eef
--- /dev/null
+++ b/functional_tests/support/issue130/test.py
@@ -0,0 +1,5 @@
+def setup():
+ raise "KABOOM"
+
+def test_foo():
+ assert(1==1)
diff --git a/functional_tests/support/issue130/test.pyc b/functional_tests/support/issue130/test.pyc
new file mode 100644
index 0000000..c93851e
Binary files /dev/null and b/functional_tests/support/issue130/test.pyc differ
diff --git a/functional_tests/support/issue143/not-a-package/__init__.py b/functional_tests/support/issue143/not-a-package/__init__.py
new file mode 100644
index 0000000..2ae2839
--- /dev/null
+++ b/functional_tests/support/issue143/not-a-package/__init__.py
@@ -0,0 +1 @@
+pass
diff --git a/functional_tests/support/issue143/not-a-package/test.py b/functional_tests/support/issue143/not-a-package/test.py
new file mode 100644
index 0000000..c1fb1c2
--- /dev/null
+++ b/functional_tests/support/issue143/not-a-package/test.py
@@ -0,0 +1,2 @@
+def test():
+ raise Exception("do not run")
diff --git a/functional_tests/support/issue191/UNKNOWN.egg-info/PKG-INFO b/functional_tests/support/issue191/UNKNOWN.egg-info/PKG-INFO
new file mode 100644
index 0000000..11b3dcd
--- /dev/null
+++ b/functional_tests/support/issue191/UNKNOWN.egg-info/PKG-INFO
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: UNKNOWN
+Version: 0.0.0
+Summary: UNKNOWN
+Home-page: UNKNOWN
+Author: UNKNOWN
+Author-email: UNKNOWN
+License: UNKNOWN
+Description: UNKNOWN
+Platform: UNKNOWN
diff --git a/functional_tests/support/issue191/UNKNOWN.egg-info/SOURCES.txt b/functional_tests/support/issue191/UNKNOWN.egg-info/SOURCES.txt
new file mode 100644
index 0000000..75d8cfe
--- /dev/null
+++ b/functional_tests/support/issue191/UNKNOWN.egg-info/SOURCES.txt
@@ -0,0 +1,6 @@
+setup.cfg
+setup.py
+UNKNOWN.egg-info/PKG-INFO
+UNKNOWN.egg-info/SOURCES.txt
+UNKNOWN.egg-info/dependency_links.txt
+UNKNOWN.egg-info/top_level.txt
\ No newline at end of file
diff --git a/functional_tests/support/issue191/UNKNOWN.egg-info/dependency_links.txt b/functional_tests/support/issue191/UNKNOWN.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/functional_tests/support/issue191/UNKNOWN.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/functional_tests/support/issue191/UNKNOWN.egg-info/top_level.txt b/functional_tests/support/issue191/UNKNOWN.egg-info/top_level.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/functional_tests/support/issue191/UNKNOWN.egg-info/top_level.txt
@@ -0,0 +1 @@
+
diff --git a/functional_tests/support/issue191/setup.cfg b/functional_tests/support/issue191/setup.cfg
new file mode 100644
index 0000000..431cf7a
--- /dev/null
+++ b/functional_tests/support/issue191/setup.cfg
@@ -0,0 +1,2 @@
+[nosetests]
+verbosity=2
\ No newline at end of file
diff --git a/functional_tests/support/issue191/setup.py b/functional_tests/support/issue191/setup.py
new file mode 100644
index 0000000..86276be
--- /dev/null
+++ b/functional_tests/support/issue191/setup.py
@@ -0,0 +1,3 @@
+from setuptools import setup
+
+setup(name='issue191')
diff --git a/functional_tests/support/issue191/test.py b/functional_tests/support/issue191/test.py
new file mode 100644
index 0000000..f174823
--- /dev/null
+++ b/functional_tests/support/issue191/test.py
@@ -0,0 +1,2 @@
+def test():
+ pass
diff --git a/functional_tests/support/issue191/test.pyc b/functional_tests/support/issue191/test.pyc
new file mode 100644
index 0000000..5fe368c
Binary files /dev/null and b/functional_tests/support/issue191/test.pyc differ
diff --git a/functional_tests/support/issue269/test_bad_class.py b/functional_tests/support/issue269/test_bad_class.py
new file mode 100644
index 0000000..b5642a6
--- /dev/null
+++ b/functional_tests/support/issue269/test_bad_class.py
@@ -0,0 +1,5 @@
+class TestCrashy(object):
+ def __init__(self):
+ raise Exception("pow")
+ def test_whatever(self):
+ pass
diff --git a/functional_tests/support/issue269/test_bad_class.pyc b/functional_tests/support/issue269/test_bad_class.pyc
new file mode 100644
index 0000000..217b159
Binary files /dev/null and b/functional_tests/support/issue269/test_bad_class.pyc differ
diff --git a/functional_tests/support/issue279/test_mod_setup_fails.py b/functional_tests/support/issue279/test_mod_setup_fails.py
new file mode 100644
index 0000000..80d22d7
--- /dev/null
+++ b/functional_tests/support/issue279/test_mod_setup_fails.py
@@ -0,0 +1,5 @@
+def setup():
+ raise Exception("I would prefer not to")
+
+def test():
+ raise Exception("I should never run")
diff --git a/functional_tests/support/issue279/test_mod_setup_fails.pyc b/functional_tests/support/issue279/test_mod_setup_fails.pyc
new file mode 100644
index 0000000..f172ec5
Binary files /dev/null and b/functional_tests/support/issue279/test_mod_setup_fails.pyc differ
diff --git a/functional_tests/support/issue408/nosetests.xml b/functional_tests/support/issue408/nosetests.xml
new file mode 100644
index 0000000..e69de29
diff --git a/functional_tests/support/issue408/test.py b/functional_tests/support/issue408/test.py
new file mode 100644
index 0000000..a5e88e9
--- /dev/null
+++ b/functional_tests/support/issue408/test.py
@@ -0,0 +1,16 @@
+class base:
+ @classmethod
+ def setup_class(cls):
+ cls.inited = 1
+ @classmethod
+ def teardown_class(cls):
+ cls.inited = 0
+ def test1(self):
+ assert self.inited
+ def test2(self):
+ assert self.inited
+
+class testa(base):
+ pass
+class testb(base):
+ pass
diff --git a/functional_tests/support/issue408/test.pyc b/functional_tests/support/issue408/test.pyc
new file mode 100644
index 0000000..689957a
Binary files /dev/null and b/functional_tests/support/issue408/test.pyc differ
diff --git a/functional_tests/support/ltfn/state.py b/functional_tests/support/ltfn/state.py
new file mode 100644
index 0000000..f931b21
--- /dev/null
+++ b/functional_tests/support/ltfn/state.py
@@ -0,0 +1 @@
+called = []
diff --git a/functional_tests/support/ltfn/state.pyc b/functional_tests/support/ltfn/state.pyc
new file mode 100644
index 0000000..322e690
Binary files /dev/null and b/functional_tests/support/ltfn/state.pyc differ
diff --git a/functional_tests/support/ltfn/test_mod.py b/functional_tests/support/ltfn/test_mod.py
new file mode 100644
index 0000000..b98d207
--- /dev/null
+++ b/functional_tests/support/ltfn/test_mod.py
@@ -0,0 +1,10 @@
+from state import called
+
+def setup():
+ called.append('test_mod.setup')
+
+def test_mod():
+ called.append('test_mod.test_mod')
+
+def teardown():
+ called.append('test_mod.teardown')
diff --git a/functional_tests/support/ltfn/test_mod.pyc b/functional_tests/support/ltfn/test_mod.pyc
new file mode 100644
index 0000000..2264b2d
Binary files /dev/null and b/functional_tests/support/ltfn/test_mod.pyc differ
diff --git a/functional_tests/support/ltfn/test_pak1/__init__.py b/functional_tests/support/ltfn/test_pak1/__init__.py
new file mode 100644
index 0000000..7087716
--- /dev/null
+++ b/functional_tests/support/ltfn/test_pak1/__init__.py
@@ -0,0 +1,13 @@
+from state import called
+
+def setup():
+ called.append('test_pak1.setup')
+
+def teardown():
+ called.append('test_pak1.teardown')
+
+def test_one_one():
+ called.append('test_pak1.test_one_one')
+
+def test_one_two():
+ called.append('test_pak1.test_one_two')
diff --git a/functional_tests/support/ltfn/test_pak1/__init__.pyc b/functional_tests/support/ltfn/test_pak1/__init__.pyc
new file mode 100644
index 0000000..8f42014
Binary files /dev/null and b/functional_tests/support/ltfn/test_pak1/__init__.pyc differ
diff --git a/functional_tests/support/ltfn/test_pak1/test_mod.py b/functional_tests/support/ltfn/test_pak1/test_mod.py
new file mode 100644
index 0000000..dd565da
--- /dev/null
+++ b/functional_tests/support/ltfn/test_pak1/test_mod.py
@@ -0,0 +1,12 @@
+from state import called
+
+def setup():
+ called.append('test_pak1.test_mod.setup')
+
+def teardown():
+ called.append('test_pak1.test_mod.teardown')
+
+def test_one_mod_one():
+ called.append('test_pak1.test_mod.test_one_mod_one')
+ pass
+
diff --git a/functional_tests/support/ltfn/test_pak1/test_mod.pyc b/functional_tests/support/ltfn/test_pak1/test_mod.pyc
new file mode 100644
index 0000000..b54e0b2
Binary files /dev/null and b/functional_tests/support/ltfn/test_pak1/test_mod.pyc differ
diff --git a/functional_tests/support/ltfn/test_pak2/__init__.py b/functional_tests/support/ltfn/test_pak2/__init__.py
new file mode 100644
index 0000000..88a2ae8
--- /dev/null
+++ b/functional_tests/support/ltfn/test_pak2/__init__.py
@@ -0,0 +1,13 @@
+from state import called
+
+def setup():
+ called.append('test_pak2.setup')
+
+def teardown():
+ called.append('test_pak2.teardown')
+
+def test_two_one():
+ called.append('test_pak2.test_two_one')
+
+def test_two_two():
+ called.append('test_pak2.test_two_two')
diff --git a/functional_tests/support/ltfn/test_pak2/__init__.pyc b/functional_tests/support/ltfn/test_pak2/__init__.pyc
new file mode 100644
index 0000000..a044dc3
Binary files /dev/null and b/functional_tests/support/ltfn/test_pak2/__init__.pyc differ
diff --git a/functional_tests/support/ltftc/tests.py b/functional_tests/support/ltftc/tests.py
new file mode 100644
index 0000000..02208a1
--- /dev/null
+++ b/functional_tests/support/ltftc/tests.py
@@ -0,0 +1,9 @@
+import unittest
+
+class Tests(unittest.TestCase):
+
+ def setUp(self):
+ self.value = 1
+
+ def test_value(self):
+ self.assertEqual(self.value, 1)
diff --git a/functional_tests/support/ltftc/tests.pyc b/functional_tests/support/ltftc/tests.pyc
new file mode 100644
index 0000000..1d45627
Binary files /dev/null and b/functional_tests/support/ltftc/tests.pyc differ
diff --git a/functional_tests/support/namespace_pkg/namespace_pkg/__init__.py b/functional_tests/support/namespace_pkg/namespace_pkg/__init__.py
new file mode 100644
index 0000000..86fe67d
--- /dev/null
+++ b/functional_tests/support/namespace_pkg/namespace_pkg/__init__.py
@@ -0,0 +1,2 @@
+import pkgutil
+__path__ = pkgutil.extend_path(__path__, __name__)
diff --git a/functional_tests/support/namespace_pkg/namespace_pkg/__init__.pyc b/functional_tests/support/namespace_pkg/namespace_pkg/__init__.pyc
new file mode 100644
index 0000000..897fc62
Binary files /dev/null and b/functional_tests/support/namespace_pkg/namespace_pkg/__init__.pyc differ
diff --git a/functional_tests/support/namespace_pkg/namespace_pkg/example.py b/functional_tests/support/namespace_pkg/namespace_pkg/example.py
new file mode 100644
index 0000000..86dda80
--- /dev/null
+++ b/functional_tests/support/namespace_pkg/namespace_pkg/example.py
@@ -0,0 +1 @@
+test = 'the nose knows'
diff --git a/functional_tests/support/namespace_pkg/namespace_pkg/example.pyc b/functional_tests/support/namespace_pkg/namespace_pkg/example.pyc
new file mode 100644
index 0000000..1563e59
Binary files /dev/null and b/functional_tests/support/namespace_pkg/namespace_pkg/example.pyc differ
diff --git a/functional_tests/support/namespace_pkg/namespace_pkg/test_pkg.py b/functional_tests/support/namespace_pkg/namespace_pkg/test_pkg.py
new file mode 100644
index 0000000..9315c52
--- /dev/null
+++ b/functional_tests/support/namespace_pkg/namespace_pkg/test_pkg.py
@@ -0,0 +1,6 @@
+from namespace_pkg import example
+from namespace_pkg import example2
+
+def test_namespace_pkg():
+ assert example.test == 'the nose knows'
+ assert example2.test == 'put that snoot to use'
diff --git a/functional_tests/support/namespace_pkg/namespace_pkg/test_pkg.pyc b/functional_tests/support/namespace_pkg/namespace_pkg/test_pkg.pyc
new file mode 100644
index 0000000..466e58a
Binary files /dev/null and b/functional_tests/support/namespace_pkg/namespace_pkg/test_pkg.pyc differ
diff --git a/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/__init__.py b/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/__init__.py
new file mode 100644
index 0000000..86fe67d
--- /dev/null
+++ b/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/__init__.py
@@ -0,0 +1,2 @@
+import pkgutil
+__path__ = pkgutil.extend_path(__path__, __name__)
diff --git a/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/example2.py b/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/example2.py
new file mode 100644
index 0000000..47f20d0
--- /dev/null
+++ b/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/example2.py
@@ -0,0 +1 @@
+test = 'put that snoot to use'
diff --git a/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/example2.pyc b/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/example2.pyc
new file mode 100644
index 0000000..07baec2
Binary files /dev/null and b/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/example2.pyc differ
diff --git a/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/test_pkg2.py b/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/test_pkg2.py
new file mode 100644
index 0000000..44ed6c1
--- /dev/null
+++ b/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/test_pkg2.py
@@ -0,0 +1,6 @@
+from namespace_pkg import example
+from namespace_pkg import example2
+
+def test_namespace_pkg2():
+ assert example.test == 'the nose knows'
+ assert example2.test == 'put that snoot to use'
diff --git a/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/test_pkg2.pyc b/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/test_pkg2.pyc
new file mode 100644
index 0000000..ac58c71
Binary files /dev/null and b/functional_tests/support/namespace_pkg/site-packages/namespace_pkg/test_pkg2.pyc differ
diff --git a/functional_tests/support/package1/example.py b/functional_tests/support/package1/example.py
new file mode 100644
index 0000000..d758778
--- /dev/null
+++ b/functional_tests/support/package1/example.py
@@ -0,0 +1,8 @@
+def times_two(a):
+ """
+ >>> times_two(2)
+ 4
+ >>> times_two('bee')
+ beebee
+ """
+ return a * 2
diff --git a/functional_tests/support/package1/example.pyc b/functional_tests/support/package1/example.pyc
new file mode 100644
index 0000000..298ed4e
Binary files /dev/null and b/functional_tests/support/package1/example.pyc differ
diff --git a/functional_tests/support/package1/tests/test_example_function.py b/functional_tests/support/package1/tests/test_example_function.py
new file mode 100644
index 0000000..d74f2a5
--- /dev/null
+++ b/functional_tests/support/package1/tests/test_example_function.py
@@ -0,0 +1,15 @@
+import example
+import unittest
+
+class TestExampleFunction_TestCase(unittest.TestCase):
+ def test_times_two(self):
+ self.assertEqual(example.times_two(2), 4)
+
+
+class TestExampleFunction:
+ def test_times_two(self):
+ assert example.times_two(2) == 4
+
+
+def test_times_two():
+ assert example.times_two(2) == 4
diff --git a/functional_tests/support/package1/tests/test_example_function.pyc b/functional_tests/support/package1/tests/test_example_function.pyc
new file mode 100644
index 0000000..e10f2f2
Binary files /dev/null and b/functional_tests/support/package1/tests/test_example_function.pyc differ
diff --git a/functional_tests/support/package2/maths.py b/functional_tests/support/package2/maths.py
new file mode 100644
index 0000000..abd85e5
--- /dev/null
+++ b/functional_tests/support/package2/maths.py
@@ -0,0 +1,11 @@
+def add(a, b):
+ return a + b
+
+def div(a, b):
+ return a // b
+
+def minus(a, b):
+ return a - b
+
+def mult(a, b):
+ return a * b
diff --git a/functional_tests/support/package2/maths.pyc b/functional_tests/support/package2/maths.pyc
new file mode 100644
index 0000000..660cfe1
Binary files /dev/null and b/functional_tests/support/package2/maths.pyc differ
diff --git a/functional_tests/support/package2/test_pak/__init__.py b/functional_tests/support/package2/test_pak/__init__.py
new file mode 100644
index 0000000..3a05d5f
--- /dev/null
+++ b/functional_tests/support/package2/test_pak/__init__.py
@@ -0,0 +1,11 @@
+print "*** test_pak imported"
+state = []
+
+def setup():
+ # print "SETUP CALLED", state, id(state)
+ state.append('test_pak.setup')
+
+
+def teardown():
+ # print "TEARDOWN CALLED", state, id(state)
+ state.append('test_pak.teardown')
diff --git a/functional_tests/support/package2/test_pak/__init__.pyc b/functional_tests/support/package2/test_pak/__init__.pyc
new file mode 100644
index 0000000..1f4ef67
Binary files /dev/null and b/functional_tests/support/package2/test_pak/__init__.pyc differ
diff --git a/functional_tests/support/package2/test_pak/test_mod.py b/functional_tests/support/package2/test_pak/test_mod.py
new file mode 100644
index 0000000..09dc9e5
--- /dev/null
+++ b/functional_tests/support/package2/test_pak/test_mod.py
@@ -0,0 +1,20 @@
+print "test_mod imported!"
+
+import maths
+from test_pak import state
+
+def setup():
+ print "MOD setup called", state, id(state)
+ state.append('test_pak.test_mod.setup')
+
+def test_add():
+ print "MOD.test_add called", state, id(state)
+ state.append('test_pak.test_mod.test_add')
+ assert maths.add(1, 2) == 3
+
+def test_minus():
+ state.append('test_pak.test_mod.test_minus')
+
+def teardown():
+ print "MOD teardown called", state, id(state)
+ state.append('test_pak.test_mod.teardown')
diff --git a/functional_tests/support/package2/test_pak/test_mod.pyc b/functional_tests/support/package2/test_pak/test_mod.pyc
new file mode 100644
index 0000000..730aee2
Binary files /dev/null and b/functional_tests/support/package2/test_pak/test_mod.pyc differ
diff --git a/functional_tests/support/package2/test_pak/test_sub/__init__.py b/functional_tests/support/package2/test_pak/test_sub/__init__.py
new file mode 100644
index 0000000..a3d051a
--- /dev/null
+++ b/functional_tests/support/package2/test_pak/test_sub/__init__.py
@@ -0,0 +1,9 @@
+from test_pak import state
+
+def setup():
+ # print "SUB setup called", state, id(state)
+ state.append('test_pak.test_sub.setup')
+
+def teardown():
+ # print "SUB teardown called", state, id(state)
+ state.append('test_pak.test_sub.teardown')
diff --git a/functional_tests/support/package2/test_pak/test_sub/__init__.pyc b/functional_tests/support/package2/test_pak/test_sub/__init__.pyc
new file mode 100644
index 0000000..4489581
Binary files /dev/null and b/functional_tests/support/package2/test_pak/test_sub/__init__.pyc differ
diff --git a/functional_tests/support/package2/test_pak/test_sub/test_mod.py b/functional_tests/support/package2/test_pak/test_sub/test_mod.py
new file mode 100644
index 0000000..2c77c97
--- /dev/null
+++ b/functional_tests/support/package2/test_pak/test_sub/test_mod.py
@@ -0,0 +1,36 @@
+from test_pak import state
+import maths
+
+def setup():
+ state.append('test_pak.test_sub.test_mod.setup')
+
+def test():
+ state.append('test_pak.test_sub.test_mod.test')
+ assert maths.add(1, 2) == 3
+
+class TestMaths:
+
+ def setup_class(cls):
+ state.append('test_pak.test_sub.test_mod.TestMaths.setup_class')
+ setup_class = classmethod(setup_class)
+
+ def teardown_class(cls):
+ state.append('test_pak.test_sub.test_mod.TestMaths.teardown_class')
+ teardown_class = classmethod(teardown_class)
+
+ def setup(self):
+ state.append('test_pak.test_sub.test_mod.TestMaths.setup')
+
+ def teardown(self):
+ state.append('test_pak.test_sub.test_mod.TestMaths.teardown')
+
+ def test_div(self):
+ state.append('test_pak.test_sub.test_mod.TestMaths.test_div')
+ assert maths.div(2, 1) == 2, "%s != %s" % (maths.div(2, 1), 2)
+
+ def test_two_two(self):
+ state.append('test_pak.test_sub.test_mod.TestMaths.test_two_two')
+ assert maths.mult(2, 2) == maths.add(2, 2)
+
+def teardown():
+ state.append('test_pak.test_sub.test_mod.teardown')
diff --git a/functional_tests/support/package2/test_pak/test_sub/test_mod.pyc b/functional_tests/support/package2/test_pak/test_sub/test_mod.pyc
new file mode 100644
index 0000000..005ca11
Binary files /dev/null and b/functional_tests/support/package2/test_pak/test_sub/test_mod.pyc differ
diff --git a/functional_tests/support/package3/lib/a.py b/functional_tests/support/package3/lib/a.py
new file mode 100644
index 0000000..b2dde25
--- /dev/null
+++ b/functional_tests/support/package3/lib/a.py
@@ -0,0 +1,2 @@
+def a():
+ pass
diff --git a/functional_tests/support/package3/lib/a.pyc b/functional_tests/support/package3/lib/a.pyc
new file mode 100644
index 0000000..62a73eb
Binary files /dev/null and b/functional_tests/support/package3/lib/a.pyc differ
diff --git a/functional_tests/support/package3/src/b.py b/functional_tests/support/package3/src/b.py
new file mode 100644
index 0000000..40aaa8c
--- /dev/null
+++ b/functional_tests/support/package3/src/b.py
@@ -0,0 +1,2 @@
+def b():
+ pass
diff --git a/functional_tests/support/package3/src/b.pyc b/functional_tests/support/package3/src/b.pyc
new file mode 100644
index 0000000..8080373
Binary files /dev/null and b/functional_tests/support/package3/src/b.pyc differ
diff --git a/functional_tests/support/package3/tests/test_a.py b/functional_tests/support/package3/tests/test_a.py
new file mode 100644
index 0000000..3b978fc
--- /dev/null
+++ b/functional_tests/support/package3/tests/test_a.py
@@ -0,0 +1,4 @@
+import a
+
+def test_a():
+ a.a()
diff --git a/functional_tests/support/package3/tests/test_a.pyc b/functional_tests/support/package3/tests/test_a.pyc
new file mode 100644
index 0000000..b6e7fcd
Binary files /dev/null and b/functional_tests/support/package3/tests/test_a.pyc differ
diff --git a/functional_tests/support/package3/tests/test_b.py b/functional_tests/support/package3/tests/test_b.py
new file mode 100644
index 0000000..d8c182a
--- /dev/null
+++ b/functional_tests/support/package3/tests/test_b.py
@@ -0,0 +1,4 @@
+import b
+
+def test_b():
+ b.b()
diff --git a/functional_tests/support/package3/tests/test_b.pyc b/functional_tests/support/package3/tests/test_b.pyc
new file mode 100644
index 0000000..faafaa4
Binary files /dev/null and b/functional_tests/support/package3/tests/test_b.pyc differ
diff --git a/functional_tests/support/pass/test.py b/functional_tests/support/pass/test.py
new file mode 100644
index 0000000..f174823
--- /dev/null
+++ b/functional_tests/support/pass/test.py
@@ -0,0 +1,2 @@
+def test():
+ pass
diff --git a/functional_tests/support/pass/test.pyc b/functional_tests/support/pass/test.pyc
new file mode 100644
index 0000000..64f1ee0
Binary files /dev/null and b/functional_tests/support/pass/test.pyc differ
diff --git a/functional_tests/support/test.cfg b/functional_tests/support/test.cfg
new file mode 100644
index 0000000..738c764
--- /dev/null
+++ b/functional_tests/support/test.cfg
@@ -0,0 +1,2 @@
+[nosetests]
+verbosity=10
diff --git a/functional_tests/support/test_buggy_generators.py b/functional_tests/support/test_buggy_generators.py
new file mode 100644
index 0000000..00e4815
--- /dev/null
+++ b/functional_tests/support/test_buggy_generators.py
@@ -0,0 +1,29 @@
+def test_generator_fails_before_yield():
+ a = 1 // 0
+ yield lambda: True
+
+
+def test_generator_fails_during_iteration():
+ for i in [1, 2, 3, 0, 5, 6]:
+ a = 1 // i
+ yield lambda: True
+
+
+def test_ok():
+ pass
+
+
+class TestBuggyGenerators(object):
+
+ def test_generator_fails_before_yield(self):
+ a = 1 // 0
+ yield lambda: True
+
+ def test_generator_fails_during_iteration(self):
+ for i in [1, 2, 3, 0, 5, 6]:
+ a = 1 // i
+ yield lambda: True
+
+ def test_ok(self):
+ pass
+
diff --git a/functional_tests/support/test_buggy_generators.pyc b/functional_tests/support/test_buggy_generators.pyc
new file mode 100644
index 0000000..becad88
Binary files /dev/null and b/functional_tests/support/test_buggy_generators.pyc differ
diff --git a/functional_tests/support/todo/test_with_todo.py b/functional_tests/support/todo/test_with_todo.py
new file mode 100644
index 0000000..b48f6a8
--- /dev/null
+++ b/functional_tests/support/todo/test_with_todo.py
@@ -0,0 +1,7 @@
+from todoplug import Todo
+
+def test_some_important_thing():
+ raise Todo("Not done yet")
+
+def test_something_else():
+ pass
diff --git a/functional_tests/support/todo/test_with_todo.pyc b/functional_tests/support/todo/test_with_todo.pyc
new file mode 100644
index 0000000..9375d17
Binary files /dev/null and b/functional_tests/support/todo/test_with_todo.pyc differ
diff --git a/functional_tests/support/todo/todoplug.py b/functional_tests/support/todo/todoplug.py
new file mode 100644
index 0000000..585c26a
--- /dev/null
+++ b/functional_tests/support/todo/todoplug.py
@@ -0,0 +1,7 @@
+from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin
+
+class Todo(Exception):
+ pass
+
+class TodoPlugin(ErrorClassPlugin):
+ todo = ErrorClass(Todo, label='TODO', isfailure=True)
diff --git a/functional_tests/support/todo/todoplug.pyc b/functional_tests/support/todo/todoplug.pyc
new file mode 100644
index 0000000..9565f40
Binary files /dev/null and b/functional_tests/support/todo/todoplug.pyc differ
diff --git a/functional_tests/support/twist/test_twisted.py b/functional_tests/support/twist/test_twisted.py
new file mode 100644
index 0000000..d6c57c2
--- /dev/null
+++ b/functional_tests/support/twist/test_twisted.py
@@ -0,0 +1,15 @@
+from twisted.trial import unittest
+
+class TestTwisted(unittest.TestCase):
+
+ def test(self):
+ pass
+
+ def test_fail(self):
+ self.fail("I failed")
+
+ def test_error(self):
+ raise TypeError("oops, wrong type")
+
+ def test_skip(self):
+ raise unittest.SkipTest('skip me')
diff --git a/functional_tests/support/twist/test_twisted.pyc b/functional_tests/support/twist/test_twisted.pyc
new file mode 100644
index 0000000..24ddfa5
Binary files /dev/null and b/functional_tests/support/twist/test_twisted.pyc differ
diff --git a/functional_tests/support/xunit.xml b/functional_tests/support/xunit.xml
new file mode 100644
index 0000000..7cf345b
--- /dev/null
+++ b/functional_tests/support/xunit.xml
@@ -0,0 +1,24 @@
+
\ No newline at end of file
diff --git a/functional_tests/support/xunit/test_xunit_as_suite.py b/functional_tests/support/xunit/test_xunit_as_suite.py
new file mode 100644
index 0000000..ec256b5
--- /dev/null
+++ b/functional_tests/support/xunit/test_xunit_as_suite.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+import sys
+from nose.exc import SkipTest
+import unittest
+
+class TestForXunit(unittest.TestCase):
+
+ def test_success(self):
+ pass
+
+ def test_fail(self):
+ self.assertEqual("this","that")
+
+ def test_error(self):
+ raise TypeError("oops, wrong type")
+
+ def test_non_ascii_error(self):
+ raise Exception(u"日本")
+
+ def test_output(self):
+ sys.stdout.write("test-generated output\n")
+
+ def test_skip(self):
+ raise SkipTest("skipit")
diff --git a/functional_tests/support/xunit/test_xunit_as_suite.pyc b/functional_tests/support/xunit/test_xunit_as_suite.pyc
new file mode 100644
index 0000000..fd84fe9
Binary files /dev/null and b/functional_tests/support/xunit/test_xunit_as_suite.pyc differ
diff --git a/functional_tests/test_attribute_plugin.py b/functional_tests/test_attribute_plugin.py
new file mode 100644
index 0000000..a093cd5
--- /dev/null
+++ b/functional_tests/test_attribute_plugin.py
@@ -0,0 +1,181 @@
+import os
+import sys
+import unittest
+from nose.plugins.attrib import AttributeSelector
+from nose.plugins import PluginTester
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+compat_24 = sys.version_info >= (2, 4)
+
+class AttributePluginTester(PluginTester, unittest.TestCase):
+ plugins = [AttributeSelector()]
+ suitepath = os.path.join(support, 'att')
+ # Some cases need -a to activate and others need -A, so
+ # let's treat -v as the activate argument and let individual
+ # cases specify their -a arguments as part of args
+ activate = '-v'
+
+ def runTest(self):
+ print '*' * 70
+ print str(self.output)
+ print '*' * 70
+ self.verify()
+
+ def verify(self):
+ raise NotImplementedError()
+
+
+class TestSimpleAttribute(AttributePluginTester):
+ args = ["-a", "a"]
+
+ def verify(self):
+ assert 'test_attr.test_one ... ok' in self.output
+ assert 'test_attr.test_two ... ok' in self.output
+ assert 'TestClass.test_class_one ... ok' in self.output
+ assert 'TestClass.test_class_two ... ok' in self.output
+ assert 'TestClass.test_class_three ... ok' in self.output
+ assert 'test_three' not in self.output
+ assert 'test_case_two' not in self.output
+ assert 'test_case_one' not in self.output
+ assert 'test_case_three' not in self.output
+ assert 'TestAttrClass.test_one ... ok' in self.output
+ assert 'TestAttrClass.test_two ... ok' in self.output
+ assert 'TestAttrClass.ends_with_test ... ok' in self.output
+
+
+class TestNotSimpleAttribute(AttributePluginTester):
+ args = ["-a", "!a"]
+
+ def verify(self):
+ assert 'test_attr.test_one ... ok' not in self.output
+ assert 'test_attr.test_two ... ok' not in self.output
+ assert 'TestClass.test_class_one ... ok' not in self.output
+ assert 'TestClass.test_class_two ... ok' not in self.output
+ assert 'TestClass.test_class_three ... ok' not in self.output
+ assert 'test_three' in self.output
+ assert 'test_case_two' in self.output
+ assert 'test_case_one' in self.output
+ assert 'test_case_three' in self.output
+
+
+class TestAttributeValue(AttributePluginTester):
+ args = ["-a", "b=2"]
+
+ def verify(self):
+ assert 'test_attr.test_one ... ok' not in self.output
+ assert 'test_attr.test_two ... ok' not in self.output
+ assert 'test_attr.test_three ... ok' not in self.output
+ assert 'TestClass.test_class_one ... ok' not in self.output
+ assert 'TestClass.test_class_two ... ok' in self.output
+ assert 'TestClass.test_class_three ... ok' not in self.output
+ assert 'test_case_two' in self.output
+ assert 'test_case_one' in self.output
+ assert 'test_case_three' in self.output
+
+
+class TestAttributeArray(AttributePluginTester):
+ args = ["-a", "d=2"]
+
+ def verify(self):
+ assert 'test_attr.test_one ... ok' in self.output
+ assert 'test_attr.test_two ... ok' in self.output
+ assert 'test_attr.test_three ... ok' not in self.output
+ assert 'TestClass.test_class_one ... ok' not in self.output
+ assert 'TestClass.test_class_two ... ok' not in self.output
+ assert 'TestClass.test_class_three ... ok' not in self.output
+ assert 'test_case_two' not in self.output
+ assert 'test_case_one' not in self.output
+ assert 'test_case_three' not in self.output
+
+
+class TestAttributeArrayAnd(AttributePluginTester):
+ args = ["-a", "d=1,d=2"]
+
+ def verify(self):
+ assert 'test_attr.test_one ... ok' in self.output
+ assert 'test_attr.test_two ... ok' not in self.output
+ assert 'test_attr.test_three ... ok' not in self.output
+ assert 'TestClass.test_class_one ... ok' not in self.output
+ assert 'TestClass.test_class_two ... ok' not in self.output
+ assert 'TestClass.test_class_three ... ok' not in self.output
+ assert 'test_case_two' not in self.output
+ assert 'test_case_one' not in self.output
+ assert 'test_case_three' not in self.output
+
+
+class TestAttributeArrayOr(AttributePluginTester):
+ args = ["-a", "d=1", "-a", "d=2"]
+
+ def verify(self):
+ assert 'test_attr.test_one ... ok' in self.output
+ assert 'test_attr.test_two ... ok' in self.output
+ assert 'test_attr.test_three ... ok' in self.output
+ assert 'TestClass.test_class_one ... ok' not in self.output
+ assert 'TestClass.test_class_two ... ok' not in self.output
+ assert 'TestClass.test_class_three ... ok' not in self.output
+ assert 'test_case_two' not in self.output
+ assert 'test_case_one' not in self.output
+ assert 'test_case_three' not in self.output
+
+
+class TestInheritance(AttributePluginTester):
+ # Issue #412
+ args = ["-a", "from_super"]
+
+ def verify(self):
+ assert 'TestSubclass.test_method ... ok' in self.output
+ assert 'TestAttrSubClass.test_sub_three ... ok' in self.output
+ assert 'TestAttrSubClass.test_one ... ok' in self.output
+ assert 'TestAttrSubClass.added_later_test ... ok' in self.output
+ assert 'test_two' not in self.output
+ assert 'test_case_one' not in self.output
+ assert 'test_case_three' not in self.output
+
+
+class TestStatic(AttributePluginTester):
+ # Issue #411
+ args = ["-a", "with_static"]
+ suitepath = os.path.join(support, 'att', 'test_attr.py:Static')
+
+ def verify(self):
+ assert 'Static.test_with_static ... ok' in self.output
+ assert 'test_case_two' not in self.output
+ assert 'test_case_one' not in self.output
+ assert 'test_case_three' not in self.output
+
+
+class TestClassAndMethodAttrs(AttributePluginTester):
+ # Issue #324
+ args = ["-a", "meth_attr=method,cls_attr=class"]
+
+ def verify(self):
+ assert '(test_attr.TestClassAndMethodAttrs) ... ok' in self.output
+ assert 'test_case_two' not in self.output
+ assert 'test_case_one' not in self.output
+ assert 'test_case_three' not in self.output
+
+
+if compat_24:
+ class TestAttributeEval(AttributePluginTester):
+ args = ["-A", "c>20"]
+
+ def verify(self):
+ assert 'test_attr.test_one ... ok' not in self.output
+ assert 'test_attr.test_two ... ok' not in self.output
+ assert 'test_attr.test_three ... ok' not in self.output
+ assert 'TestClass.test_class_one ... ok' not in self.output
+ assert 'TestClass.test_class_two ... ok' not in self.output
+ assert 'TestClass.test_class_three ... ok' not in self.output
+ assert 'test_case_two' in self.output
+ assert 'test_case_one' not in self.output
+ assert 'test_case_three' not in self.output
+
+
+# Avoid trying to run base class as tests
+del AttributePluginTester
+
+if __name__ == '__main__':
+ #import logging
+ #logging.basicConfig(level=logging.DEBUG)
+ unittest.main()
diff --git a/functional_tests/test_attribute_plugin.pyc b/functional_tests/test_attribute_plugin.pyc
new file mode 100644
index 0000000..d962527
Binary files /dev/null and b/functional_tests/test_attribute_plugin.pyc differ
diff --git a/functional_tests/test_buggy_generators.py b/functional_tests/test_buggy_generators.py
new file mode 100644
index 0000000..9e6e168
--- /dev/null
+++ b/functional_tests/test_buggy_generators.py
@@ -0,0 +1,36 @@
+import os
+import unittest
+from cStringIO import StringIO
+from nose.core import TestProgram
+from nose.config import Config
+from nose.result import _TextTestResult
+
+here = os.path.dirname(__file__)
+support = os.path.join(here, 'support')
+
+
+class TestRunner(unittest.TextTestRunner):
+ def _makeResult(self):
+ self.result = _TextTestResult(
+ self.stream, self.descriptions, self.verbosity)
+ return self.result
+
+
+class TestBuggyGenerators(unittest.TestCase):
+ def test_run_buggy_generators(self):
+ stream = StringIO()
+ runner = TestRunner(stream=stream)
+ prog = TestProgram(
+ argv=['nosetests',
+ os.path.join(support, 'test_buggy_generators.py')],
+ testRunner=runner,
+ config=Config(),
+ exit=False)
+ res = runner.result
+ print stream.getvalue()
+ self.assertEqual(res.testsRun, 12,
+ "Expected to run 12 tests, ran %s" % res.testsRun)
+ assert not res.wasSuccessful()
+ assert len(res.errors) == 4
+ assert not res.failures
+
diff --git a/functional_tests/test_buggy_generators.pyc b/functional_tests/test_buggy_generators.pyc
new file mode 100644
index 0000000..3161552
Binary files /dev/null and b/functional_tests/test_buggy_generators.pyc differ
diff --git a/functional_tests/test_cases.py b/functional_tests/test_cases.py
new file mode 100644
index 0000000..99b9071
--- /dev/null
+++ b/functional_tests/test_cases.py
@@ -0,0 +1,38 @@
+import unittest
+from nose.config import Config
+from nose import case
+from nose.plugins import Plugin, PluginManager
+
+class TestTestCasePluginCalls(unittest.TestCase):
+
+ def test_describe_test_called(self):
+ class Descrip(Plugin):
+ counter = 0
+ enabled = True
+ def describeTest(self, test):
+ return "test #%s" % id(test)
+ def testName(self, test):
+ self.counter += 1
+ return "(%s) test" % self.counter
+
+ class TC(unittest.TestCase):
+ def test_one(self):
+ pass
+ def test_two(self):
+ pass
+
+ config = Config(plugins=PluginManager(plugins=[Descrip()]))
+
+ c1 = case.Test(TC('test_one'), config=config)
+ c2 = case.Test(TC('test_two'), config=config)
+
+ self.assertEqual(str(c1), '(1) test')
+ self.assertEqual(str(c2), '(2) test')
+ assert c1.shortDescription().startswith('test #'), \
+ "Unexpected shortDescription: %s" % c1.shortDescription()
+ assert c2.shortDescription().startswith('test #'), \
+ "Unexpected shortDescription: %s" % c2.shortDescription()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_cases.pyc b/functional_tests/test_cases.pyc
new file mode 100644
index 0000000..05e0ce7
Binary files /dev/null and b/functional_tests/test_cases.pyc differ
diff --git a/functional_tests/test_collector.py b/functional_tests/test_collector.py
new file mode 100644
index 0000000..c3b9dca
--- /dev/null
+++ b/functional_tests/test_collector.py
@@ -0,0 +1,46 @@
+import os
+import sys
+import unittest
+import warnings
+from cStringIO import StringIO
+from nose.result import _TextTestResult
+here = os.path.dirname(__file__)
+support = os.path.join(here, 'support')
+
+
+class TestRunner(unittest.TextTestRunner):
+ def _makeResult(self):
+ self.result = _TextTestResult(
+ self.stream, self.descriptions, self.verbosity)
+ return self.result
+
+
+class TestNoseTestCollector(unittest.TestCase):
+
+ def test_skip_works_with_collector(self):
+ verbosity = 2
+ stream = StringIO()
+ runner = TestRunner(stream=stream, verbosity=verbosity)
+ pwd = os.getcwd()
+
+ # we don't need to see our own warnings
+ warnings.filterwarnings(action='ignore',
+ category=RuntimeWarning,
+ module='nose.plugins.manager')
+
+ try:
+ os.chdir(os.path.join(support, 'issue038'))
+ unittest.TestProgram(
+ None, None,
+ argv=['test_collector', '-v', 'nose.collector'],
+ testRunner=runner)
+ except SystemExit:
+ pass
+ os.chdir(pwd)
+ out = stream.getvalue()
+ assert runner.result.wasSuccessful()
+ assert 'SKIP' in out, "SKIP not found in %s" % out
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_collector.pyc b/functional_tests/test_collector.pyc
new file mode 100644
index 0000000..35a0426
Binary files /dev/null and b/functional_tests/test_collector.pyc differ
diff --git a/functional_tests/test_commands.py b/functional_tests/test_commands.py
new file mode 100644
index 0000000..682af04
--- /dev/null
+++ b/functional_tests/test_commands.py
@@ -0,0 +1,47 @@
+import os
+import sys
+import unittest
+from nose.plugins.skip import SkipTest
+from nose import commands
+from StringIO import StringIO
+
+support = os.path.join(
+ os.path.dirname(__file__), 'support', 'issue191')
+
+
+class TestCommands(unittest.TestCase):
+ def setUp(self):
+ try:
+ import setuptools
+ except ImportError:
+ raise SkipTest("setuptools not available")
+ self.dir = os.getcwd()
+ self.stderr = sys.stderr
+ os.chdir(support)
+
+ def tearDown(self):
+ os.chdir(self.dir)
+ sys.stderr = self.stderr
+
+ def test_setup_nosetests_command_works(self):
+ from setuptools.dist import Distribution
+ buf = StringIO()
+ sys.stderr = buf
+ cmd = commands.nosetests(
+ Distribution(attrs={'script_name': 'setup.py',
+ 'package_dir': {'issue191': support}}))
+ cmd.finalize_options()
+ ## FIXME why doesn't Config see the chdir above?
+ print cmd._nosetests__config.workingDir
+ cmd._nosetests__config.workingDir = support
+ cmd._nosetests__config.stream = buf
+ try:
+ cmd.run()
+ except SystemExit, e:
+ self.assertFalse(e.args[0], buf.getvalue())
+ else:
+ self.fail("cmd.run() did not exit")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_commands.pyc b/functional_tests/test_commands.pyc
new file mode 100644
index 0000000..9884faa
Binary files /dev/null and b/functional_tests/test_commands.pyc differ
diff --git a/functional_tests/test_config_files.py b/functional_tests/test_config_files.py
new file mode 100644
index 0000000..5f18f3a
--- /dev/null
+++ b/functional_tests/test_config_files.py
@@ -0,0 +1,41 @@
+import logging
+import os
+import unittest
+from nose.config import Config
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+class TestConfigurationFromFile(unittest.TestCase):
+ def setUp(self):
+ self.cfg_file = os.path.join(support, 'test.cfg')
+ # install mock root logger so that these tests don't stomp on
+ # the real logging config of the test runner
+ class MockLogger(logging.Logger):
+ root = logging.RootLogger(logging.WARNING)
+ manager = logging.Manager(root)
+
+ self.real_logger = logging.Logger
+ self.real_root = logging.root
+ logging.Logger = MockLogger
+ logging.root = MockLogger.root
+
+ def tearDown(self):
+ # reset real root logger
+ logging.Logger = self.real_logger
+ logging.root = self.real_root
+
+ def test_load_config_file(self):
+ c = Config(files=self.cfg_file)
+ c.configure(['test_load_config_file'])
+ self.assertEqual(c.verbosity, 10)
+
+ def test_config_file_set_by_arg(self):
+ c = Config()
+ c.configure(['test_config_file_set_by_arg',
+ '-c', self.cfg_file, '-v'])
+ # 10 from file, 1 more from cmd line
+ self.assertEqual(c.verbosity, 11)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_config_files.pyc b/functional_tests/test_config_files.pyc
new file mode 100644
index 0000000..f430364
Binary files /dev/null and b/functional_tests/test_config_files.pyc differ
diff --git a/functional_tests/test_coverage_plugin.py b/functional_tests/test_coverage_plugin.py
new file mode 100644
index 0000000..717f13a
--- /dev/null
+++ b/functional_tests/test_coverage_plugin.py
@@ -0,0 +1,78 @@
+"""Test the coverage plugin."""
+import os
+import unittest
+import shutil
+
+from nose.plugins import PluginTester
+from nose.plugins.cover import Coverage
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+
+class TestCoveragePlugin(PluginTester, unittest.TestCase):
+ activate = "--with-coverage"
+ args = ['-v', '--cover-package=blah', '--cover-html', '--cover-min-percentage', '25']
+ plugins = [Coverage()]
+ suitepath = os.path.join(support, 'coverage')
+
+ def setUp(self):
+ self.cover_file = os.path.join(os.getcwd(), '.coverage')
+ self.cover_html_dir = os.path.join(os.getcwd(), 'cover')
+ if os.path.exists(self.cover_file):
+ os.unlink(self.cover_file)
+ if os.path.exists(self.cover_html_dir):
+ shutil.rmtree(self.cover_html_dir)
+ super(TestCoveragePlugin, self).setUp()
+
+ def runTest(self):
+ self.assertTrue("blah 4 3 25% 1" in self.output)
+ self.assertTrue("Ran 1 test in""" in self.output)
+ # Assert coverage html report exists
+ self.assertTrue(os.path.exists(os.path.join(self.cover_html_dir,
+ 'index.html')))
+ # Assert coverage data is saved
+ self.assertTrue(os.path.exists(self.cover_file))
+
+
+class TestCoverageMinPercentagePlugin(PluginTester, unittest.TestCase):
+ activate = "--with-coverage"
+ args = ['-v', '--cover-package=blah', '--cover-min-percentage', '100']
+ plugins = [Coverage()]
+ suitepath = os.path.join(support, 'coverage')
+
+ def setUp(self):
+ self.cover_file = os.path.join(os.getcwd(), '.coverage')
+ self.cover_html_dir = os.path.join(os.getcwd(), 'cover')
+ if os.path.exists(self.cover_file):
+ os.unlink(self.cover_file)
+ if os.path.exists(self.cover_html_dir):
+ shutil.rmtree(self.cover_html_dir)
+ self.assertRaises(SystemExit,
+ super(TestCoverageMinPercentagePlugin, self).setUp)
+
+ def runTest(self):
+ pass
+
+
+class TestCoverageMinPercentageTOTALPlugin(PluginTester, unittest.TestCase):
+ activate = "--with-coverage"
+ args = ['-v', '--cover-package=blah', '--cover-package=moo',
+ '--cover-min-percentage', '100']
+ plugins = [Coverage()]
+ suitepath = os.path.join(support, 'coverage2')
+
+ def setUp(self):
+ self.cover_file = os.path.join(os.getcwd(), '.coverage')
+ self.cover_html_dir = os.path.join(os.getcwd(), 'cover')
+ if os.path.exists(self.cover_file):
+ os.unlink(self.cover_file)
+ if os.path.exists(self.cover_html_dir):
+ shutil.rmtree(self.cover_html_dir)
+ self.assertRaises(SystemExit,
+ super(TestCoverageMinPercentageTOTALPlugin, self).setUp)
+
+ def runTest(self):
+ pass
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_coverage_plugin.pyc b/functional_tests/test_coverage_plugin.pyc
new file mode 100644
index 0000000..b731e73
Binary files /dev/null and b/functional_tests/test_coverage_plugin.pyc differ
diff --git a/functional_tests/test_defaultpluginmanager.py b/functional_tests/test_defaultpluginmanager.py
new file mode 100644
index 0000000..28c1b86
--- /dev/null
+++ b/functional_tests/test_defaultpluginmanager.py
@@ -0,0 +1,22 @@
+import unittest
+from nose.plugins import Plugin
+from nose.plugins.manager import DefaultPluginManager
+
+class OverridesSkip(Plugin):
+ """Plugin to override the built-in Skip"""
+ enabled = True
+ name = 'skip'
+ is_overridden = True
+
+
+class TestDefaultPluginManager(unittest.TestCase):
+
+ def test_extraplugins_override_builtins(self):
+ pm = DefaultPluginManager()
+ pm.addPlugins(extraplugins=[OverridesSkip()])
+ pm.loadPlugins()
+ for plugin in pm.plugins:
+ if plugin.name == "skip":
+ break
+ overridden = getattr(plugin, 'is_overridden', False)
+ self.assertTrue(overridden)
diff --git a/functional_tests/test_defaultpluginmanager.pyc b/functional_tests/test_defaultpluginmanager.pyc
new file mode 100644
index 0000000..a73f080
Binary files /dev/null and b/functional_tests/test_defaultpluginmanager.pyc differ
diff --git a/functional_tests/test_doctest_plugin.py b/functional_tests/test_doctest_plugin.py
new file mode 100644
index 0000000..c91ecc5
--- /dev/null
+++ b/functional_tests/test_doctest_plugin.py
@@ -0,0 +1,44 @@
+import os
+import unittest
+from nose.plugins.doctests import Doctest
+from nose.plugins import PluginTester
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+class TestDoctestPlugin(PluginTester, unittest.TestCase):
+ activate = '--with-doctest'
+ args = ['-v']
+ plugins = [Doctest()]
+ suitepath = os.path.join(support, 'dtt')
+
+ def runTest(self):
+ print str(self.output)
+
+ assert 'Doctest: some_mod ... ok' in self.output
+ assert 'Doctest: some_mod.foo ... ok' in self.output
+ assert 'Ran 2 tests' in self.output
+ assert str(self.output).strip().endswith('OK')
+
+
+class TestDoctestFiles(PluginTester, unittest.TestCase):
+ activate = '--with-doctest'
+ args = ['-v', '--doctest-extension=.txt']
+ plugins = [Doctest()]
+ suitepath = os.path.join(support, 'dtt', 'docs')
+
+ def runTest(self):
+ print str(self.output)
+
+ expect = [
+ 'Doctest: doc.txt ... ok',
+ 'Doctest: errdoc.txt ... FAIL'
+ ]
+ for line in self.output:
+ if not line.strip():
+ continue
+ if line.startswith('='):
+ break
+ self.assertEqual(line.strip(), expect.pop(0))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_doctest_plugin.pyc b/functional_tests/test_doctest_plugin.pyc
new file mode 100644
index 0000000..714f557
Binary files /dev/null and b/functional_tests/test_doctest_plugin.pyc differ
diff --git a/functional_tests/test_entrypoints.py b/functional_tests/test_entrypoints.py
new file mode 100644
index 0000000..a57f218
--- /dev/null
+++ b/functional_tests/test_entrypoints.py
@@ -0,0 +1,17 @@
+import os
+import sys
+from nose.exc import SkipTest
+
+try:
+ from pkg_resources import EntryPoint
+except ImportError:
+ raise SkipTest("No setuptools available; skipping")
+
+here = os.path.dirname(__file__)
+support = os.path.join(here, 'support')
+ep = os.path.join(support, 'ep')
+
+
+def test_plugin_entrypoint_is_loadable():
+ epfile = os.path.join(ep, 'Some_plugin.egg-info', 'entry_points.txt')
+ assert EntryPoint.parse_map(open(epfile, 'r').readlines())
diff --git a/functional_tests/test_entrypoints.pyc b/functional_tests/test_entrypoints.pyc
new file mode 100644
index 0000000..239c7b5
Binary files /dev/null and b/functional_tests/test_entrypoints.pyc differ
diff --git a/functional_tests/test_failuredetail_plugin.py b/functional_tests/test_failuredetail_plugin.py
new file mode 100644
index 0000000..284cf49
--- /dev/null
+++ b/functional_tests/test_failuredetail_plugin.py
@@ -0,0 +1,50 @@
+import os
+import sys
+import unittest
+from nose.plugins.failuredetail import FailureDetail
+from nose.plugins.capture import Capture
+from nose.plugins import PluginTester
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+class TestFailureDetail(PluginTester, unittest.TestCase):
+ activate = "-d"
+ args = ['-v']
+ plugins = [FailureDetail()]
+ suitepath = os.path.join(support, 'fdp')
+
+ def runTest(self):
+ print '*' * 70
+ print str(self.output)
+ print '*' * 70
+
+ expect = \
+ 'AssertionError: a is not 4\n'
+ ' print "Hello"\n'
+ ' 2 = 2\n'
+ '>> assert 2 == 4, "a is not 4"'
+
+ assert expect in self.output
+
+
+class TestFailureDetailWithCapture(PluginTester, unittest.TestCase):
+ activate = "-d"
+ args = ['-v']
+ plugins = [FailureDetail(), Capture()]
+ suitepath = os.path.join(support, 'fdp/test_fdp_no_capt.py')
+
+ def runTest(self):
+ print '*' * 70
+ print str(self.output)
+ print '*' * 70
+
+ expect = \
+ 'AssertionError: a is not 4\n'
+ ' print "Hello"\n'
+ ' 2 = 2\n'
+ '>> assert 2 == 4, "a is not 4"'
+
+ assert expect in self.output
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_failuredetail_plugin.pyc b/functional_tests/test_failuredetail_plugin.pyc
new file mode 100644
index 0000000..2d78dd9
Binary files /dev/null and b/functional_tests/test_failuredetail_plugin.pyc differ
diff --git a/functional_tests/test_generator_fixtures.py b/functional_tests/test_generator_fixtures.py
new file mode 100644
index 0000000..3240141
--- /dev/null
+++ b/functional_tests/test_generator_fixtures.py
@@ -0,0 +1,58 @@
+from nose.tools import eq_
+called = []
+
+def outer_setup():
+ called.append('outer_setup')
+
+def outer_teardown():
+ called.append('outer_teardown')
+
+def inner_setup():
+ called.append('inner_setup')
+
+def inner_teardown():
+ called.append('inner_teardown')
+
+def test_gen():
+ called[:] = []
+ for i in range(0, 5):
+ yield check, i
+
+def check(i):
+ expect = ['outer_setup']
+ for x in range(0, i):
+ expect.append('inner_setup')
+ expect.append('inner_teardown')
+ expect.append('inner_setup')
+ eq_(called, expect)
+
+
+test_gen.setup = outer_setup
+test_gen.teardown = outer_teardown
+check.setup = inner_setup
+check.teardown = inner_teardown
+
+
+class TestClass(object):
+ def setup(self):
+ print "setup called in", self
+ self.called = ['setup']
+
+ def teardown(self):
+ print "teardown called in", self
+ eq_(self.called, ['setup'])
+ self.called.append('teardown')
+
+ def test(self):
+ print "test called in", self
+ for i in range(0, 5):
+ yield self.check, i
+
+ def check(self, i):
+ print "check called in", self
+ expect = ['setup']
+ #for x in range(0, i):
+ # expect.append('setup')
+ # expect.append('teardown')
+ #expect.append('setup')
+ eq_(self.called, expect)
diff --git a/functional_tests/test_generator_fixtures.pyc b/functional_tests/test_generator_fixtures.pyc
new file mode 100644
index 0000000..3e69ef2
Binary files /dev/null and b/functional_tests/test_generator_fixtures.pyc differ
diff --git a/functional_tests/test_id_plugin.py b/functional_tests/test_id_plugin.py
new file mode 100644
index 0000000..7b3d39d
--- /dev/null
+++ b/functional_tests/test_id_plugin.py
@@ -0,0 +1,261 @@
+import os
+import re
+import sys
+import tempfile
+import unittest
+
+from nose.plugins import PluginTester
+from nose.plugins.builtin import Doctest
+from nose.plugins.builtin import TestId
+from cPickle import dump, load
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+idfile = tempfile.mktemp()
+test_part = re.compile(r'(#\d+)? +([^(]+)')
+
+def teardown():
+ try:
+ os.remove(idfile)
+ except OSError:
+ pass
+
+class TestDiscoveryMode(PluginTester, unittest.TestCase):
+ activate = '--with-id'
+ plugins = [TestId()]
+ args = ['-v', '--id-file=%s' % idfile]
+ suitepath = os.path.join(support, 'idp')
+
+ def test_ids_added_to_output(self):
+ #print '>' * 70
+ #print str(self.output)
+ #print '<' * 70
+
+ for line in self.output:
+ if line.startswith('='):
+ break
+ if not line.strip():
+ continue
+ if 'test_gen' in line and not '(0,)' in line:
+ assert not line.startswith('#'), \
+ "Generated test line '%s' should not have id" % line
+ else:
+ assert line.startswith('#'), \
+ "Test line '%s' missing id" % line.strip()
+
+ # test that id file is written
+ def test_id_file_contains_ids_seen(self):
+ assert os.path.exists(idfile)
+ fh = open(idfile, 'rb')
+ ids = load(fh)['ids']
+ fh.close()
+ assert ids
+ assert ids.keys()
+ self.assertEqual(map(int, ids.keys()), ids.keys())
+ assert ids.values()
+
+
+class TestLoadNamesMode(PluginTester, unittest.TestCase):
+ """NOTE that this test passing requires the previous test case to
+ be run! (Otherwise the ids file will not exist)
+ """
+ activate = '--with-id'
+ plugins = [TestId()]
+ # Not a typo: # is optional before ids
+ args = ['-v', '--id-file=%s' % idfile, '2', '#5']
+ suitepath = None
+
+ def makeSuite(self):
+ return None
+
+ def test_load_ids(self):
+ #print '#' * 70
+ #print str(self.output)
+ #print '#' * 70
+
+ for line in self.output:
+ if line.startswith('#'):
+ assert line.startswith('#2 ') or line.startswith('#5 '), \
+ "Unexpected test line '%s'" % line
+ assert os.path.exists(idfile)
+ fh = open(idfile, 'rb')
+ ids = load(fh)
+ fh.close()
+ assert ids
+ assert ids.keys()
+ ids = ids['ids']
+ self.assertEqual(filter(lambda i: int(i), ids.keys()), ids.keys())
+ assert len(ids.keys()) > 2
+
+
+class TestLoadNamesMode_2(PluginTester, unittest.TestCase):
+ """NOTE that this test passing requires the previous test case to
+ be run! (Otherwise the ids file will not exist)
+
+ Tests that generators still only have id on one line
+ """
+ activate = '--with-id'
+ plugins = [TestId()]
+ args = ['-v', '--id-file=%s' % idfile, '9']
+ suitepath = None
+
+ def makeSuite(self):
+ return None
+
+ def test_load_ids(self):
+ #print '%' * 70
+ #print str(self.output)
+ #print '%' * 70
+
+ count = 0
+ for line in self.output:
+ if line.startswith('#'):
+ count += 1
+ self.assertEqual(count, 1)
+ teardown()
+
+
+class TestWithDoctest_1(PluginTester, unittest.TestCase):
+ activate = '--with-id'
+ plugins = [Doctest(), TestId()]
+ args = ['-v', '--id-file=%s' % idfile, '--with-doctest']
+ suitepath = os.path.join(support, 'idp')
+
+ def test_doctests_get_ids(self):
+ #print '>' * 70
+ #print str(self.output)
+ #print '>' * 70
+
+ last = None
+ for line in self.output:
+ if line.startswith('='):
+ break
+ if not line.strip():
+ continue
+ # assert line startswith # or test part matches last
+ m = test_part.match(line.rstrip())
+ assert m
+ idx, name = m.groups()
+ assert idx or last is None or name == last, \
+ "Expected an id on line %s" % line.strip()
+ last = name
+
+ fh = open(idfile, 'rb')
+ ids = load(fh)['ids']
+ fh.close()
+ for key, (file, mod, call) in ids.items():
+ assert mod != 'doctest', \
+ "Doctest test was incorrectly identified as being part of "\
+ "the doctest module itself (#%s)" % key
+
+
+class TestWithDoctest_2(PluginTester, unittest.TestCase):
+ activate = '--with-id'
+ plugins = [Doctest(), TestId()]
+ args = ['-v', '--id-file=%s' % idfile, '--with-doctest', '#2']
+ suitepath = None
+
+ def setUp(self):
+ sys.path.insert(0, os.path.join(support, 'idp'))
+ super(TestWithDoctest_2, self).setUp()
+
+ def tearDown(self):
+ sys.path.remove(os.path.join(support, 'idp'))
+ super(TestWithDoctest_2, self).tearDown()
+
+ def makeSuite(self):
+ return None
+
+ def test_load_ids_doctest(self):
+ print '*' * 70
+ print str(self.output)
+ print '*' * 70
+
+ assert 'Doctest: exm.add_one ... FAIL' in self.output
+
+ count = 0
+ for line in self.output:
+ if line.startswith('#'):
+ count += 1
+ self.assertEqual(count, 1)
+ teardown()
+
+
+class TestWithDoctestFileTests_1(PluginTester, unittest.TestCase):
+ activate = '--with-id'
+ plugins = [Doctest(), TestId()]
+ args = ['-v', '--id-file=%s' % idfile, '--with-doctest',
+ '--doctest-extension=.txt']
+ suitepath = os.path.join(support, 'dtt', 'docs')
+
+ def test_docfile_tests_get_ids(self):
+ print '>' * 70
+ print str(self.output)
+ print '>' * 70
+
+ last = None
+ for line in self.output:
+ if line.startswith('='):
+ break
+ # assert line startswith # or test part matches last
+ if not line.strip():
+ continue
+ m = test_part.match(line.rstrip())
+ assert m, "line %s does not match expected pattern" % line.strip()
+ idx, name = m.groups()
+ assert idx or last is None or name == last, \
+ "Expected an id on line %s" % line.strip()
+
+ last = name
+ fh = open(idfile, 'rb')
+ ids = load(fh)['ids']
+ fh.close()
+ for key, (file, mod, call) in ids.items():
+ assert mod != 'doctest', \
+ "Doctest test was incorrectly identified as being part of "\
+ "the doctest module itself (#%s)" % key
+
+
+class TestWithDoctestFileTests_2(PluginTester, unittest.TestCase):
+ activate = '--with-id'
+ plugins = [Doctest(), TestId()]
+ args = ['-v', '--id-file=%s' % idfile, '--with-doctest',
+ '--doctest-extension=.txt', '2']
+ suitepath = None
+
+ def setUp(self):
+ sys.path.insert(0, os.path.join(support, 'dtt', 'docs'))
+ super(TestWithDoctestFileTests_2, self).setUp()
+
+ def tearDown(self):
+ sys.path.remove(os.path.join(support, 'dtt', 'docs'))
+ super(TestWithDoctestFileTests_2, self).tearDown()
+
+ def makeSuite(self):
+ return None
+
+ def test_load_from_name_id_docfile_test(self):
+ print '*' * 70
+ print str(self.output)
+ print '*' * 70
+
+ assert 'Doctest: errdoc.txt ... FAIL' in self.output
+
+ count = 0
+ for line in self.output:
+ if line.startswith('#'):
+ count += 1
+ assert count == 1
+ teardown()
+
+
+if __name__ == '__main__':
+ import logging
+ logging.basicConfig()
+ l = logging.getLogger('nose.plugins.testid')
+ l.setLevel(logging.DEBUG)
+
+ try:
+ unittest.main()
+ finally:
+ teardown()
+
diff --git a/functional_tests/test_id_plugin.pyc b/functional_tests/test_id_plugin.pyc
new file mode 100644
index 0000000..8d1d349
Binary files /dev/null and b/functional_tests/test_id_plugin.pyc differ
diff --git a/functional_tests/test_importer.py b/functional_tests/test_importer.py
new file mode 100644
index 0000000..c24fdcf
--- /dev/null
+++ b/functional_tests/test_importer.py
@@ -0,0 +1,168 @@
+import os
+import sys
+import unittest
+from nose.importer import Importer
+
+
+class TestImporter(unittest.TestCase):
+
+ def setUp(self):
+ self.dir = os.path.normpath(os.path.join(os.path.dirname(__file__),
+ 'support'))
+ self.imp = Importer()
+ self._mods = sys.modules.copy()
+ self._path = sys.path[:]
+ sys.modules.pop('mod', None)
+ sys.modules.pop('pak', None)
+ sys.modules.pop('pak.mod', None)
+ sys.modules.pop('pak.sub', None)
+
+ def tearDown(self):
+ to_del = [ m for m in sys.modules.keys() if
+ m not in self._mods ]
+ if to_del:
+ for mod in to_del:
+ del sys.modules[mod]
+ sys.modules.update(self._mods)
+ sys.path = self._path[:]
+
+ def test_import_from_dir(self):
+ imp = self.imp
+
+ d1 = os.path.join(self.dir, 'dir1')
+ d2 = os.path.join(self.dir, 'dir2')
+
+ # simple name
+ m1 = imp.importFromDir(d1, 'mod')
+ m2 = imp.importFromDir(d2, 'mod')
+ self.assertNotEqual(m1, m2)
+ self.assertNotEqual(m1.__file__, m2.__file__)
+
+ # dotted name
+ p1 = imp.importFromDir(d1, 'pak.mod')
+ p2 = imp.importFromDir(d2, 'pak.mod')
+ self.assertNotEqual(p1, p2)
+ self.assertNotEqual(p1.__file__, p2.__file__)
+
+ def test_import_from_path(self):
+ imp = self.imp
+
+ jn = os.path.join
+ d1 = jn(self.dir, 'dir1')
+ d2 = jn(self.dir, 'dir2')
+
+ # simple name
+ m1 = imp.importFromPath(jn(d1, 'mod.py'), 'mod')
+ m2 = imp.importFromPath(jn(d2, 'mod.py'), 'mod')
+ self.assertNotEqual(m1, m2)
+ self.assertNotEqual(m1.__file__, m2.__file__)
+
+ # dotted name
+ p1 = imp.importFromPath(jn(d1, 'pak', 'mod.py'), 'pak.mod')
+ p2 = imp.importFromPath(jn(d2, 'pak', 'mod.py'), 'pak.mod')
+ self.assertNotEqual(p1, p2)
+ self.assertNotEqual(p1.__file__, p2.__file__)
+
+ # simple name -- package
+ sp1 = imp.importFromPath(jn(d1, 'pak'), 'pak')
+ sp2 = imp.importFromPath(jn(d2, 'pak'), 'pak')
+ self.assertNotEqual(sp1, sp2)
+ assert sp1.__path__
+ assert sp2.__path__
+ self.assertNotEqual(sp1.__path__, sp2.__path__)
+
+ # dotted name -- package
+ dp1 = imp.importFromPath(jn(d1, 'pak', 'sub'), 'pak.sub')
+ dp2 = imp.importFromPath(jn(d2, 'pak', 'sub'), 'pak.sub')
+ self.assertNotEqual(dp1, dp2)
+ assert dp1.__path__
+ assert dp2.__path__
+ self.assertNotEqual(dp1.__path__, dp2.__path__)
+
+ def test_import_sets_intermediate_modules(self):
+ imp = self.imp
+ path = os.path.join(self.dir,
+ 'package2', 'test_pak', 'test_sub', 'test_mod.py')
+ mod = imp.importFromPath(path, 'test_pak.test_sub.test_mod')
+ print mod, dir(mod)
+ assert 'test_pak' in sys.modules, 'test_pak was not imported?'
+ test_pak = sys.modules['test_pak']
+ assert hasattr(test_pak, 'test_sub'), "test_pak.test_sub was not set"
+
+ def test_cached_no_reload(self):
+ imp = self.imp
+ d1 = os.path.join(self.dir, 'dir1')
+ m1 = imp.importFromDir(d1, 'mod')
+ m2 = imp.importFromDir(d1, 'mod')
+ assert m1 is m2, "%s is not %s" % (m1, m2)
+
+ def test_cached_no_reload_dotted(self):
+ imp = self.imp
+ d1 = os.path.join(self.dir, 'dir1')
+ p1 = imp.importFromDir(d1, 'pak.mod')
+ p2 = imp.importFromDir(d1, 'pak.mod')
+ assert p1 is p2, "%s is not %s" % (p1, p2)
+
+ def test_import_sets_sys_modules(self):
+ imp = self.imp
+ d1 = os.path.join(self.dir, 'dir1')
+ p1 = imp.importFromDir(d1, 'pak.mod')
+ assert sys.modules['pak.mod'] is p1, "pak.mod not in sys.modules"
+ assert sys.modules['pak'], "pak not in sys.modules"
+ assert sys.modules['pak'].mod is p1, \
+ "sys.modules['pak'].mod is not the module we loaded"
+
+ def test_failed_import_raises_import_error(self):
+ imp = self.imp
+ def bad_import():
+ imp.importFromPath(self.dir, 'no.such.module')
+ self.assertRaises(ImportError, bad_import)
+
+ def test_sys_modules_same_path_no_reload(self):
+ imp = self.imp
+
+ d1 = os.path.join(self.dir, 'dir1')
+ d2 = os.path.join(self.dir, 'dir2')
+ sys.path.insert(0, d1)
+ mod_sys_imported = __import__('mod')
+ mod_nose_imported = imp.importFromDir(d1, 'mod')
+ assert mod_nose_imported is mod_sys_imported, \
+ "nose reimported a module in sys.modules from the same path"
+
+ mod_nose_imported2 = imp.importFromDir(d2, 'mod')
+ assert mod_nose_imported2 != mod_sys_imported, \
+ "nose failed to reimport same name, different dir"
+
+ def test_import_pkg_from_path_fpw(self):
+ imp = self.imp
+ imp.config.firstPackageWins = True
+ jn = os.path.join
+ d1 = jn(self.dir, 'dir1')
+ d2 = jn(self.dir, 'dir2')
+
+ # dotted name
+ p1 = imp.importFromPath(jn(d1, 'pak', 'mod.py'), 'pak.mod')
+ p2 = imp.importFromPath(jn(d2, 'pak', 'mod.py'), 'pak.mod')
+ self.assertEqual(p1, p2)
+ self.assertEqual(p1.__file__, p2.__file__)
+
+ # simple name -- package
+ sp1 = imp.importFromPath(jn(d1, 'pak'), 'pak')
+ sp2 = imp.importFromPath(jn(d2, 'pak'), 'pak')
+ self.assertEqual(sp1, sp2)
+ assert sp1.__path__
+ assert sp2.__path__
+ self.assertEqual(sp1.__path__, sp2.__path__)
+
+ # dotted name -- package
+ dp1 = imp.importFromPath(jn(d1, 'pak', 'sub'), 'pak.sub')
+ dp2 = imp.importFromPath(jn(d2, 'pak', 'sub'), 'pak.sub')
+ self.assertEqual(dp1, dp2)
+ assert dp1.__path__
+ assert dp2.__path__
+ self.assertEqual(dp1.__path__, dp2.__path__)
+
+if __name__ == '__main__':
+ import logging
+ logging.basicConfig(level=logging.DEBUG)
+ unittest.main()
diff --git a/functional_tests/test_importer.pyc b/functional_tests/test_importer.pyc
new file mode 100644
index 0000000..f9d1147
Binary files /dev/null and b/functional_tests/test_importer.pyc differ
diff --git a/functional_tests/test_isolate_plugin.py b/functional_tests/test_isolate_plugin.py
new file mode 100644
index 0000000..087dcaa
--- /dev/null
+++ b/functional_tests/test_isolate_plugin.py
@@ -0,0 +1,57 @@
+import os
+import sys
+import unittest
+from nose.plugins.isolate import IsolationPlugin
+from nose.plugins import PluginTester
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+class TestDiscovery(PluginTester, unittest.TestCase):
+ activate = '--with-isolation'
+ args = ['-v']
+ plugins = [IsolationPlugin()]
+ suitepath = os.path.join(support, 'ipt')
+
+ def runTest(self):
+ print str(self.output)
+
+ for line in self.output:
+ if not line.strip():
+ continue
+ if line.startswith('-'):
+ break
+ assert line.strip().endswith('ok'), \
+ "Failed test: %s" % line.strip()
+
+
+class TestLoadFromNames(PluginTester, unittest.TestCase):
+ activate = '--with-isolation'
+ args = ['-v', 'test1/tests.py', 'test2/tests.py']
+ plugins = [IsolationPlugin()]
+ suitepath = None
+
+ def setUp(self):
+ self._dir = os.getcwd()
+ os.chdir(os.path.join(support, 'ipt'))
+ super(TestLoadFromNames, self).setUp()
+
+ def tearDown(self):
+ os.chdir(self._dir)
+ super(TestLoadFromNames, self).tearDown()
+
+ def makeSuite(self):
+ return None
+
+ def runTest(self):
+ print str(self.output)
+
+ for line in self.output:
+ if not line.strip():
+ continue
+ if line.startswith('-'):
+ break
+ assert line.strip().endswith('ok'), \
+ "Failed test: %s" % line.strip()
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_isolate_plugin.pyc b/functional_tests/test_isolate_plugin.pyc
new file mode 100644
index 0000000..93d9b94
Binary files /dev/null and b/functional_tests/test_isolate_plugin.pyc differ
diff --git a/functional_tests/test_issue120/support/some_test.py b/functional_tests/test_issue120/support/some_test.py
new file mode 100644
index 0000000..9947266
--- /dev/null
+++ b/functional_tests/test_issue120/support/some_test.py
@@ -0,0 +1,3 @@
+def some_test():
+ pass
+
diff --git a/functional_tests/test_issue120/support/some_test.pyc b/functional_tests/test_issue120/support/some_test.pyc
new file mode 100644
index 0000000..2a48d98
Binary files /dev/null and b/functional_tests/test_issue120/support/some_test.pyc differ
diff --git a/functional_tests/test_issue120/test_named_test_with_doctest.rst b/functional_tests/test_issue120/test_named_test_with_doctest.rst
new file mode 100644
index 0000000..f05deb7
--- /dev/null
+++ b/functional_tests/test_issue120/test_named_test_with_doctest.rst
@@ -0,0 +1,25 @@
+Naming a non-existent test using the colon syntax (foo.py:my_test)
+with plugin doctests enabled used to cause a failure with a ValueError
+from module doctest, losing the original failure (failure to find the
+test).
+
+ >>> import os
+ >>> from nose.plugins.plugintest import run_buffered as run
+ >>> from nose.plugins.doctests import Doctest
+
+ >>> support = os.path.join(os.path.dirname(__file__), 'support')
+ >>> test_name = os.path.join(support, 'some_test.py') + ':nonexistent'
+ >>> run(argv=['nosetests', '--with-doctest', test_name],
+ ... plugins=[Doctest()])
+ E
+ ======================================================================
+ ERROR: Failure: ValueError (No such test nonexistent)
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ ValueError: No such test nonexistent
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ FAILED (errors=1)
diff --git a/functional_tests/test_issue_072.py b/functional_tests/test_issue_072.py
new file mode 100644
index 0000000..3848f6f
--- /dev/null
+++ b/functional_tests/test_issue_072.py
@@ -0,0 +1,45 @@
+import os
+import sys
+import unittest
+
+from nose.plugins import PluginTester
+from nose.plugins.builtin import FailureDetail, Capture
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+
+class TestFailureDetailWorks(PluginTester, unittest.TestCase):
+ activate = '-d'
+ plugins = [FailureDetail()]
+ args = ['-v']
+ suitepath = os.path.join(support, 'issue072')
+
+ def test_assert_info_in_output(self):
+ print
+ print '!' * 70
+ print str(self.output)
+ print '!' * 70
+ print
+ assert '>> assert 4 == 2' in str(self.output)
+
+class TestFailureDetailWorksWhenChained(PluginTester, unittest.TestCase):
+ activate = '-d'
+ plugins = [FailureDetail(), Capture()]
+ args = ['-v']
+ suitepath = os.path.join(support, 'issue072')
+
+ def test_assert_info_and_capt_stdout_in_output(self):
+ out = str(self.output)
+ print
+ print 'x' * 70
+ print out
+ print 'x' * 70
+ print
+
+ assert '>> assert 4 == 2' in out, \
+ "Assert info not found in chained output"
+ assert 'something' in out, \
+ "Captured stdout not found in chained output"
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_issue_072.pyc b/functional_tests/test_issue_072.pyc
new file mode 100644
index 0000000..cbf9e4e
Binary files /dev/null and b/functional_tests/test_issue_072.pyc differ
diff --git a/functional_tests/test_issue_082.py b/functional_tests/test_issue_082.py
new file mode 100644
index 0000000..06fa019
--- /dev/null
+++ b/functional_tests/test_issue_082.py
@@ -0,0 +1,74 @@
+import os
+import re
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+import sys
+import unittest
+
+from nose.plugins import Plugin, PluginTester
+from nose.plugins.builtin import FailureDetail, Capture, Doctest
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+
+class IncludeUnderscoreFilesPlugin(Plugin):
+
+ # Note that this is purely for purposes of testing nose itself, and is
+ # not intended to be a useful plugin. In particular, the rules it
+ # applies for _*.py files differ from the nose defaults (e.g. the
+ # --testmatch option is ignored).
+
+ name = "underscorefiles"
+
+ def wantFile(self, file):
+ base = os.path.basename(file)
+ dummy, ext = os.path.splitext(base)
+ pysrc = ext == '.py'
+ if pysrc and os.path.basename(file).startswith("_"):
+ return True
+
+ def wantDirectory(self, dirname):
+ if os.path.basename(dirname).startswith("_"):
+ return True
+
+
+class TestIncludeUnderscoreFiles(PluginTester, unittest.TestCase):
+ activate = '--with-underscorefiles'
+ plugins = [IncludeUnderscoreFilesPlugin(), Doctest()]
+ args = ['-v', '--with-doctest']
+ suitepath = os.path.join(support, 'issue082')
+ ignoreFiles = (re.compile(r'^\.'),
+ # we want _*.py, but don't want e.g. __init__.py, since that
+ # appears to cause infinite recursion at the moment
+ re.compile(r'^__'),
+ re.compile(r'^setup\.py$')
+ )
+
+ def test_assert_info_in_output(self):
+ print self.output
+ # In future, all four test cases will be run. Backwards-compatibility
+ # means that can't be done in nose 0.10.
+ assert '_mypackage._eggs' not in str(self.output)
+ assert '_mypackage.bacon' not in str(self.output)
+ assert 'Doctest: mypublicpackage._foo ... FAIL' in str(self.output)
+ assert 'Doctest: mypublicpackage.bar ... FAIL' in str(self.output)
+
+
+class TestExcludeUnderscoreFilesByDefault(PluginTester, unittest.TestCase):
+ activate = '-v'
+ plugins = [Doctest()]
+ args = ['--with-doctest']
+ suitepath = os.path.join(support, 'issue082')
+
+ def test_assert_info_in_output(self):
+ print self.output
+ assert '_mypackage._eggs' not in str(self.output)
+ assert '_mypackage.bacon' not in str(self.output)
+ assert 'mypublicpackage._foo' not in str(self.output)
+ assert 'Doctest: mypublicpackage.bar ... FAIL' in str(self.output)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_issue_082.pyc b/functional_tests/test_issue_082.pyc
new file mode 100644
index 0000000..66bd500
Binary files /dev/null and b/functional_tests/test_issue_082.pyc differ
diff --git a/functional_tests/test_issue_408.py b/functional_tests/test_issue_408.py
new file mode 100644
index 0000000..17ea65c
--- /dev/null
+++ b/functional_tests/test_issue_408.py
@@ -0,0 +1,25 @@
+import os
+import unittest
+
+from nose.plugins import Plugin, PluginTester
+#from nose.plugins.builtin import FailureDetail, Capture, Doctest
+
+support = os.path.join(os.path.dirname(__file__), 'support', 'issue408')
+
+class TestIssue408(PluginTester, unittest.TestCase):
+ args = ['--where='+support, 'test:testa.test1', 'test:testa.test2', 'test:testb.test1', 'test:testb.test2']
+ activate = "-v"
+
+ def makeSuite(self):
+ # make PluginTester happy, because we don't specify suitepath, we
+ # have to implement this function
+ return None
+
+ def test_no_failure(self):
+ output = str(self.output)
+ assert 'FAIL:' not in output
+ assert 'AssertionError' not in output
+ assert 'OK' in output
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_issue_408.pyc b/functional_tests/test_issue_408.pyc
new file mode 100644
index 0000000..2803ff7
Binary files /dev/null and b/functional_tests/test_issue_408.pyc differ
diff --git a/functional_tests/test_load_tests_from_test_case.py b/functional_tests/test_load_tests_from_test_case.py
new file mode 100644
index 0000000..42f8563
--- /dev/null
+++ b/functional_tests/test_load_tests_from_test_case.py
@@ -0,0 +1,56 @@
+"""
+Tests that plugins can override loadTestsFromTestCase
+"""
+import os
+import unittest
+from nose import loader
+from nose.plugins import PluginTester
+from nose.plugins.base import Plugin
+
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+
+class NoFixturePlug(Plugin):
+ enabled = True
+
+ def options(self, parser, env):
+ print "options"
+ pass
+
+ def configure(self, options, conf):
+ print "configure"
+ pass
+
+ def loadTestsFromTestCase(self, testCaseClass):
+ print "Called!"
+ class Derived(testCaseClass):
+ def setUp(self):
+ pass
+ def tearDown(self):
+ pass
+ # must use nose loader here because the default loader in 2.3
+ # won't load tests from base classes
+ l = loader.TestLoader()
+ return l.loadTestsFromTestCase(Derived)
+
+
+class TestLoadTestsFromTestCaseHook(PluginTester, unittest.TestCase):
+
+ activate = '-v'
+ args = []
+ plugins = [NoFixturePlug()]
+ suitepath = os.path.join(support, 'ltftc')
+
+ def runTest(self):
+ expect = [
+ 'test_value (%s.Derived) ... ERROR' % __name__,
+ 'test_value (tests.Tests) ... ok']
+ print str(self.output)
+ for line in self.output:
+ if expect:
+ self.assertEqual(line.strip(), expect.pop(0))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_load_tests_from_test_case.pyc b/functional_tests/test_load_tests_from_test_case.pyc
new file mode 100644
index 0000000..5885760
Binary files /dev/null and b/functional_tests/test_load_tests_from_test_case.pyc differ
diff --git a/functional_tests/test_loader.py b/functional_tests/test_loader.py
new file mode 100644
index 0000000..6f73559
--- /dev/null
+++ b/functional_tests/test_loader.py
@@ -0,0 +1,451 @@
+import os
+import sys
+import unittest
+from difflib import ndiff
+from cStringIO import StringIO
+
+from nose.config import Config
+from nose.plugins.manager import PluginManager
+from nose.plugins.skip import Skip
+from nose import loader
+from nose import suite
+from nose.result import _TextTestResult
+try:
+ # 2.7+
+ from unittest.runner import _WritelnDecorator
+except ImportError:
+ from unittest import _WritelnDecorator
+
+support = os.path.abspath(os.path.join(os.path.dirname(__file__), 'support'))
+
+class TestNoseTestLoader(unittest.TestCase):
+
+ def setUp(self):
+ self._mods = sys.modules.copy()
+ suite.ContextSuiteFactory.suiteClass = TreePrintContextSuite
+
+ def tearDown(self):
+ to_del = [ m for m in sys.modules.keys() if
+ m not in self._mods ]
+ if to_del:
+ for mod in to_del:
+ del sys.modules[mod]
+ sys.modules.update(self._mods)
+ suite.ContextSuiteFactory.suiteClass = suite.ContextSuite
+
+ def test_load_from_name_file(self):
+ res = unittest.TestResult()
+ wd = os.path.join(support, 'package1')
+ l = loader.TestLoader(workingDir=wd)
+
+ file_suite = l.loadTestsFromName('tests/test_example_function.py')
+ file_suite(res)
+ assert not res.errors, res.errors
+ assert not res.failures, res.failures
+
+ def test_load_from_name_dot(self):
+ res = unittest.TestResult()
+ wd = os.path.join(support, 'package1')
+ l = loader.TestLoader(workingDir=wd)
+ dir_suite = l.loadTestsFromName('.')
+ dir_suite(res)
+ assert not res.errors, res.errors
+ assert not res.failures, res.failures
+
+ def test_load_from_name_file_callable(self):
+ res = unittest.TestResult()
+ wd = os.path.join(support, 'package1')
+ l = loader.TestLoader(workingDir=wd)
+ suite = l.loadTestsFromName(
+ 'tests/test_example_function.py:test_times_two')
+ suite(res)
+ assert not res.errors, res.errors
+ assert not res.failures, res.failures
+ self.assertEqual(res.testsRun, 1)
+
+ def test_fixture_context(self):
+ res = unittest.TestResult()
+ wd = os.path.join(support, 'package2')
+ l = loader.TestLoader(workingDir=wd)
+ dir_suite = l.loadTestsFromName('.')
+ dir_suite(res)
+
+ m = sys.modules['test_pak']
+ print "test pak state", m.state
+
+ assert not res.errors, res.errors
+ assert not res.failures, res.failures
+ self.assertEqual(res.testsRun, 5)
+
+ # Expected order of calls
+ expect = ['test_pak.setup',
+ 'test_pak.test_mod.setup',
+ 'test_pak.test_mod.test_add',
+ 'test_pak.test_mod.test_minus',
+ 'test_pak.test_mod.teardown',
+ 'test_pak.test_sub.setup',
+ 'test_pak.test_sub.test_mod.setup',
+ 'test_pak.test_sub.test_mod.TestMaths.setup_class',
+ 'test_pak.test_sub.test_mod.TestMaths.setup',
+ 'test_pak.test_sub.test_mod.TestMaths.test_div',
+ 'test_pak.test_sub.test_mod.TestMaths.teardown',
+ 'test_pak.test_sub.test_mod.TestMaths.setup',
+ 'test_pak.test_sub.test_mod.TestMaths.test_two_two',
+ 'test_pak.test_sub.test_mod.TestMaths.teardown',
+ 'test_pak.test_sub.test_mod.TestMaths.teardown_class',
+ 'test_pak.test_sub.test_mod.test',
+ 'test_pak.test_sub.test_mod.teardown',
+ 'test_pak.test_sub.teardown',
+ 'test_pak.teardown']
+ self.assertEqual(len(m.state), len(expect))
+ for item in m.state:
+ self.assertEqual(item, expect.pop(0))
+
+ def test_fixture_context_name_is_module(self):
+ res = unittest.TestResult()
+ wd = os.path.join(support, 'package2')
+ l = loader.TestLoader(workingDir=wd)
+ suite = l.loadTestsFromName('test_pak.test_mod')
+ suite(res)
+
+ assert 'test_pak' in sys.modules, \
+ "Context did not load test_pak"
+ m = sys.modules['test_pak']
+ print "test pak state", m.state
+ expect = ['test_pak.setup',
+ 'test_pak.test_mod.setup',
+ 'test_pak.test_mod.test_add',
+ 'test_pak.test_mod.test_minus',
+ 'test_pak.test_mod.teardown',
+ 'test_pak.teardown']
+ self.assertEqual(len(m.state), len(expect))
+ for item in m.state:
+ self.assertEqual(item, expect.pop(0))
+
+ def test_fixture_context_name_is_test_function(self):
+ res = unittest.TestResult()
+ wd = os.path.join(support, 'package2')
+ l = loader.TestLoader(workingDir=wd)
+ suite = l.loadTestsFromName('test_pak.test_mod:test_add')
+ suite(res)
+
+ assert 'test_pak' in sys.modules, \
+ "Context did not load test_pak"
+ m = sys.modules['test_pak']
+ print "test pak state", m.state
+ expect = ['test_pak.setup',
+ 'test_pak.test_mod.setup',
+ 'test_pak.test_mod.test_add',
+ 'test_pak.test_mod.teardown',
+ 'test_pak.teardown']
+ self.assertEqual(len(m.state), len(expect))
+ for item in m.state:
+ self.assertEqual(item, expect.pop(0))
+
+ def test_fixture_context_name_is_test_class(self):
+ res = unittest.TestResult()
+ wd = os.path.join(support, 'package2')
+ l = loader.TestLoader(workingDir=wd)
+ suite = l.loadTestsFromName(
+ 'test_pak.test_sub.test_mod:TestMaths')
+ suite(res)
+
+ assert 'test_pak' in sys.modules, \
+ "Context did not load test_pak"
+ m = sys.modules['test_pak']
+ # print "test pak state", m.state
+ expect = ['test_pak.setup',
+ 'test_pak.test_sub.setup',
+ 'test_pak.test_sub.test_mod.setup',
+ 'test_pak.test_sub.test_mod.TestMaths.setup_class',
+ 'test_pak.test_sub.test_mod.TestMaths.setup',
+ 'test_pak.test_sub.test_mod.TestMaths.test_div',
+ 'test_pak.test_sub.test_mod.TestMaths.teardown',
+ 'test_pak.test_sub.test_mod.TestMaths.setup',
+ 'test_pak.test_sub.test_mod.TestMaths.test_two_two',
+ 'test_pak.test_sub.test_mod.TestMaths.teardown',
+ 'test_pak.test_sub.test_mod.TestMaths.teardown_class',
+ 'test_pak.test_sub.test_mod.teardown',
+ 'test_pak.test_sub.teardown',
+ 'test_pak.teardown']
+ self.assertEqual(m.state, expect, diff(expect, m.state))
+
+ def test_fixture_context_name_is_test_class_test(self):
+ res = unittest.TestResult()
+ wd = os.path.join(support, 'package2')
+ l = loader.TestLoader(workingDir=wd)
+ suite = l.loadTestsFromName(
+ 'test_pak.test_sub.test_mod:TestMaths.test_div')
+ suite(res)
+
+ assert 'test_pak' in sys.modules, \
+ "Context not load test_pak"
+ m = sys.modules['test_pak']
+ print "test pak state", m.state
+ expect = ['test_pak.setup',
+ 'test_pak.test_sub.setup',
+ 'test_pak.test_sub.test_mod.setup',
+ 'test_pak.test_sub.test_mod.TestMaths.setup_class',
+ 'test_pak.test_sub.test_mod.TestMaths.setup',
+ 'test_pak.test_sub.test_mod.TestMaths.test_div',
+ 'test_pak.test_sub.test_mod.TestMaths.teardown',
+ 'test_pak.test_sub.test_mod.TestMaths.teardown_class',
+ 'test_pak.test_sub.test_mod.teardown',
+ 'test_pak.test_sub.teardown',
+ 'test_pak.teardown']
+ self.assertEqual(m.state, expect, diff(expect, m.state))
+
+ def test_fixture_context_multiple_names(self):
+ res = unittest.TestResult()
+ wd = os.path.join(support, 'package2')
+ l = loader.TestLoader(workingDir=wd)
+ suite = l.loadTestsFromNames(
+ ['test_pak.test_sub.test_mod:TestMaths.test_div',
+ 'test_pak.test_sub.test_mod:TestMaths.test_two_two',
+ 'test_pak.test_mod:test_add'])
+ print suite
+ suite(res)
+ assert not res.errors, res.errors
+ assert not res.failures, res.failures
+ assert 'test_pak' in sys.modules, \
+ "Context not load test_pak"
+ m = sys.modules['test_pak']
+ print "test pak state", m.state
+ expect = ['test_pak.setup',
+ 'test_pak.test_sub.setup',
+ 'test_pak.test_sub.test_mod.setup',
+ 'test_pak.test_sub.test_mod.TestMaths.setup_class',
+ 'test_pak.test_sub.test_mod.TestMaths.setup',
+ 'test_pak.test_sub.test_mod.TestMaths.test_div',
+ 'test_pak.test_sub.test_mod.TestMaths.teardown',
+ 'test_pak.test_sub.test_mod.TestMaths.setup',
+ 'test_pak.test_sub.test_mod.TestMaths.test_two_two',
+ 'test_pak.test_sub.test_mod.TestMaths.teardown',
+ 'test_pak.test_sub.test_mod.TestMaths.teardown_class',
+ 'test_pak.test_sub.test_mod.teardown',
+ 'test_pak.test_sub.teardown',
+ 'test_pak.test_mod.setup',
+ 'test_pak.test_mod.test_add',
+ 'test_pak.test_mod.teardown',
+ 'test_pak.teardown']
+ self.assertEqual(m.state, expect, diff(expect, m.state))
+
+ def test_fixture_context_multiple_names_some_common_ancestors(self):
+ stream = _WritelnDecorator(StringIO())
+ res = _TextTestResult(stream, 0, 2)
+ wd = os.path.join(support, 'ltfn')
+ l = loader.TestLoader(workingDir=wd)
+ suite = l.loadTestsFromNames(
+ ['test_pak1.test_mod',
+ 'test_pak2:test_two_two',
+ 'test_pak1:test_one_one'])
+ print suite
+ suite(res)
+ res.printErrors()
+ print stream.getvalue()
+ assert not res.errors, res.errors
+ assert not res.failures, res.failures
+ assert 'state' in sys.modules, \
+ "Context not load state module"
+ m = sys.modules['state']
+ print "state", m.called
+
+ expect = ['test_pak1.setup',
+ 'test_pak1.test_mod.setup',
+ 'test_pak1.test_mod.test_one_mod_one',
+ 'test_pak1.test_mod.teardown',
+ 'test_pak1.test_one_one',
+ 'test_pak1.teardown',
+ 'test_pak2.setup',
+ 'test_pak2.test_two_two',
+ 'test_pak2.teardown']
+ self.assertEqual(m.called, expect, diff(expect, m.called))
+
+ def test_fixture_context_multiple_names_no_common_ancestors(self):
+ stream = _WritelnDecorator(StringIO())
+ res = _TextTestResult(stream, 0, 2)
+ wd = os.path.join(support, 'ltfn')
+ l = loader.TestLoader(workingDir=wd)
+ suite = l.loadTestsFromNames(
+ ['test_pak1.test_mod',
+ 'test_pak2:test_two_two',
+ 'test_mod'])
+ print suite
+ suite(res)
+ res.printErrors()
+ print stream.getvalue()
+ assert not res.errors, res.errors
+ assert not res.failures, res.failures
+ assert 'state' in sys.modules, \
+ "Context not load state module"
+ m = sys.modules['state']
+ print "state", m.called
+
+ expect = ['test_pak1.setup',
+ 'test_pak1.test_mod.setup',
+ 'test_pak1.test_mod.test_one_mod_one',
+ 'test_pak1.test_mod.teardown',
+ 'test_pak1.teardown',
+ 'test_pak2.setup',
+ 'test_pak2.test_two_two',
+ 'test_pak2.teardown',
+ 'test_mod.setup',
+ 'test_mod.test_mod',
+ 'test_mod.teardown']
+ self.assertEqual(m.called, expect, diff(expect, m.called))
+
+ def test_mod_setup_fails_no_tests_run(self):
+ ctx = os.path.join(support, 'ctx')
+ l = loader.TestLoader(workingDir=ctx)
+ suite = l.loadTestsFromName('mod_setup_fails.py')
+
+ res = unittest.TestResult()
+ suite(res)
+
+ assert res.errors
+ assert not res.failures, res.failures
+ assert res.testsRun == 0, \
+ "Expected to run 0 tests but ran %s" % res.testsRun
+
+ def test_mod_setup_skip_no_tests_run_no_errors(self):
+ config = Config(plugins=PluginManager(plugins=[Skip()]))
+ ctx = os.path.join(support, 'ctx')
+ l = loader.TestLoader(workingDir=ctx, config=config)
+ suite = l.loadTestsFromName('mod_setup_skip.py')
+
+ res = unittest.TestResult()
+ suite(res)
+
+ assert not suite.was_setup, "Suite setup did not fail"
+ assert not res.errors, res.errors
+ assert not res.failures, res.failures
+ assert res.skipped
+ assert res.testsRun == 0, \
+ "Expected to run 0 tests but ran %s" % res.testsRun
+
+ def test_mod_import_skip_one_test_no_errors(self):
+ config = Config(plugins=PluginManager(plugins=[Skip()]))
+ ctx = os.path.join(support, 'ctx')
+ l = loader.TestLoader(workingDir=ctx, config=config)
+ suite = l.loadTestsFromName('mod_import_skip.py')
+
+ res = unittest.TestResult()
+ suite(res)
+
+ assert not res.errors, res.errors
+ assert not res.failures, res.failures
+ assert res.testsRun == 1, \
+ "Expected to run 1 tests but ran %s" % res.testsRun
+
+ def test_failed_import(self):
+ ctx = os.path.join(support, 'ctx')
+ l = loader.TestLoader(workingDir=ctx)
+ suite = l.loadTestsFromName('no_such_module.py')
+
+ res = _TextTestResult(
+ stream=_WritelnDecorator(sys.stdout),
+ descriptions=0, verbosity=1)
+ suite(res)
+
+ print res.errors
+ res.printErrors()
+ assert res.errors, "Expected errors but got none"
+ assert not res.failures, res.failures
+ assert res.testsRun == 1, \
+ "Expected to run 1 tests but ran %s" % res.testsRun
+
+ def test_failed_import_module_name(self):
+ ctx = os.path.join(support, 'ctx')
+ l = loader.TestLoader(workingDir=ctx)
+ suite = l.loadTestsFromName('no_such_module')
+
+ res = _TextTestResult(
+ stream=_WritelnDecorator(sys.stdout),
+ descriptions=0, verbosity=1)
+ suite(res)
+ print res.errors
+ res.printErrors()
+ assert res.errors, "Expected errors but got none"
+ assert not res.failures, res.failures
+ err = res.errors[0][0].test.exc_class
+ assert err is ImportError, \
+ "Expected import error, got %s" % err
+
+ def test_load_nonsense_name(self):
+ ctx = os.path.join(support, 'ctx')
+ l = loader.TestLoader(workingDir=ctx)
+ suite = l.loadTestsFromName('fred!')
+
+ res = _TextTestResult(
+ stream=_WritelnDecorator(sys.stdout),
+ descriptions=0, verbosity=1)
+ suite(res)
+ print res.errors
+ assert res.errors, "Expected errors but got none"
+ assert not res.failures, res.failures
+
+ def test_generator_with_closure(self):
+ """Test that a generator test can employ a closure
+
+ Issue #3. If the generator binds early, the last value
+ of the closure will be seen for each generated test and
+ the tests will fail.
+ """
+ gen = os.path.join(support, 'gen')
+ l = loader.TestLoader(workingDir=gen)
+ suite = l.loadTestsFromName('test')
+ res = _TextTestResult(
+ stream=_WritelnDecorator(sys.stdout),
+ descriptions=0, verbosity=1)
+ suite(res)
+ assert not res.errors
+ self.assertEqual(res.testsRun, 5)
+
+ def test_issue_269(self):
+ """Test classes that raise exceptions in __init__ do not stop test run
+ """
+ wdir = os.path.join(support, 'issue269')
+ l = loader.TestLoader(workingDir=wdir)
+ suite = l.loadTestsFromName('test_bad_class')
+ res = _TextTestResult(
+ stream=_WritelnDecorator(sys.stdout),
+ descriptions=0, verbosity=1)
+ suite(res)
+ print res.errors
+ self.assertEqual(len(res.errors), 1)
+ assert 'raise Exception("pow")' in res.errors[0][1]
+
+
+# used for comparing lists
+def diff(a, b):
+ return '\n' + '\n'.join([ l for l in ndiff(a, b)
+ if not l.startswith(' ') ])
+
+
+# used for context debugging
+class TreePrintContextSuite(suite.ContextSuite):
+ indent = ''
+
+ def setUp(self):
+ print self, 'setup -->'
+ suite.ContextSuite.setUp(self)
+ TreePrintContextSuite.indent += ' '
+
+ def tearDown(self):
+ TreePrintContextSuite.indent = TreePrintContextSuite.indent[:-2]
+ try:
+ suite.ContextSuite.tearDown(self)
+ finally:
+ print self, 'teardown <--'
+ def __repr__(self):
+
+ return '%s<%s>' % (self.indent,
+ getattr(self.context, '__name__', self.context))
+ __str__ = __repr__
+
+
+if __name__ == '__main__':
+ #import logging
+ #logging.basicConfig() #level=logging.DEBUG)
+ #logging.getLogger('nose.suite').setLevel(logging.DEBUG)
+ unittest.main()
diff --git a/functional_tests/test_loader.pyc b/functional_tests/test_loader.pyc
new file mode 100644
index 0000000..5f4a203
Binary files /dev/null and b/functional_tests/test_loader.pyc differ
diff --git a/functional_tests/test_multiprocessing/__init__.py b/functional_tests/test_multiprocessing/__init__.py
new file mode 100644
index 0000000..2a52efd
--- /dev/null
+++ b/functional_tests/test_multiprocessing/__init__.py
@@ -0,0 +1,28 @@
+import os
+from unittest import TestCase
+
+from nose.plugins import PluginTester
+from nose.plugins.skip import SkipTest
+from nose.plugins.multiprocess import MultiProcess
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+def setup():
+ try:
+ import multiprocessing
+ if 'active' in MultiProcess.status:
+ raise SkipTest("Multiprocess plugin is active. Skipping tests of "
+ "plugin itself.")
+ except ImportError:
+ raise SkipTest("multiprocessing module not available")
+
+class MPTestBase(PluginTester, TestCase):
+ processes = 1
+ activate = '--processes=1'
+ plugins = [MultiProcess()]
+ suitepath = os.path.join(support, 'timeout.py')
+
+ def __init__(self, *args, **kwargs):
+ self.activate = '--processes=%d' % self.processes
+ PluginTester.__init__(self)
+ TestCase.__init__(self, *args, **kwargs)
diff --git a/functional_tests/test_multiprocessing/__init__.pyc b/functional_tests/test_multiprocessing/__init__.pyc
new file mode 100644
index 0000000..3e924ee
Binary files /dev/null and b/functional_tests/test_multiprocessing/__init__.pyc differ
diff --git a/functional_tests/test_multiprocessing/support/class.py b/functional_tests/test_multiprocessing/support/class.py
new file mode 100644
index 0000000..905bcdf
--- /dev/null
+++ b/functional_tests/test_multiprocessing/support/class.py
@@ -0,0 +1,14 @@
+class TestFunctionalTest(object):
+ counter = 0
+ @classmethod
+ def setup_class(cls):
+ cls.counter += 1
+ @classmethod
+ def teardown_class(cls):
+ cls.counter -= 1
+ def _run(self):
+ assert self.counter==1
+ def test1(self):
+ self._run()
+ def test2(self):
+ self._run()
diff --git a/functional_tests/test_multiprocessing/support/class.pyc b/functional_tests/test_multiprocessing/support/class.pyc
new file mode 100644
index 0000000..a58cec4
Binary files /dev/null and b/functional_tests/test_multiprocessing/support/class.pyc differ
diff --git a/functional_tests/test_multiprocessing/support/concurrent_shared/__init__.py b/functional_tests/test_multiprocessing/support/concurrent_shared/__init__.py
new file mode 100644
index 0000000..c557001
--- /dev/null
+++ b/functional_tests/test_multiprocessing/support/concurrent_shared/__init__.py
@@ -0,0 +1,6 @@
+counter=[0]
+_multiprocess_shared_ = True
+def setup_package():
+ counter[0] += 1
+def teardown_package():
+ counter[0] -= 1
diff --git a/functional_tests/test_multiprocessing/support/concurrent_shared/__init__.pyc b/functional_tests/test_multiprocessing/support/concurrent_shared/__init__.pyc
new file mode 100644
index 0000000..9218290
Binary files /dev/null and b/functional_tests/test_multiprocessing/support/concurrent_shared/__init__.pyc differ
diff --git a/functional_tests/test_multiprocessing/support/concurrent_shared/test.py b/functional_tests/test_multiprocessing/support/concurrent_shared/test.py
new file mode 100644
index 0000000..5bc21f6
--- /dev/null
+++ b/functional_tests/test_multiprocessing/support/concurrent_shared/test.py
@@ -0,0 +1,11 @@
+#from . import counter
+from time import sleep
+#_multiprocess_can_split_ = True
+class Test1(object):
+ def test1(self):
+ sleep(1)
+ pass
+class Test2(object):
+ def test2(self):
+ sleep(1)
+ pass
diff --git a/functional_tests/test_multiprocessing/support/concurrent_shared/test.pyc b/functional_tests/test_multiprocessing/support/concurrent_shared/test.pyc
new file mode 100644
index 0000000..eaa9880
Binary files /dev/null and b/functional_tests/test_multiprocessing/support/concurrent_shared/test.pyc differ
diff --git a/functional_tests/test_multiprocessing/support/fake_nosetest.py b/functional_tests/test_multiprocessing/support/fake_nosetest.py
new file mode 100644
index 0000000..f5a6289
--- /dev/null
+++ b/functional_tests/test_multiprocessing/support/fake_nosetest.py
@@ -0,0 +1,14 @@
+import os
+import sys
+
+import nose
+from nose.plugins.multiprocess import MultiProcess
+from nose.config import Config
+from nose.plugins.manager import PluginManager
+
+if __name__ == '__main__':
+ if len(sys.argv) < 3:
+ print "USAGE: %s TEST_FILE LOG_FILE" % sys.argv[0]
+ sys.exit(1)
+ os.environ['NOSE_MP_LOG']=sys.argv[2]
+ nose.main(defaultTest=sys.argv[1], argv=[sys.argv[0],'--processes=1','-v'], config=Config(plugins=PluginManager(plugins=[MultiProcess()])))
diff --git a/functional_tests/test_multiprocessing/support/keyboardinterrupt.py b/functional_tests/test_multiprocessing/support/keyboardinterrupt.py
new file mode 100644
index 0000000..2c36d95
--- /dev/null
+++ b/functional_tests/test_multiprocessing/support/keyboardinterrupt.py
@@ -0,0 +1,29 @@
+import os
+
+from tempfile import mktemp
+from time import sleep
+
+if 'NOSE_MP_LOG' not in os.environ:
+ raise Exception('Environment variable NOSE_MP_LOG is not set')
+
+logfile = os.environ['NOSE_MP_LOG']
+
+def log(w):
+ f = open(logfile, 'a')
+ f.write(w+"\n")
+ f.close()
+#make sure all tests in this file are dispatched to the same subprocess
+def setup():
+ log('setup')
+
+def test_timeout():
+ log('test_timeout')
+ sleep(2)
+ log('test_timeout_finished')
+
+# check timeout will not prevent remaining tests dispatched to the same subprocess to continue to run
+def test_pass():
+ log('test_pass')
+
+def teardown():
+ log('teardown')
diff --git a/functional_tests/test_multiprocessing/support/keyboardinterrupt.pyc b/functional_tests/test_multiprocessing/support/keyboardinterrupt.pyc
new file mode 100644
index 0000000..0c1dd85
Binary files /dev/null and b/functional_tests/test_multiprocessing/support/keyboardinterrupt.pyc differ
diff --git a/functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.py b/functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.py
new file mode 100644
index 0000000..3932bbd
--- /dev/null
+++ b/functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.py
@@ -0,0 +1,34 @@
+import os
+
+from tempfile import mktemp
+from time import sleep
+
+if 'NOSE_MP_LOG' not in os.environ:
+ raise Exception('Environment variable NOSE_MP_LOG is not set')
+
+logfile = os.environ['NOSE_MP_LOG']
+
+def log(w):
+ f = open(logfile, 'a')
+ f.write(w+"\n")
+ f.close()
+#make sure all tests in this file are dispatched to the same subprocess
+def setup():
+ '''global logfile
+ logfile = mktemp()
+ print "tempfile is:",logfile'''
+ log('setup')
+
+def test_timeout():
+ log('test_timeout')
+ sleep(2)
+ log('test_timeout_finished')
+
+# check timeout will not prevent remaining tests dispatched to the same subprocess to continue to run
+def test_pass():
+ log('test_pass')
+
+def teardown():
+ log('teardown')
+ sleep(10)
+ log('teardown_finished')
diff --git a/functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.pyc b/functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.pyc
new file mode 100644
index 0000000..7444e51
Binary files /dev/null and b/functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.pyc differ
diff --git a/functional_tests/test_multiprocessing/support/nameerror.py b/functional_tests/test_multiprocessing/support/nameerror.py
new file mode 100644
index 0000000..20e7bd7
--- /dev/null
+++ b/functional_tests/test_multiprocessing/support/nameerror.py
@@ -0,0 +1,4 @@
+# we purposefully raise a NameError at the top level here
+
+undefined_variable
+
diff --git a/functional_tests/test_multiprocessing/support/nameerror.pyc b/functional_tests/test_multiprocessing/support/nameerror.pyc
new file mode 100644
index 0000000..04a04a9
Binary files /dev/null and b/functional_tests/test_multiprocessing/support/nameerror.pyc differ
diff --git a/functional_tests/test_multiprocessing/support/timeout.py b/functional_tests/test_multiprocessing/support/timeout.py
new file mode 100644
index 0000000..480c859
--- /dev/null
+++ b/functional_tests/test_multiprocessing/support/timeout.py
@@ -0,0 +1,12 @@
+#make sure all tests in this file are dispatched to the same subprocess
+def setup():
+ pass
+
+def test_timeout():
+ "this test *should* fail when process-timeout=1"
+ from time import sleep
+ sleep(2)
+
+# check timeout will not prevent remaining tests dispatched to the same subprocess to continue to run
+def test_pass():
+ pass
diff --git a/functional_tests/test_multiprocessing/support/timeout.pyc b/functional_tests/test_multiprocessing/support/timeout.pyc
new file mode 100644
index 0000000..c53fc3b
Binary files /dev/null and b/functional_tests/test_multiprocessing/support/timeout.pyc differ
diff --git a/functional_tests/test_multiprocessing/test_class.py b/functional_tests/test_multiprocessing/test_class.py
new file mode 100644
index 0000000..d92710d
--- /dev/null
+++ b/functional_tests/test_multiprocessing/test_class.py
@@ -0,0 +1,13 @@
+import os
+
+from test_multiprocessing import MPTestBase
+
+
+#test case for #462
+class TestClassFixture(MPTestBase):
+ suitepath = os.path.join(os.path.dirname(__file__), 'support', 'class.py')
+
+ def runTest(self):
+ assert str(self.output).strip().endswith('OK')
+ assert 'Ran 2 tests' in self.output
+
diff --git a/functional_tests/test_multiprocessing/test_class.pyc b/functional_tests/test_multiprocessing/test_class.pyc
new file mode 100644
index 0000000..652490f
Binary files /dev/null and b/functional_tests/test_multiprocessing/test_class.pyc differ
diff --git a/functional_tests/test_multiprocessing/test_concurrent_shared.py b/functional_tests/test_multiprocessing/test_concurrent_shared.py
new file mode 100644
index 0000000..2552c2b
--- /dev/null
+++ b/functional_tests/test_multiprocessing/test_concurrent_shared.py
@@ -0,0 +1,13 @@
+import os
+
+from test_multiprocessing import MPTestBase
+
+class TestConcurrentShared(MPTestBase):
+ processes = 2
+ suitepath = os.path.join(os.path.dirname(__file__), 'support',
+ 'concurrent_shared')
+
+ def runTest(self):
+ assert 'Ran 2 tests in 1.' in self.output, "make sure two tests use 1.x seconds (no more than 2 seconsd)"
+ assert str(self.output).strip().endswith('OK')
+
diff --git a/functional_tests/test_multiprocessing/test_concurrent_shared.pyc b/functional_tests/test_multiprocessing/test_concurrent_shared.pyc
new file mode 100644
index 0000000..bf83a64
Binary files /dev/null and b/functional_tests/test_multiprocessing/test_concurrent_shared.pyc differ
diff --git a/functional_tests/test_multiprocessing/test_keyboardinterrupt.py b/functional_tests/test_multiprocessing/test_keyboardinterrupt.py
new file mode 100644
index 0000000..8f07e54
--- /dev/null
+++ b/functional_tests/test_multiprocessing/test_keyboardinterrupt.py
@@ -0,0 +1,84 @@
+from subprocess import Popen,PIPE
+import os
+import sys
+from time import sleep
+import signal
+
+import nose
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+PYTHONPATH = os.environ['PYTHONPATH'] if 'PYTHONPATH' in os.environ else ''
+def setup():
+ nose_parent_dir = os.path.normpath(os.path.join(os.path.abspath(os.path.dirname(nose.__file__)),'..'))
+ paths = [nose_parent_dir]
+ if PYTHONPATH:
+ paths.append(PYTHONPATH)
+ os.environ['PYTHONPATH'] = os.pathsep.join(paths)
+def teardown():
+ if PYTHONPATH:
+ os.environ['PYTHONPATH'] = PYTHONPATH
+ else:
+ del os.environ['PYTHONPATH']
+
+runner = os.path.join(support, 'fake_nosetest.py')
+def keyboardinterrupt(case):
+ #os.setsid would create a process group so signals sent to the
+ #parent process will propogates to all children processes
+ from tempfile import mktemp
+ logfile = mktemp()
+ process = Popen([sys.executable,runner,os.path.join(support,case),logfile], preexec_fn=os.setsid, stdout=PIPE, stderr=PIPE, bufsize=-1)
+
+ #wait until logfile is created:
+ retry=100
+ while not os.path.exists(logfile):
+ sleep(0.1)
+ retry -= 1
+ if not retry:
+ raise Exception('Timeout while waiting for log file to be created by fake_nosetest.py')
+
+ os.killpg(process.pid, signal.SIGINT)
+ return process, logfile
+
+def get_log_content(logfile):
+ '''prefix = 'tempfile is: '
+ if not stdout.startswith(prefix):
+ raise Exception('stdout does not contain tmp file name: '+stdout)
+ logfile = stdout[len(prefix):].strip() #remove trailing new line char'''
+ f = open(logfile)
+ content = f.read()
+ f.close()
+ os.remove(logfile)
+ return content
+
+def test_keyboardinterrupt():
+ process, logfile = keyboardinterrupt('keyboardinterrupt.py')
+ stdout, stderr = [s.decode('utf-8') for s in process.communicate(None)]
+ print stderr
+ log = get_log_content(logfile)
+ assert 'setup' in log
+ assert 'test_timeout' in log
+ assert 'test_timeout_finished' not in log
+ assert 'test_pass' not in log
+ assert 'teardown' in log
+ assert 'Ran 0 tests' in stderr
+ assert 'KeyboardInterrupt' in stderr
+ assert 'FAILED (errors=1)' in stderr
+ assert 'ERROR: Worker 0 keyboard interrupt, failing current test '+os.path.join(support,'keyboardinterrupt.py') in stderr
+
+
+def test_keyboardinterrupt_twice():
+ process, logfile = keyboardinterrupt('keyboardinterrupt_twice.py')
+ sleep(0.5)
+ os.killpg(process.pid, signal.SIGINT)
+ stdout, stderr = [s.decode('utf-8') for s in process.communicate(None)]
+ log = get_log_content(logfile)
+ assert 'setup' in log
+ assert 'test_timeout' in log
+ assert 'test_timeout_finished' not in log
+ assert 'test_pass' not in log
+ assert 'teardown' in log
+ assert 'teardown_finished' not in log
+ assert 'Ran 0 tests' in stderr
+ assert 'KeyboardInterrupt' in stderr
+ assert 'FAILED (errors=1)' in stderr
diff --git a/functional_tests/test_multiprocessing/test_keyboardinterrupt.pyc b/functional_tests/test_multiprocessing/test_keyboardinterrupt.pyc
new file mode 100644
index 0000000..a40b2e7
Binary files /dev/null and b/functional_tests/test_multiprocessing/test_keyboardinterrupt.pyc differ
diff --git a/functional_tests/test_multiprocessing/test_nameerror.py b/functional_tests/test_multiprocessing/test_nameerror.py
new file mode 100644
index 0000000..5e58226
--- /dev/null
+++ b/functional_tests/test_multiprocessing/test_nameerror.py
@@ -0,0 +1,13 @@
+import os
+
+from test_multiprocessing import support, MPTestBase
+
+class TestMPNameError(MPTestBase):
+ processes = 2
+ suitepath = os.path.join(os.path.dirname(__file__), 'support', 'nameerror.py')
+
+ def runTest(self):
+ print str(self.output)
+ assert 'NameError' in self.output
+ assert "'undefined_variable' is not defined" in self.output
+
diff --git a/functional_tests/test_multiprocessing/test_nameerror.pyc b/functional_tests/test_multiprocessing/test_nameerror.pyc
new file mode 100644
index 0000000..2d5732b
Binary files /dev/null and b/functional_tests/test_multiprocessing/test_nameerror.pyc differ
diff --git a/functional_tests/test_multiprocessing/test_process_timeout.py b/functional_tests/test_multiprocessing/test_process_timeout.py
new file mode 100644
index 0000000..6b858f8
--- /dev/null
+++ b/functional_tests/test_multiprocessing/test_process_timeout.py
@@ -0,0 +1,21 @@
+import os
+
+from test_multiprocessing import MPTestBase
+
+class TestMPTimeout(MPTestBase):
+ args = ['--process-timeout=1']
+ suitepath = os.path.join(os.path.dirname(__file__), 'support', 'timeout.py')
+
+ def runTest(self):
+ assert "TimedOutException: 'timeout.test_timeout'" in self.output
+ assert "Ran 2 tests in" in self.output
+ assert "FAILED (errors=1)" in self.output
+
+class TestMPTimeoutPass(TestMPTimeout):
+ args = ['--process-timeout=3']
+
+ def runTest(self):
+ assert "TimedOutException: 'timeout.test_timeout'" not in self.output
+ assert "Ran 2 tests in" in self.output
+ assert str(self.output).strip().endswith('OK')
+
diff --git a/functional_tests/test_multiprocessing/test_process_timeout.pyc b/functional_tests/test_multiprocessing/test_process_timeout.pyc
new file mode 100644
index 0000000..30bbf65
Binary files /dev/null and b/functional_tests/test_multiprocessing/test_process_timeout.pyc differ
diff --git a/functional_tests/test_namespace_pkg.py b/functional_tests/test_namespace_pkg.py
new file mode 100644
index 0000000..2db051e
--- /dev/null
+++ b/functional_tests/test_namespace_pkg.py
@@ -0,0 +1,58 @@
+import os
+import sys
+import unittest
+from cStringIO import StringIO
+from nose.core import TestProgram
+from test_program import TestRunner
+
+here = os.path.dirname(__file__)
+support = os.path.join(here, 'support')
+
+class TestNamespacePackages(unittest.TestCase):
+
+ def setUp(self):
+ self.cwd = os.getcwd()
+ self.orig_path = sys.path[:]
+ test_dir = os.path.join(support, 'namespace_pkg')
+ os.chdir(test_dir)
+ sys.path.append(os.path.join(test_dir, 'site-packages'))
+
+ def tearDown(self):
+ sys.path = self.orig_path
+ os.chdir(self.cwd)
+
+ def test_namespace_pkg(self):
+ """Ensure namespace packages work/can import from each other"""
+ stream = StringIO()
+ runner = TestRunner(stream=stream)
+ runner.verbosity = 2
+ prog = TestProgram(argv=[''],
+ testRunner=runner,
+ exit=False)
+ res = runner.result
+ self.assertEqual(res.testsRun, 1,
+ "Expected to run 1 test, ran %s" % res.testsRun)
+ assert res.wasSuccessful()
+ assert not res.errors
+ assert not res.failures
+
+ def test_traverse_namespace(self):
+ """Ensure the --traverse-namespace option tests the other
+ namespace package sibling also.
+ """
+ stream = StringIO()
+ runner = TestRunner(stream=stream)
+ runner.verbosity = 2
+ prog = TestProgram(argv=['', '--traverse-namespace'],
+ testRunner=runner,
+ exit=False)
+ res = runner.result
+ self.assertEqual(res.testsRun, 2,
+ "Expected to run 2 tests, ran %s" % res.testsRun)
+ assert res.wasSuccessful()
+ assert not res.errors
+ assert not res.failures
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_namespace_pkg.pyc b/functional_tests/test_namespace_pkg.pyc
new file mode 100644
index 0000000..bf7634b
Binary files /dev/null and b/functional_tests/test_namespace_pkg.pyc differ
diff --git a/functional_tests/test_plugin_api.py b/functional_tests/test_plugin_api.py
new file mode 100644
index 0000000..c508ded
--- /dev/null
+++ b/functional_tests/test_plugin_api.py
@@ -0,0 +1,45 @@
+"""
+Functional tests of plugin apis -- individual plugintester runs for
+test plugins that implement one or more hooks for testing.
+"""
+import os
+import sys
+import unittest
+from nose.plugins import Plugin, PluginTester
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+class AllFail(Plugin):
+ def prepareTestCase(self, test):
+ self.test = test
+ return self.fail
+
+ def fail(self, result):
+ result.startTest(self.test)
+ try:
+ try:
+ assert False, "I want to fail!"
+ except:
+ result.addFailure(self.test, sys.exc_info())
+ finally:
+ result.stopTest(self.test)
+
+class TestPrepareTestCase_MakeAllFail(PluginTester, unittest.TestCase):
+ activate = '--with-allfail'
+ args = ['-v']
+ plugins = [AllFail()]
+ suitepath = os.path.join(support, 'package2')
+
+ def runTest(self):
+ print "x" * 70
+ print str(self.output)
+ print "x" * 70
+ for line in self.output:
+ if line.startswith('test_pak'):
+ assert line.strip().endswith('FAIL'), \
+ "Expected failure but got: %s" % line.strip()
+ assert not str(self.output).strip().endswith('OK')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_plugin_api.pyc b/functional_tests/test_plugin_api.pyc
new file mode 100644
index 0000000..a790585
Binary files /dev/null and b/functional_tests/test_plugin_api.pyc differ
diff --git a/functional_tests/test_plugins.py b/functional_tests/test_plugins.py
new file mode 100644
index 0000000..eff6c7a
--- /dev/null
+++ b/functional_tests/test_plugins.py
@@ -0,0 +1,71 @@
+import os
+import sys
+import unittest
+from nose.config import Config
+from nose.core import TestProgram
+
+here = os.path.abspath(os.path.dirname(__file__))
+support = os.path.join(here, 'support')
+units = os.path.normpath(os.path.join(here, '..', 'unit_tests'))
+
+if units not in sys.path:
+ sys.path.insert(0, units)
+from mock import RecordingPluginManager
+
+
+class TestPluginCalls(unittest.TestCase):
+ """
+ Tests how plugins are called throughout a standard test run
+ """
+ def test_plugin_calls_package1(self):
+ wdir = os.path.join(support, 'package1')
+ man = RecordingPluginManager()
+ conf = Config(plugins=man, stream=sys.stdout)
+ t = TestProgram(defaultTest=wdir, config=conf,
+ argv=['test_plugin_calls_package1'], exit=False)
+ print man.calls()
+ assert man.called
+
+ self.assertEqual(
+ man.calls(),
+ ['loadPlugins', 'addOptions', 'configure', 'begin',
+ 'prepareTestLoader', 'loadTestsFromNames', 'loadTestsFromName',
+ 'prepareTestRunner', 'prepareTest', 'setOutputStream',
+ 'prepareTestResult', 'beforeDirectory', 'wantFile',
+ 'wantDirectory', 'beforeContext', 'beforeImport',
+ 'afterImport', 'wantModule', 'wantClass', 'wantFunction',
+ 'makeTest', 'wantMethod', 'loadTestsFromTestClass',
+ 'loadTestsFromTestCase', 'loadTestsFromModule', 'startContext',
+ 'beforeTest', 'prepareTestCase', 'startTest', 'addSuccess',
+ 'stopTest', 'afterTest', 'stopContext', 'afterContext',
+ 'loadTestsFromDir', 'afterDirectory',
+ 'report', 'finalize'])
+
+ def test_plugin_calls_package1_verbose(self):
+ wdir = os.path.join(support, 'package1')
+ man = RecordingPluginManager()
+ conf = Config(plugins=man, stream=sys.stdout)
+ t = TestProgram(defaultTest=wdir, config=conf,
+ argv=['test_plugin_calls_package1', '-v'], exit=False)
+ print man.calls()
+ assert man.called
+
+ self.assertEqual(
+ man.calls(),
+ ['loadPlugins', 'addOptions', 'configure', 'begin',
+ 'prepareTestLoader', 'loadTestsFromNames', 'loadTestsFromName',
+ 'prepareTestRunner', 'prepareTest', 'setOutputStream',
+ 'prepareTestResult', 'beforeDirectory', 'wantFile',
+ 'wantDirectory', 'beforeContext', 'beforeImport',
+ 'afterImport', 'wantModule', 'wantClass', 'wantFunction',
+ 'makeTest', 'wantMethod', 'loadTestsFromTestClass',
+ 'loadTestsFromTestCase', 'loadTestsFromModule', 'startContext',
+ 'beforeTest', 'prepareTestCase', 'startTest', 'describeTest',
+ 'testName', 'addSuccess', 'stopTest', 'afterTest', 'stopContext',
+ 'afterContext', 'loadTestsFromDir', 'afterDirectory',
+ 'report', 'finalize'])
+
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_plugins.pyc b/functional_tests/test_plugins.pyc
new file mode 100644
index 0000000..edd721e
Binary files /dev/null and b/functional_tests/test_plugins.pyc differ
diff --git a/functional_tests/test_plugintest.py b/functional_tests/test_plugintest.py
new file mode 100644
index 0000000..7d1a65b
--- /dev/null
+++ b/functional_tests/test_plugintest.py
@@ -0,0 +1,51 @@
+
+import unittest, os
+from nose.plugins import PluginTester, Plugin
+from nose.tools import eq_
+from cStringIO import StringIO
+
+class StubPlugin(Plugin):
+ def options(self, parser, env=os.environ):
+ super(StubPlugin, self).options(parser, env=env)
+ def configure(self, options, conf):
+ pass
+
+class SomePluginTestCase(PluginTester):
+ activate = None # set this to --with-yourplugin, etc
+ plugins = [] # list of plugin instances
+
+ def makeSuite(self):
+ class SomeTest(unittest.TestCase):
+ def runTest(self):
+ raise ValueError("Now do something, plugin!")
+ return unittest.TestSuite([SomeTest()])
+
+class TestPluginTester(unittest.TestCase):
+ def _runPluginTest(self, test_case):
+ loader = unittest.TestLoader()
+ suite = loader.loadTestsFromTestCase(test_case)
+ res = unittest.TestResult()
+ suite(res)
+ return res
+
+ def testPluginTesterExecsPlugin(self):
+ called = []
+ class MockExecPlugin(StubPlugin):
+ def configure(self, options, conf):
+ called.append('configure')
+
+ class MockExecTestCase(SomePluginTestCase, unittest.TestCase):
+ activate = '--with-mockexec'
+ plugins = [MockExecPlugin()]
+
+ def test_something_anything(self):
+ # here is where the test case would test
+ # that the plugin interacted with stub tests
+ pass
+
+ res = self._runPluginTest(MockExecTestCase)
+ eq_(res.testsRun, 1)
+ eq_(called[0], 'configure')
+
+if __name__ == '__main__':
+ unittest.main()
\ No newline at end of file
diff --git a/functional_tests/test_plugintest.pyc b/functional_tests/test_plugintest.pyc
new file mode 100644
index 0000000..0cd6400
Binary files /dev/null and b/functional_tests/test_plugintest.pyc differ
diff --git a/functional_tests/test_program.py b/functional_tests/test_program.py
new file mode 100644
index 0000000..bb63818
--- /dev/null
+++ b/functional_tests/test_program.py
@@ -0,0 +1,189 @@
+import os
+import unittest
+from cStringIO import StringIO
+from nose import SkipTest
+from nose.core import TestProgram
+from nose.config import Config
+from nose.plugins.manager import DefaultPluginManager
+from nose.result import _TextTestResult
+
+here = os.path.dirname(__file__)
+support = os.path.join(here, 'support')
+
+class TestRunner(unittest.TextTestRunner):
+ def _makeResult(self):
+ self.result = _TextTestResult(
+ self.stream, self.descriptions, self.verbosity)
+ return self.result
+
+# Note that all of these tests use a set config to avoid the loading
+# of plugins or settings from .noserc.
+
+class TestTestProgram(unittest.TestCase):
+
+ def test_run_support_ctx(self):
+ """Collect and run tests in functional_tests/support/ctx
+
+ This should collect no tests in the default configuration, since
+ none of the modules have test-like names.
+ """
+ stream = StringIO()
+ runner = TestRunner(stream=stream)
+ prog = TestProgram(defaultTest=os.path.join(support, 'ctx'),
+ argv=['test_run_support_ctx'],
+ testRunner=runner,
+ config=Config(),
+ exit=False)
+ res = runner.result
+ print stream.getvalue()
+ self.assertEqual(res.testsRun, 0,
+ "Expected to run 0 tests, ran %s" % res.testsRun)
+ assert res.wasSuccessful()
+ assert not res.errors
+ assert not res.failures
+
+ def test_run_support_package2(self):
+ """Collect and run tests in functional_tests/support/package2
+
+ This should collect and run 5 tests.
+ """
+ stream = StringIO()
+ runner = TestRunner(stream=stream)
+ prog = TestProgram(defaultTest=os.path.join(support, 'package2'),
+ argv=['test_run_support_package2', '-v'],
+ testRunner=runner,
+ config=Config(),
+ exit=False)
+ res = runner.result
+ print stream.getvalue()
+ self.assertEqual(res.testsRun, 5,
+ "Expected to run 5 tests, ran %s" % res.testsRun)
+ assert res.wasSuccessful()
+ assert not res.errors
+ assert not res.failures
+
+ def test_run_support_package3(self):
+ """Collect and run tests in functional_tests/support/package3
+
+ This should collect and run 2 test. The package layout is:
+
+ lib/
+ a.py
+ src/
+ b.py
+ tests/
+ test_a.py
+ test_b.py
+ """
+ stream = StringIO()
+ runner = TestRunner(stream=stream)
+
+ prog = TestProgram(defaultTest=os.path.join(support, 'package3'),
+ argv=['test_run_support_package3', '-v'],
+ testRunner=runner,
+ config=Config(),
+ exit=False)
+ res = runner.result
+ print stream.getvalue()
+ self.assertEqual(res.testsRun, 2,
+ "Expected to run 2 tests, ran %s" % res.testsRun)
+ assert res.wasSuccessful()
+ assert not res.errors
+ assert not res.failures
+
+ def test_run_support_twist(self):
+ """Collect and run tests in functional/support/twist
+
+ This should collect and run 4 tests with 2 fails and an error.
+ """
+ try:
+ from twisted.trial.unittest import TestCase
+ except ImportError:
+ raise SkipTest('twisted not available; skipping')
+ stream = StringIO()
+ runner = TestRunner(stream=stream, verbosity=2)
+
+ prog = TestProgram(defaultTest=os.path.join(support, 'twist'),
+ argv=['test_run_support_twist'],
+ testRunner=runner,
+ config=Config(stream=stream),
+ exit=False)
+ res = runner.result
+ print stream.getvalue()
+
+ # some versions of twisted.trial.unittest.TestCase have
+ # runTest in the base class -- this is wrong! But we have
+ # to deal with it
+ if hasattr(TestCase, 'runTest'):
+ expect = 5
+ else:
+ expect = 4
+ self.assertEqual(res.testsRun, expect,
+ "Expected to run %s tests, ran %s" %
+ (expect, res.testsRun))
+ assert not res.wasSuccessful()
+ assert len(res.errors) == 1
+ assert len(res.failures) == 2
+
+ def test_issue_130(self):
+ """Collect and run tests in support/issue130 without error.
+
+ This tests that the result and error classes can handle string
+ exceptions.
+ """
+ import warnings
+ warnings.filterwarnings('ignore', category=DeprecationWarning,
+ module='test')
+
+ stream = StringIO()
+ runner = TestRunner(stream=stream, verbosity=2)
+
+ prog = TestProgram(defaultTest=os.path.join(support, 'issue130'),
+ argv=['test_issue_130'],
+ testRunner=runner,
+ config=Config(stream=stream,
+ plugins=DefaultPluginManager()),
+ exit=False)
+ res = runner.result
+ print stream.getvalue()
+ self.assertEqual(res.testsRun, 0) # error is in setup
+ assert not res.wasSuccessful()
+ assert res.errors
+ assert not res.failures
+
+ def test_defaultTest_list(self):
+ stream = StringIO()
+ runner = TestRunner(stream=stream, verbosity=2)
+ tests = [os.path.join(support, 'package2'),
+ os.path.join(support, 'package3')]
+ prog = TestProgram(defaultTest=tests,
+ argv=['test_run_support_package2_3', '-v'],
+ testRunner=runner,
+ config=Config(),
+ exit=False)
+ res = runner.result
+ print stream.getvalue()
+ self.assertEqual(res.testsRun, 7)
+
+ def test_illegal_packages_not_selected(self):
+ stream = StringIO()
+ runner = TestRunner(stream=stream, verbosity=2)
+
+ prog = TestProgram(defaultTest=os.path.join(support, 'issue143'),
+ argv=['test_issue_143'],
+ testRunner=runner,
+ config=Config(stream=stream,
+ plugins=DefaultPluginManager()),
+ exit=False)
+ res = runner.result
+ print stream.getvalue()
+ self.assertEqual(res.testsRun, 0)
+ assert res.wasSuccessful()
+ assert not res.errors
+ assert not res.failures
+
+
+if __name__ == '__main__':
+ #import logging
+ #logging.basicConfig(level=logging.DEBUG)
+ unittest.main()
diff --git a/functional_tests/test_program.pyc b/functional_tests/test_program.pyc
new file mode 100644
index 0000000..dafa056
Binary files /dev/null and b/functional_tests/test_program.pyc differ
diff --git a/functional_tests/test_result.py b/functional_tests/test_result.py
new file mode 100644
index 0000000..7206020
--- /dev/null
+++ b/functional_tests/test_result.py
@@ -0,0 +1,32 @@
+import os
+import sys
+import unittest
+from cStringIO import StringIO
+from nose.config import Config
+from nose.core import TestProgram
+from nose.plugins.manager import PluginManager
+
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+class TestResultSummary(unittest.TestCase):
+
+ def test_with_todo_plugin(self):
+ pkpath = os.path.join(support, 'todo')
+ sys.path.insert(0, pkpath)
+ from todoplug import TodoPlugin
+
+ stream = StringIO()
+ config = Config(stream=stream,
+ plugins=PluginManager([TodoPlugin()]))
+
+ TestProgram(argv=['t', '--with-todo', pkpath],
+ config=config, exit=False)
+ out = stream.getvalue()
+ print out
+ self.assert_('FAILED (TODO=1)' in out)
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/functional_tests/test_result.pyc b/functional_tests/test_result.pyc
new file mode 100644
index 0000000..c8d8810
Binary files /dev/null and b/functional_tests/test_result.pyc differ
diff --git a/functional_tests/test_selector.py b/functional_tests/test_selector.py
new file mode 100644
index 0000000..6282ac4
--- /dev/null
+++ b/functional_tests/test_selector.py
@@ -0,0 +1,17 @@
+import os
+import unittest
+from nose.selector import Selector, TestAddress
+
+support = os.path.abspath(os.path.join(os.path.dirname(__file__), 'support'))
+
+class TestTestAddress(unittest.TestCase):
+
+ def test_module_filename(self):
+ wd = os.path.join(support, 'package2')
+ addr = TestAddress('test_pak.test_mod', workingDir=wd)
+ self.assertEqual(addr.filename,
+ os.path.join(wd, 'test_pak', 'test_mod.py'))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_selector.pyc b/functional_tests/test_selector.pyc
new file mode 100644
index 0000000..03b8f54
Binary files /dev/null and b/functional_tests/test_selector.pyc differ
diff --git a/functional_tests/test_skip_pdb_interaction.py b/functional_tests/test_skip_pdb_interaction.py
new file mode 100644
index 0000000..20c5f78
--- /dev/null
+++ b/functional_tests/test_skip_pdb_interaction.py
@@ -0,0 +1,49 @@
+import unittest
+from nose import case
+from nose.config import Config
+from nose.plugins import debug
+from nose.plugins.manager import PluginManager
+from nose.plugins.skip import Skip, SkipTest
+from nose.proxy import ResultProxyFactory
+
+
+class StubPdb:
+ called = False
+ def post_mortem(self, tb):
+ self.called = True
+
+class TestSkipPdbInteraction(unittest.TestCase):
+ """Tests interaction between skip plugin and pdb plugin -- pdb should
+ not fire on a skip error
+ """
+ def setUp(self):
+ self._pdb = debug.pdb
+ debug.pdb = StubPdb()
+
+ def tearDown(self):
+ debug.pdb = self._pdb
+
+ def test_skip_prevents_pdb_call(self):
+
+ class TC(unittest.TestCase):
+ def test(self):
+ raise SkipTest('not me')
+
+ skip = Skip()
+ skip.enabled = True
+ p = debug.Pdb()
+ p.enabled = True
+ p.enabled_for_errors = True
+ res = unittest.TestResult()
+ conf = Config(plugins=PluginManager(plugins=[skip, p]))
+ rpf = ResultProxyFactory(conf)
+ test = case.Test(TC('test'), resultProxy=rpf)
+ test(res)
+
+ assert not res.errors, "Skip was recorded as error %s" % res.errors
+ assert not debug.pdb.called, "pdb was called"
+
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_skip_pdb_interaction.pyc b/functional_tests/test_skip_pdb_interaction.pyc
new file mode 100644
index 0000000..e53d79b
Binary files /dev/null and b/functional_tests/test_skip_pdb_interaction.pyc differ
diff --git a/functional_tests/test_success.py b/functional_tests/test_success.py
new file mode 100644
index 0000000..760a7d1
--- /dev/null
+++ b/functional_tests/test_success.py
@@ -0,0 +1,43 @@
+import os
+import unittest
+from nose.plugins.plugintest import PluginTester, remove_timings
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+
+
+class TestSingleTestPass(PluginTester, unittest.TestCase):
+ activate = '-v'
+ plugins = []
+ suitepath = os.path.join(support, 'pass')
+
+ def test_single_test_pass(self):
+ # note that this doesn't use nose.plugins.doctests.run, in order that
+ # this test fails if the final terminating newline is not present (it
+ # could still be written as a doctest -- PluginTester was just closer
+ # to hand)
+ print self.output
+ output = remove_timings(str(self.output))
+ assert output == """\
+test.test ... ok
+
+----------------------------------------------------------------------
+Ran 1 test in ...s
+
+OK
+"""
+
+class TestZeroTestsPass(PluginTester, unittest.TestCase):
+ activate = '-v'
+ plugins = []
+ suitepath = os.path.join(support, 'empty')
+
+ def test_zero_tests_pass(self):
+ print self.output
+ output = remove_timings(str(self.output))
+ assert output == """\
+
+----------------------------------------------------------------------
+Ran 0 tests in ...s
+
+OK
+"""
diff --git a/functional_tests/test_success.pyc b/functional_tests/test_success.pyc
new file mode 100644
index 0000000..cbc564d
Binary files /dev/null and b/functional_tests/test_success.pyc differ
diff --git a/functional_tests/test_suite.py b/functional_tests/test_suite.py
new file mode 100644
index 0000000..a411469
--- /dev/null
+++ b/functional_tests/test_suite.py
@@ -0,0 +1,47 @@
+import os
+import sys
+import unittest
+from nose import case
+from nose.suite import ContextSuiteFactory
+
+support = os.path.abspath(os.path.join(os.path.dirname(__file__), 'support'))
+
+class TestContextSuiteFactory(unittest.TestCase):
+
+ def setUp(self):
+ self._mods = sys.modules.copy()
+ self._path = sys.path[:]
+ sys.path.insert(0, os.path.join(support, 'package2'))
+
+ def tearDown(self):
+ to_del = [ m for m in sys.modules.keys() if
+ m not in self._mods ]
+ if to_del:
+ for mod in to_del:
+ del sys.modules[mod]
+ sys.modules.update(self._mods)
+ sys.path = self._path
+
+ def test_find_context(self):
+ from test_pak import test_mod
+
+ factory = ContextSuiteFactory()
+ tests = [case.FunctionTestCase(test_mod.test_add),
+ case.FunctionTestCase(test_mod.test_minus)]
+ suite = factory(tests)
+ self.assertEqual(suite.context, test_mod)
+
+ def test_ancestry(self):
+ from test_pak.test_sub.test_mod import TestMaths
+ from test_pak.test_sub import test_mod
+ from test_pak import test_sub
+ import test_pak
+
+ factory = ContextSuiteFactory()
+ ancestry = [l for l in factory.ancestry(TestMaths)]
+ self.assertEqual(ancestry,
+ [test_mod, test_sub, test_pak])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/functional_tests/test_suite.pyc b/functional_tests/test_suite.pyc
new file mode 100644
index 0000000..3e5af98
Binary files /dev/null and b/functional_tests/test_suite.pyc differ
diff --git a/functional_tests/test_withid_failures.rst b/functional_tests/test_withid_failures.rst
new file mode 100644
index 0000000..5a371b7
--- /dev/null
+++ b/functional_tests/test_withid_failures.rst
@@ -0,0 +1,50 @@
+ >>> import os
+ >>> import sys
+ >>> from nose.plugins.plugintest import run_buffered as run
+ >>> from nose.plugins.testid import TestId
+ >>> import tempfile
+ >>> idfile = tempfile.mktemp()
+ >>> support = os.path.join(os.path.dirname(__file__), 'support', 'id_fails')
+ >>> argv = [__file__, '-v', '--with-id', '--id-file', idfile, support]
+ >>> run(argv=argv, plugins=[TestId()])
+ #1 Failure: ImportError (No module named apackagethatdoesntexist) ... ERROR
+ #2 test_b.test ... ok
+ #3 test_b.test_fail ... FAIL
+
+ ======================================================================
+ ERROR: Failure: ImportError (No module named apackagethatdoesntexist)
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ ImportError: No module named apackagethatdoesntexist
+
+ ======================================================================
+ FAIL: test_b.test_fail
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ AssertionError
+
+ ----------------------------------------------------------------------
+ Ran 3 tests in ...s
+
+ FAILED (errors=1, failures=1)
+
+Addressing failures works (sometimes).
+
+ >>> argv.append('1')
+ >>> _junk = sys.modules.pop('test_a', None) # 2.3 requires
+ >>> run(argv=argv, plugins=[TestId()])
+ #1 Failure: ImportError (No module named apackagethatdoesntexist) ... ERROR
+
+ ======================================================================
+ ERROR: Failure: ImportError (No module named apackagethatdoesntexist)
+ ----------------------------------------------------------------------
+ Traceback (most recent call last):
+ ...
+ ImportError: No module named apackagethatdoesntexist
+
+ ----------------------------------------------------------------------
+ Ran 1 test in ...s
+
+ FAILED (errors=1)
diff --git a/functional_tests/test_xunit.py b/functional_tests/test_xunit.py
new file mode 100644
index 0000000..5d21a17
--- /dev/null
+++ b/functional_tests/test_xunit.py
@@ -0,0 +1,61 @@
+# -*- coding: utf-8 -*-
+import codecs
+import os
+import sys
+import unittest
+from nose.plugins.xunit import Xunit
+from nose.plugins.skip import Skip
+from nose.plugins import PluginTester
+
+support = os.path.join(os.path.dirname(__file__), 'support')
+xml_results_filename = os.path.join(support, "xunit.xml")
+
+# the plugin is tested better in unit tests.
+# this is just here for a sanity check
+
+class TestXUnitPlugin(PluginTester, unittest.TestCase):
+ activate = '--with-xunit'
+ args = ['-v','--xunit-file=%s' % xml_results_filename]
+ plugins = [Xunit(), Skip()]
+ suitepath = os.path.join(support, 'xunit')
+
+ def runTest(self):
+ print str(self.output)
+
+ assert "ERROR: test_error" in self.output
+ assert "FAIL: test_fail" in self.output
+ assert "test_skip (test_xunit_as_suite.TestForXunit) ... SKIP: skipit" in self.output
+ assert "XML: %s" % xml_results_filename in self.output
+
+ f = codecs.open(xml_results_filename,'r', encoding='utf8')
+ result = f.read()
+ f.close()
+ print result.encode('utf8', 'replace')
+
+ assert '' in result
+ assert '' in result
+ assert '' % (Exception.__module__,)) in result
+ else:
+ assert ('' % (Exception.__module__,)).decode('utf8') in result
+ assert '' in result
+ assert '' in result
+
+
+class TestIssue279(PluginTester, unittest.TestCase):
+ activate = '--with-xunit'
+ args = ['-v','--xunit-file=%s' % xml_results_filename]
+ plugins = [Xunit(), Skip()]
+ suitepath = os.path.join(support, 'issue279')
+
+ def runTest(self):
+ print str(self.output)
+ f = open(xml_results_filename,'r')
+ result = f.read()
+ f.close()
+ print result
+ assert 'tests="1" errors="1" failures="0" skip="0"' in result
+ assert "Exception: I would prefer not to" in result
diff --git a/functional_tests/test_xunit.pyc b/functional_tests/test_xunit.pyc
new file mode 100644
index 0000000..15c1a36
Binary files /dev/null and b/functional_tests/test_xunit.pyc differ
diff --git a/install-rpm.sh b/install-rpm.sh
new file mode 100755
index 0000000..68f7f01
--- /dev/null
+++ b/install-rpm.sh
@@ -0,0 +1,3 @@
+python setup.py install --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
+# 'brp-compress' gzips the man pages without distutils knowing... fix this
+sed -i -e 's@man/man\([[:digit:]]\)/\(.\+\.[[:digit:]]\)$@man/man\1/\2.gz@g' INSTALLED_FILES
diff --git a/lgpl.txt b/lgpl.txt
new file mode 100644
index 0000000..8add30a
--- /dev/null
+++ b/lgpl.txt
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ , 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/nose.egg-info/PKG-INFO b/nose.egg-info/PKG-INFO
new file mode 100644
index 0000000..0ad5792
--- /dev/null
+++ b/nose.egg-info/PKG-INFO
@@ -0,0 +1,38 @@
+Metadata-Version: 1.1
+Name: nose
+Version: 1.2.1
+Summary: nose extends unittest to make testing easier
+Home-page: http://readthedocs.org/docs/nose/
+Author: Jason Pellerin
+Author-email: jpellerin+nose@gmail.com
+License: GNU LGPL
+Description: nose extends the test loading and running features of unittest, making
+ it easier to write, find and run tests.
+
+ By default, nose will run tests in files or directories under the current
+ working directory whose names include "test" or "Test" at a word boundary
+ (like "test_this" or "functional_test" or "TestClass" but not
+ "libtest"). Test output is similar to that of unittest, but also includes
+ captured stdout output from failing tests, for easy print-style debugging.
+
+ These features, and many more, are customizable through the use of
+ plugins. Plugins included with nose provide support for doctest, code
+ coverage and profiling, flexible attribute-based test selection,
+ output capture and more. More information about writing plugins may be
+ found on in the nose API documentation, here:
+ http://readthedocs.org/docs/nose/
+
+ If you have recently reported a bug marked as fixed, or have a craving for
+ the very latest, you may want the development version instead:
+ https://github.com/nose-devs/nose/tarball/master#egg=nose-dev
+
+Keywords: test unittest doctest automatic discovery
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
+Classifier: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Topic :: Software Development :: Testing
diff --git a/nose.egg-info/SOURCES.txt b/nose.egg-info/SOURCES.txt
new file mode 100644
index 0000000..28e5f5a
--- /dev/null
+++ b/nose.egg-info/SOURCES.txt
@@ -0,0 +1,608 @@
+AUTHORS
+CHANGELOG
+MANIFEST.in
+NEWS
+README.txt
+distribute_setup.py
+install-rpm.sh
+lgpl.txt
+nosetests.1
+patch.py
+selftest.py
+setup.cfg
+setup.py
+setup3lib.py
+bin/nosetests
+doc/Makefile
+doc/api.rst
+doc/conf.py
+doc/contributing.rst
+doc/developing.rst
+doc/docstring.py
+doc/finding_tests.rst
+doc/further_reading.rst
+doc/index.html
+doc/index.rst
+doc/man.rst
+doc/manbuilder.py
+doc/manbuilder.pyc
+doc/manpage.py
+doc/manpage.pyc
+doc/more_info.rst
+doc/news.rst
+doc/plugins.rst
+doc/rtd-requirements.txt
+doc/setuptools_integration.rst
+doc/testing.rst
+doc/testing_tools.rst
+doc/usage.rst
+doc/writing_tests.rst
+doc/.static/nose.css
+doc/.templates/index.html
+doc/.templates/indexsidebar.html
+doc/.templates/layout.html
+doc/.templates/page.html
+doc/api/commands.rst
+doc/api/config.rst
+doc/api/core.rst
+doc/api/importer.rst
+doc/api/inspector.rst
+doc/api/loader.rst
+doc/api/plugin_manager.rst
+doc/api/proxy.rst
+doc/api/result.rst
+doc/api/selector.rst
+doc/api/suite.rst
+doc/api/test_cases.rst
+doc/api/twistedtools.rst
+doc/api/util.rst
+doc/plugins/allmodules.rst
+doc/plugins/attrib.rst
+doc/plugins/builtin.rst
+doc/plugins/capture.rst
+doc/plugins/collect.rst
+doc/plugins/cover.rst
+doc/plugins/debug.rst
+doc/plugins/deprecated.rst
+doc/plugins/doctests.rst
+doc/plugins/documenting.rst
+doc/plugins/errorclasses.rst
+doc/plugins/failuredetail.rst
+doc/plugins/interface.rst
+doc/plugins/isolate.rst
+doc/plugins/logcapture.rst
+doc/plugins/multiprocess.rst
+doc/plugins/other.rst
+doc/plugins/prof.rst
+doc/plugins/skip.rst
+doc/plugins/testid.rst
+doc/plugins/testing.rst
+doc/plugins/writing.rst
+doc/plugins/xunit.rst
+examples/attrib_plugin.py
+examples/html_plugin/htmlplug.py
+examples/html_plugin/setup.py
+examples/plugin/plug.py
+examples/plugin/setup.py
+functional_tests/test_attribute_plugin.py
+functional_tests/test_attribute_plugin.pyc
+functional_tests/test_buggy_generators.py
+functional_tests/test_buggy_generators.pyc
+functional_tests/test_cases.py
+functional_tests/test_cases.pyc
+functional_tests/test_collector.py
+functional_tests/test_collector.pyc
+functional_tests/test_commands.py
+functional_tests/test_commands.pyc
+functional_tests/test_config_files.py
+functional_tests/test_config_files.pyc
+functional_tests/test_coverage_plugin.py
+functional_tests/test_coverage_plugin.pyc
+functional_tests/test_defaultpluginmanager.py
+functional_tests/test_defaultpluginmanager.pyc
+functional_tests/test_doctest_plugin.py
+functional_tests/test_doctest_plugin.pyc
+functional_tests/test_entrypoints.py
+functional_tests/test_entrypoints.pyc
+functional_tests/test_failuredetail_plugin.py
+functional_tests/test_failuredetail_plugin.pyc
+functional_tests/test_generator_fixtures.py
+functional_tests/test_generator_fixtures.pyc
+functional_tests/test_id_plugin.py
+functional_tests/test_id_plugin.pyc
+functional_tests/test_importer.py
+functional_tests/test_importer.pyc
+functional_tests/test_isolate_plugin.py
+functional_tests/test_isolate_plugin.pyc
+functional_tests/test_issue_072.py
+functional_tests/test_issue_072.pyc
+functional_tests/test_issue_082.py
+functional_tests/test_issue_082.pyc
+functional_tests/test_issue_408.py
+functional_tests/test_issue_408.pyc
+functional_tests/test_load_tests_from_test_case.py
+functional_tests/test_load_tests_from_test_case.pyc
+functional_tests/test_loader.py
+functional_tests/test_loader.pyc
+functional_tests/test_namespace_pkg.py
+functional_tests/test_namespace_pkg.pyc
+functional_tests/test_plugin_api.py
+functional_tests/test_plugin_api.pyc
+functional_tests/test_plugins.py
+functional_tests/test_plugins.pyc
+functional_tests/test_plugintest.py
+functional_tests/test_plugintest.pyc
+functional_tests/test_program.py
+functional_tests/test_program.pyc
+functional_tests/test_result.py
+functional_tests/test_result.pyc
+functional_tests/test_selector.py
+functional_tests/test_selector.pyc
+functional_tests/test_skip_pdb_interaction.py
+functional_tests/test_skip_pdb_interaction.pyc
+functional_tests/test_success.py
+functional_tests/test_success.pyc
+functional_tests/test_suite.py
+functional_tests/test_suite.pyc
+functional_tests/test_withid_failures.rst
+functional_tests/test_xunit.py
+functional_tests/test_xunit.pyc
+functional_tests/doc_tests/test_addplugins/test_addplugins.rst
+functional_tests/doc_tests/test_addplugins/support/test.py
+functional_tests/doc_tests/test_addplugins/support/test.pyc
+functional_tests/doc_tests/test_allmodules/test_allmodules.rst
+functional_tests/doc_tests/test_allmodules/support/mod.py
+functional_tests/doc_tests/test_allmodules/support/mod.pyc
+functional_tests/doc_tests/test_allmodules/support/test.py
+functional_tests/doc_tests/test_allmodules/support/test.pyc
+functional_tests/doc_tests/test_coverage_html/coverage_html_fixtures.pyc
+functional_tests/doc_tests/test_coverage_html/support/blah.pyc
+functional_tests/doc_tests/test_coverage_html/support/tests/test_covered.pyc
+functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures.rst
+functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures_fixtures.py
+functional_tests/doc_tests/test_doctest_fixtures/doctest_fixtures_fixtures.pyc
+functional_tests/doc_tests/test_init_plugin/example.cfg
+functional_tests/doc_tests/test_init_plugin/init_plugin.rst
+functional_tests/doc_tests/test_init_plugin/init_plugin.rst.py3.patch
+functional_tests/doc_tests/test_issue089/unwanted_package.rst
+functional_tests/doc_tests/test_issue089/support/unwanted_package/__init__.py
+functional_tests/doc_tests/test_issue089/support/unwanted_package/__init__.pyc
+functional_tests/doc_tests/test_issue089/support/unwanted_package/test_spam.py
+functional_tests/doc_tests/test_issue089/support/unwanted_package/test_spam.pyc
+functional_tests/doc_tests/test_issue089/support/wanted_package/__init__.py
+functional_tests/doc_tests/test_issue089/support/wanted_package/__init__.pyc
+functional_tests/doc_tests/test_issue089/support/wanted_package/test_eggs.py
+functional_tests/doc_tests/test_issue089/support/wanted_package/test_eggs.pyc
+functional_tests/doc_tests/test_issue097/plugintest_environment.rst
+functional_tests/doc_tests/test_issue107/plugin_exceptions.rst
+functional_tests/doc_tests/test_issue107/support/test_spam.py
+functional_tests/doc_tests/test_issue107/support/test_spam.pyc
+functional_tests/doc_tests/test_issue119/empty_plugin.rst
+functional_tests/doc_tests/test_issue119/test_zeronine.py
+functional_tests/doc_tests/test_issue119/test_zeronine.pyc
+functional_tests/doc_tests/test_issue142/errorclass_failure.rst
+functional_tests/doc_tests/test_issue142/support/errorclass_failing_test.py
+functional_tests/doc_tests/test_issue142/support/errorclass_failing_test.pyc
+functional_tests/doc_tests/test_issue142/support/errorclass_failure_plugin.py
+functional_tests/doc_tests/test_issue142/support/errorclass_failure_plugin.pyc
+functional_tests/doc_tests/test_issue142/support/errorclass_tests.py
+functional_tests/doc_tests/test_issue142/support/errorclass_tests.pyc
+functional_tests/doc_tests/test_issue145/imported_tests.rst
+functional_tests/doc_tests/test_issue145/support/package1/__init__.py
+functional_tests/doc_tests/test_issue145/support/package1/__init__.pyc
+functional_tests/doc_tests/test_issue145/support/package1/test_module.py
+functional_tests/doc_tests/test_issue145/support/package1/test_module.pyc
+functional_tests/doc_tests/test_issue145/support/package2c/__init__.py
+functional_tests/doc_tests/test_issue145/support/package2c/__init__.pyc
+functional_tests/doc_tests/test_issue145/support/package2c/test_module.py
+functional_tests/doc_tests/test_issue145/support/package2c/test_module.pyc
+functional_tests/doc_tests/test_issue145/support/package2f/__init__.py
+functional_tests/doc_tests/test_issue145/support/package2f/__init__.pyc
+functional_tests/doc_tests/test_issue145/support/package2f/test_module.py
+functional_tests/doc_tests/test_issue145/support/package2f/test_module.pyc
+functional_tests/doc_tests/test_multiprocess/multiprocess.rst
+functional_tests/doc_tests/test_multiprocess/multiprocess_fixtures.py
+functional_tests/doc_tests/test_multiprocess/multiprocess_fixtures.pyc
+functional_tests/doc_tests/test_multiprocess/support/test_can_split.py
+functional_tests/doc_tests/test_multiprocess/support/test_can_split.pyc
+functional_tests/doc_tests/test_multiprocess/support/test_not_shared.py
+functional_tests/doc_tests/test_multiprocess/support/test_not_shared.pyc
+functional_tests/doc_tests/test_multiprocess/support/test_shared.py
+functional_tests/doc_tests/test_multiprocess/support/test_shared.pyc
+functional_tests/doc_tests/test_restricted_plugin_options/restricted_plugin_options.rst
+functional_tests/doc_tests/test_restricted_plugin_options/restricted_plugin_options.rst.py3.patch
+functional_tests/doc_tests/test_restricted_plugin_options/support/bad.cfg
+functional_tests/doc_tests/test_restricted_plugin_options/support/start.cfg
+functional_tests/doc_tests/test_restricted_plugin_options/support/test.py
+functional_tests/doc_tests/test_restricted_plugin_options/support/test.pyc
+functional_tests/doc_tests/test_selector_plugin/selector_plugin.rst
+functional_tests/doc_tests/test_selector_plugin/support/mymodule.py
+functional_tests/doc_tests/test_selector_plugin/support/mymodule.pyc
+functional_tests/doc_tests/test_selector_plugin/support/mypackage/__init__.py
+functional_tests/doc_tests/test_selector_plugin/support/mypackage/__init__.pyc
+functional_tests/doc_tests/test_selector_plugin/support/mypackage/strings.py
+functional_tests/doc_tests/test_selector_plugin/support/mypackage/strings.pyc
+functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/__init__.py
+functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/__init__.pyc
+functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/basic.py
+functional_tests/doc_tests/test_selector_plugin/support/mypackage/math/basic.pyc
+functional_tests/doc_tests/test_selector_plugin/support/tests/testlib.py
+functional_tests/doc_tests/test_selector_plugin/support/tests/testlib.pyc
+functional_tests/doc_tests/test_selector_plugin/support/tests/math/basic.py
+functional_tests/doc_tests/test_selector_plugin/support/tests/math/basic.pyc
+functional_tests/doc_tests/test_selector_plugin/support/tests/mymodule/my_function.py
+functional_tests/doc_tests/test_selector_plugin/support/tests/mymodule/my_function.pyc
+functional_tests/doc_tests/test_selector_plugin/support/tests/strings/cat.py
+functional_tests/doc_tests/test_selector_plugin/support/tests/strings/cat.pyc
+functional_tests/doc_tests/test_xunit_plugin/test_skips.rst
+functional_tests/doc_tests/test_xunit_plugin/support/nosetests.xml
+functional_tests/doc_tests/test_xunit_plugin/support/test_skip.py
+functional_tests/doc_tests/test_xunit_plugin/support/test_skip.pyc
+functional_tests/support/test.cfg
+functional_tests/support/test_buggy_generators.py
+functional_tests/support/test_buggy_generators.pyc
+functional_tests/support/xunit.xml
+functional_tests/support/att/test_attr.py
+functional_tests/support/att/test_attr.pyc
+functional_tests/support/coverage/blah.py
+functional_tests/support/coverage/blah.pyc
+functional_tests/support/coverage/tests/test_covered.py
+functional_tests/support/coverage/tests/test_covered.pyc
+functional_tests/support/coverage2/blah.py
+functional_tests/support/coverage2/moo.py
+functional_tests/support/coverage2/moo.pyc
+functional_tests/support/coverage2/tests/test_covered.py
+functional_tests/support/coverage2/tests/test_covered.pyc
+functional_tests/support/ctx/mod_import_skip.py
+functional_tests/support/ctx/mod_import_skip.pyc
+functional_tests/support/ctx/mod_setup_fails.py
+functional_tests/support/ctx/mod_setup_fails.pyc
+functional_tests/support/ctx/mod_setup_skip.py
+functional_tests/support/ctx/mod_setup_skip.pyc
+functional_tests/support/dir1/mod.py
+functional_tests/support/dir1/mod.pyc
+functional_tests/support/dir1/pak/__init__.py
+functional_tests/support/dir1/pak/__init__.pyc
+functional_tests/support/dir1/pak/mod.py
+functional_tests/support/dir1/pak/mod.pyc
+functional_tests/support/dir1/pak/sub/__init__.py
+functional_tests/support/dir1/pak/sub/__init__.pyc
+functional_tests/support/dir2/mod.py
+functional_tests/support/dir2/mod.pyc
+functional_tests/support/dir2/pak/__init__.py
+functional_tests/support/dir2/pak/__init__.pyc
+functional_tests/support/dir2/pak/mod.py
+functional_tests/support/dir2/pak/mod.pyc
+functional_tests/support/dir2/pak/sub/__init__.py
+functional_tests/support/dir2/pak/sub/__init__.pyc
+functional_tests/support/dtt/some_mod.py
+functional_tests/support/dtt/some_mod.pyc
+functional_tests/support/dtt/docs/doc.txt
+functional_tests/support/dtt/docs/errdoc.txt
+functional_tests/support/dtt/docs/nodoc.txt
+functional_tests/support/empty/.hidden
+functional_tests/support/ep/setup.py
+functional_tests/support/ep/someplugin.py
+functional_tests/support/ep/Some_plugin.egg-info/PKG-INFO
+functional_tests/support/ep/Some_plugin.egg-info/SOURCES.txt
+functional_tests/support/ep/Some_plugin.egg-info/dependency_links.txt
+functional_tests/support/ep/Some_plugin.egg-info/entry_points.txt
+functional_tests/support/ep/Some_plugin.egg-info/top_level.txt
+functional_tests/support/fdp/test_fdp.py
+functional_tests/support/fdp/test_fdp.pyc
+functional_tests/support/fdp/test_fdp_no_capt.py
+functional_tests/support/fdp/test_fdp_no_capt.pyc
+functional_tests/support/gen/test.py
+functional_tests/support/gen/test.pyc
+functional_tests/support/id_fails/test_a.py
+functional_tests/support/id_fails/test_a.pyc
+functional_tests/support/id_fails/test_b.py
+functional_tests/support/id_fails/test_b.pyc
+functional_tests/support/idp/exm.py
+functional_tests/support/idp/exm.pyc
+functional_tests/support/idp/tests.py
+functional_tests/support/idp/tests.pyc
+functional_tests/support/ipt/test1/ipthelp.py
+functional_tests/support/ipt/test1/ipthelp.pyc
+functional_tests/support/ipt/test1/tests.py
+functional_tests/support/ipt/test1/tests.pyc
+functional_tests/support/ipt/test2/ipthelp.py
+functional_tests/support/ipt/test2/ipthelp.pyc
+functional_tests/support/ipt/test2/tests.py
+functional_tests/support/ipt/test2/tests.pyc
+functional_tests/support/issue038/test.py
+functional_tests/support/issue038/test.pyc
+functional_tests/support/issue072/test.py
+functional_tests/support/issue072/test.pyc
+functional_tests/support/issue082/_mypackage/__init__.py
+functional_tests/support/issue082/_mypackage/_eggs.py
+functional_tests/support/issue082/_mypackage/bacon.py
+functional_tests/support/issue082/mypublicpackage/__init__.py
+functional_tests/support/issue082/mypublicpackage/__init__.pyc
+functional_tests/support/issue082/mypublicpackage/_foo.py
+functional_tests/support/issue082/mypublicpackage/_foo.pyc
+functional_tests/support/issue082/mypublicpackage/bar.py
+functional_tests/support/issue082/mypublicpackage/bar.pyc
+functional_tests/support/issue130/test.py
+functional_tests/support/issue130/test.pyc
+functional_tests/support/issue143/not-a-package/__init__.py
+functional_tests/support/issue143/not-a-package/test.py
+functional_tests/support/issue191/setup.cfg
+functional_tests/support/issue191/setup.py
+functional_tests/support/issue191/test.py
+functional_tests/support/issue191/test.pyc
+functional_tests/support/issue191/UNKNOWN.egg-info/PKG-INFO
+functional_tests/support/issue191/UNKNOWN.egg-info/SOURCES.txt
+functional_tests/support/issue191/UNKNOWN.egg-info/dependency_links.txt
+functional_tests/support/issue191/UNKNOWN.egg-info/top_level.txt
+functional_tests/support/issue269/test_bad_class.py
+functional_tests/support/issue269/test_bad_class.pyc
+functional_tests/support/issue279/test_mod_setup_fails.py
+functional_tests/support/issue279/test_mod_setup_fails.pyc
+functional_tests/support/issue408/nosetests.xml
+functional_tests/support/issue408/test.py
+functional_tests/support/issue408/test.pyc
+functional_tests/support/ltfn/state.py
+functional_tests/support/ltfn/state.pyc
+functional_tests/support/ltfn/test_mod.py
+functional_tests/support/ltfn/test_mod.pyc
+functional_tests/support/ltfn/test_pak1/__init__.py
+functional_tests/support/ltfn/test_pak1/__init__.pyc
+functional_tests/support/ltfn/test_pak1/test_mod.py
+functional_tests/support/ltfn/test_pak1/test_mod.pyc
+functional_tests/support/ltfn/test_pak2/__init__.py
+functional_tests/support/ltfn/test_pak2/__init__.pyc
+functional_tests/support/ltftc/tests.py
+functional_tests/support/ltftc/tests.pyc
+functional_tests/support/namespace_pkg/namespace_pkg/__init__.py
+functional_tests/support/namespace_pkg/namespace_pkg/__init__.pyc
+functional_tests/support/namespace_pkg/namespace_pkg/example.py
+functional_tests/support/namespace_pkg/namespace_pkg/example.pyc
+functional_tests/support/namespace_pkg/namespace_pkg/test_pkg.py
+functional_tests/support/namespace_pkg/namespace_pkg/test_pkg.pyc
+functional_tests/support/namespace_pkg/site-packages/namespace_pkg/__init__.py
+functional_tests/support/namespace_pkg/site-packages/namespace_pkg/example2.py
+functional_tests/support/namespace_pkg/site-packages/namespace_pkg/example2.pyc
+functional_tests/support/namespace_pkg/site-packages/namespace_pkg/test_pkg2.py
+functional_tests/support/namespace_pkg/site-packages/namespace_pkg/test_pkg2.pyc
+functional_tests/support/package1/example.py
+functional_tests/support/package1/example.pyc
+functional_tests/support/package1/tests/test_example_function.py
+functional_tests/support/package1/tests/test_example_function.pyc
+functional_tests/support/package2/maths.py
+functional_tests/support/package2/maths.pyc
+functional_tests/support/package2/test_pak/__init__.py
+functional_tests/support/package2/test_pak/__init__.pyc
+functional_tests/support/package2/test_pak/test_mod.py
+functional_tests/support/package2/test_pak/test_mod.pyc
+functional_tests/support/package2/test_pak/test_sub/__init__.py
+functional_tests/support/package2/test_pak/test_sub/__init__.pyc
+functional_tests/support/package2/test_pak/test_sub/test_mod.py
+functional_tests/support/package2/test_pak/test_sub/test_mod.pyc
+functional_tests/support/package3/lib/a.py
+functional_tests/support/package3/lib/a.pyc
+functional_tests/support/package3/src/b.py
+functional_tests/support/package3/src/b.pyc
+functional_tests/support/package3/tests/test_a.py
+functional_tests/support/package3/tests/test_a.pyc
+functional_tests/support/package3/tests/test_b.py
+functional_tests/support/package3/tests/test_b.pyc
+functional_tests/support/pass/test.py
+functional_tests/support/pass/test.pyc
+functional_tests/support/todo/test_with_todo.py
+functional_tests/support/todo/test_with_todo.pyc
+functional_tests/support/todo/todoplug.py
+functional_tests/support/todo/todoplug.pyc
+functional_tests/support/twist/test_twisted.py
+functional_tests/support/twist/test_twisted.pyc
+functional_tests/support/xunit/test_xunit_as_suite.py
+functional_tests/support/xunit/test_xunit_as_suite.pyc
+functional_tests/test_issue120/test_named_test_with_doctest.rst
+functional_tests/test_issue120/support/some_test.py
+functional_tests/test_issue120/support/some_test.pyc
+functional_tests/test_multiprocessing/__init__.py
+functional_tests/test_multiprocessing/__init__.pyc
+functional_tests/test_multiprocessing/test_class.py
+functional_tests/test_multiprocessing/test_class.pyc
+functional_tests/test_multiprocessing/test_concurrent_shared.py
+functional_tests/test_multiprocessing/test_concurrent_shared.pyc
+functional_tests/test_multiprocessing/test_keyboardinterrupt.py
+functional_tests/test_multiprocessing/test_keyboardinterrupt.pyc
+functional_tests/test_multiprocessing/test_nameerror.py
+functional_tests/test_multiprocessing/test_nameerror.pyc
+functional_tests/test_multiprocessing/test_process_timeout.py
+functional_tests/test_multiprocessing/test_process_timeout.pyc
+functional_tests/test_multiprocessing/support/class.py
+functional_tests/test_multiprocessing/support/class.pyc
+functional_tests/test_multiprocessing/support/fake_nosetest.py
+functional_tests/test_multiprocessing/support/keyboardinterrupt.py
+functional_tests/test_multiprocessing/support/keyboardinterrupt.pyc
+functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.py
+functional_tests/test_multiprocessing/support/keyboardinterrupt_twice.pyc
+functional_tests/test_multiprocessing/support/nameerror.py
+functional_tests/test_multiprocessing/support/nameerror.pyc
+functional_tests/test_multiprocessing/support/timeout.py
+functional_tests/test_multiprocessing/support/timeout.pyc
+functional_tests/test_multiprocessing/support/concurrent_shared/__init__.py
+functional_tests/test_multiprocessing/support/concurrent_shared/__init__.pyc
+functional_tests/test_multiprocessing/support/concurrent_shared/test.py
+functional_tests/test_multiprocessing/support/concurrent_shared/test.pyc
+nose/__init__.py
+nose/case.py
+nose/commands.py
+nose/config.py
+nose/core.py
+nose/exc.py
+nose/failure.py
+nose/importer.py
+nose/inspector.py
+nose/loader.py
+nose/proxy.py
+nose/pyversion.py
+nose/result.py
+nose/selector.py
+nose/suite.py
+nose/twistedtools.py
+nose/usage.txt
+nose/util.py
+nose.egg-info/PKG-INFO
+nose.egg-info/SOURCES.txt
+nose.egg-info/dependency_links.txt
+nose.egg-info/entry_points.txt
+nose.egg-info/not-zip-safe
+nose.egg-info/top_level.txt
+nose/ext/__init__.py
+nose/ext/dtcompat.py
+nose/plugins/__init__.py
+nose/plugins/allmodules.py
+nose/plugins/attrib.py
+nose/plugins/base.py
+nose/plugins/builtin.py
+nose/plugins/capture.py
+nose/plugins/collect.py
+nose/plugins/cover.py
+nose/plugins/debug.py
+nose/plugins/deprecated.py
+nose/plugins/doctests.py
+nose/plugins/errorclass.py
+nose/plugins/failuredetail.py
+nose/plugins/isolate.py
+nose/plugins/logcapture.py
+nose/plugins/manager.py
+nose/plugins/multiprocess.py
+nose/plugins/plugintest.py
+nose/plugins/prof.py
+nose/plugins/skip.py
+nose/plugins/testid.py
+nose/plugins/xunit.py
+nose/sphinx/__init__.py
+nose/sphinx/pluginopts.py
+nose/tools/__init__.py
+nose/tools/nontrivial.py
+nose/tools/trivial.py
+unit_tests/helpers.py
+unit_tests/helpers.pyc
+unit_tests/mock.py
+unit_tests/mock.pyc
+unit_tests/test_attribute_plugin.py
+unit_tests/test_attribute_plugin.pyc
+unit_tests/test_bug105.py
+unit_tests/test_bug105.pyc
+unit_tests/test_capture_plugin.py
+unit_tests/test_capture_plugin.pyc
+unit_tests/test_cases.py
+unit_tests/test_cases.pyc
+unit_tests/test_config.py
+unit_tests/test_config.pyc
+unit_tests/test_config_defaults.rst
+unit_tests/test_core.py
+unit_tests/test_core.pyc
+unit_tests/test_deprecated_plugin.py
+unit_tests/test_deprecated_plugin.pyc
+unit_tests/test_doctest_error_handling.py
+unit_tests/test_doctest_error_handling.pyc
+unit_tests/test_doctest_munging.rst
+unit_tests/test_id_plugin.py
+unit_tests/test_id_plugin.pyc
+unit_tests/test_importer.py
+unit_tests/test_importer.pyc
+unit_tests/test_inspector.py
+unit_tests/test_inspector.pyc
+unit_tests/test_isolation_plugin.py
+unit_tests/test_isolation_plugin.pyc
+unit_tests/test_issue155.rst
+unit_tests/test_issue270.rst
+unit_tests/test_issue270_fixtures.py
+unit_tests/test_issue270_fixtures.pyc
+unit_tests/test_issue_006.py
+unit_tests/test_issue_006.pyc
+unit_tests/test_issue_064.py
+unit_tests/test_issue_064.pyc
+unit_tests/test_issue_065.py
+unit_tests/test_issue_065.pyc
+unit_tests/test_issue_100.rst
+unit_tests/test_issue_100.rst.py3.patch
+unit_tests/test_issue_101.py
+unit_tests/test_issue_101.pyc
+unit_tests/test_issue_159.rst
+unit_tests/test_issue_227.py
+unit_tests/test_issue_227.pyc
+unit_tests/test_issue_230.py
+unit_tests/test_issue_230.pyc
+unit_tests/test_lazy_suite.py
+unit_tests/test_lazy_suite.pyc
+unit_tests/test_loader.py
+unit_tests/test_loader.pyc
+unit_tests/test_logcapture_plugin.py
+unit_tests/test_logcapture_plugin.pyc
+unit_tests/test_logging.py
+unit_tests/test_logging.pyc
+unit_tests/test_ls_tree.rst
+unit_tests/test_multiprocess.py
+unit_tests/test_multiprocess.pyc
+unit_tests/test_multiprocess_runner.py
+unit_tests/test_multiprocess_runner.pyc
+unit_tests/test_pdb_plugin.py
+unit_tests/test_pdb_plugin.pyc
+unit_tests/test_plugin.py
+unit_tests/test_plugin.pyc
+unit_tests/test_plugin_interfaces.py
+unit_tests/test_plugin_interfaces.pyc
+unit_tests/test_plugin_manager.py
+unit_tests/test_plugin_manager.pyc
+unit_tests/test_plugins.py
+unit_tests/test_plugins.pyc
+unit_tests/test_result_proxy.py
+unit_tests/test_result_proxy.pyc
+unit_tests/test_selector.py
+unit_tests/test_selector.pyc
+unit_tests/test_selector_plugins.py
+unit_tests/test_selector_plugins.pyc
+unit_tests/test_skip_plugin.py
+unit_tests/test_skip_plugin.pyc
+unit_tests/test_suite.py
+unit_tests/test_suite.pyc
+unit_tests/test_tools.py
+unit_tests/test_tools.pyc
+unit_tests/test_twisted.py
+unit_tests/test_twisted.pyc
+unit_tests/test_twisted_testcase.py
+unit_tests/test_twisted_testcase.pyc
+unit_tests/test_utils.py
+unit_tests/test_utils.pyc
+unit_tests/test_xunit.py
+unit_tests/test_xunit.pyc
+unit_tests/support/script.py
+unit_tests/support/test.py
+unit_tests/support/bug101/tests.py
+unit_tests/support/bug105/tests.py
+unit_tests/support/bug105/tests.pyc
+unit_tests/support/config_defaults/a.cfg
+unit_tests/support/config_defaults/b.cfg
+unit_tests/support/config_defaults/invalid.cfg
+unit_tests/support/config_defaults/invalid_value.cfg
+unit_tests/support/doctest/err_doctests.py
+unit_tests/support/doctest/err_doctests.pyc
+unit_tests/support/doctest/no_doctests.py
+unit_tests/support/doctest/no_doctests.pyc
+unit_tests/support/foo/__init__.py
+unit_tests/support/foo/__init__.pyc
+unit_tests/support/foo/doctests.txt
+unit_tests/support/foo/test_foo.py
+unit_tests/support/foo/bar/__init__.py
+unit_tests/support/foo/bar/__init__.pyc
+unit_tests/support/foo/bar/buz.py
+unit_tests/support/foo/bar/buz.pyc
+unit_tests/support/foo/tests/dir_test_file.py
+unit_tests/support/issue006/tests.py
+unit_tests/support/issue006/tests.pyc
+unit_tests/support/issue065/tests.py
+unit_tests/support/issue065/tests.pyc
+unit_tests/support/issue270/__init__.py
+unit_tests/support/issue270/__init__.pyc
+unit_tests/support/issue270/foo_test.py
+unit_tests/support/issue270/foo_test.pyc
+unit_tests/support/other/file.txt
+unit_tests/support/pkgorg/lib/modernity.py
+unit_tests/support/pkgorg/tests/test_mod.py
+unit_tests/support/test-dir/test.py
\ No newline at end of file
diff --git a/nose.egg-info/dependency_links.txt b/nose.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/nose.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/nose.egg-info/entry_points.txt b/nose.egg-info/entry_points.txt
new file mode 100644
index 0000000..07c6548
--- /dev/null
+++ b/nose.egg-info/entry_points.txt
@@ -0,0 +1,7 @@
+[console_scripts]
+nosetests = nose:run_exit
+nosetests-2.7 = nose:run_exit
+
+[distutils.commands]
+nosetests = nose.commands:nosetests
+
diff --git a/nose.egg-info/not-zip-safe b/nose.egg-info/not-zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/nose.egg-info/not-zip-safe
@@ -0,0 +1 @@
+
diff --git a/nose.egg-info/top_level.txt b/nose.egg-info/top_level.txt
new file mode 100644
index 0000000..f3c7e8e
--- /dev/null
+++ b/nose.egg-info/top_level.txt
@@ -0,0 +1 @@
+nose
diff --git a/nose/__init__.py b/nose/__init__.py
new file mode 100644
index 0000000..85a9750
--- /dev/null
+++ b/nose/__init__.py
@@ -0,0 +1,15 @@
+from nose.core import collector, main, run, run_exit, runmodule
+# backwards compatibility
+from nose.exc import SkipTest, DeprecatedTest
+from nose.tools import with_setup
+
+__author__ = 'Jason Pellerin'
+__versioninfo__ = (1, 2, 1)
+__version__ = '.'.join(map(str, __versioninfo__))
+
+__all__ = [
+ 'main', 'run', 'run_exit', 'runmodule', 'with_setup',
+ 'SkipTest', 'DeprecatedTest', 'collector'
+ ]
+
+
diff --git a/nose/case.py b/nose/case.py
new file mode 100644
index 0000000..cffa4ab
--- /dev/null
+++ b/nose/case.py
@@ -0,0 +1,397 @@
+"""nose unittest.TestCase subclasses. It is not necessary to subclass these
+classes when writing tests; they are used internally by nose.loader.TestLoader
+to create test cases from test functions and methods in test classes.
+"""
+import logging
+import sys
+import unittest
+from inspect import isfunction
+from nose.config import Config
+from nose.failure import Failure # for backwards compatibility
+from nose.util import resolve_name, test_address, try_run
+
+log = logging.getLogger(__name__)
+
+
+__all__ = ['Test']
+
+
+class Test(unittest.TestCase):
+ """The universal test case wrapper.
+
+ When a plugin sees a test, it will always see an instance of this
+ class. To access the actual test case that will be run, access the
+ test property of the nose.case.Test instance.
+ """
+ __test__ = False # do not collect
+ def __init__(self, test, config=None, resultProxy=None):
+ # sanity check
+ if not callable(test):
+ raise TypeError("nose.case.Test called with argument %r that "
+ "is not callable. A callable is required."
+ % test)
+ self.test = test
+ if config is None:
+ config = Config()
+ self.config = config
+ self.tbinfo = None
+ self.capturedOutput = None
+ self.resultProxy = resultProxy
+ self.plugins = config.plugins
+ self.passed = None
+ unittest.TestCase.__init__(self)
+
+ def __call__(self, *arg, **kwarg):
+ return self.run(*arg, **kwarg)
+
+ def __str__(self):
+ name = self.plugins.testName(self)
+ if name is not None:
+ return name
+ return str(self.test)
+
+ def __repr__(self):
+ return "Test(%r)" % self.test
+
+ def afterTest(self, result):
+ """Called after test is complete (after result.stopTest)
+ """
+ try:
+ afterTest = result.afterTest
+ except AttributeError:
+ pass
+ else:
+ afterTest(self.test)
+
+ def beforeTest(self, result):
+ """Called before test is run (before result.startTest)
+ """
+ try:
+ beforeTest = result.beforeTest
+ except AttributeError:
+ pass
+ else:
+ beforeTest(self.test)
+
+ def exc_info(self):
+ """Extract exception info.
+ """
+ exc, exv, tb = sys.exc_info()
+ return (exc, exv, tb)
+
+ def id(self):
+ """Get a short(er) description of the test
+ """
+ return self.test.id()
+
+ def address(self):
+ """Return a round-trip name for this test, a name that can be
+ fed back as input to loadTestByName and (assuming the same
+ plugin configuration) result in the loading of this test.
+ """
+ if hasattr(self.test, 'address'):
+ return self.test.address()
+ else:
+ # not a nose case
+ return test_address(self.test)
+
+ def _context(self):
+ try:
+ return self.test.context
+ except AttributeError:
+ pass
+ try:
+ return self.test.__class__
+ except AttributeError:
+ pass
+ try:
+ return resolve_name(self.test.__module__)
+ except AttributeError:
+ pass
+ return None
+ context = property(_context, None, None,
+ """Get the context object of this test (if any).""")
+
+ def run(self, result):
+ """Modified run for the test wrapper.
+
+ From here we don't call result.startTest or stopTest or
+ addSuccess. The wrapper calls addError/addFailure only if its
+ own setup or teardown fails, or running the wrapped test fails
+ (eg, if the wrapped "test" is not callable).
+
+ Two additional methods are called, beforeTest and
+ afterTest. These give plugins a chance to modify the wrapped
+ test before it is called and do cleanup after it is
+ called. They are called unconditionally.
+ """
+ if self.resultProxy:
+ result = self.resultProxy(result, self)
+ try:
+ try:
+ self.beforeTest(result)
+ self.runTest(result)
+ except KeyboardInterrupt:
+ raise
+ except:
+ err = sys.exc_info()
+ result.addError(self, err)
+ finally:
+ self.afterTest(result)
+
+ def runTest(self, result):
+ """Run the test. Plugins may alter the test by returning a
+ value from prepareTestCase. The value must be callable and
+ must accept one argument, the result instance.
+ """
+ test = self.test
+ plug_test = self.config.plugins.prepareTestCase(self)
+ if plug_test is not None:
+ test = plug_test
+ test(result)
+
+ def shortDescription(self):
+ desc = self.plugins.describeTest(self)
+ if desc is not None:
+ return desc
+ # work around bug in unittest.TestCase.shortDescription
+ # with multiline docstrings.
+ test = self.test
+ try:
+ test._testMethodDoc = test._testMethodDoc.strip()# 2.5
+ except AttributeError:
+ try:
+ # 2.4 and earlier
+ test._TestCase__testMethodDoc = \
+ test._TestCase__testMethodDoc.strip()
+ except AttributeError:
+ pass
+ # 2.7 compat: shortDescription() always returns something
+ # which is a change from 2.6 and below, and breaks the
+ # testName plugin call.
+ try:
+ desc = self.test.shortDescription()
+ except Exception:
+ # this is probably caused by a problem in test.__str__() and is
+ # only triggered by python 3.1's unittest!
+ pass
+ try:
+ if desc == str(self.test):
+ return
+ except Exception:
+ # If str() triggers an exception then ignore it.
+ # see issue 422
+ pass
+ return desc
+
+
+class TestBase(unittest.TestCase):
+ """Common functionality for FunctionTestCase and MethodTestCase.
+ """
+ __test__ = False # do not collect
+
+ def id(self):
+ return str(self)
+
+ def runTest(self):
+ self.test(*self.arg)
+
+ def shortDescription(self):
+ if hasattr(self.test, 'description'):
+ return self.test.description
+ func, arg = self._descriptors()
+ doc = getattr(func, '__doc__', None)
+ if not doc:
+ doc = str(self)
+ return doc.strip().split("\n")[0].strip()
+
+
+class FunctionTestCase(TestBase):
+ """TestCase wrapper for test functions.
+
+ Don't use this class directly; it is used internally in nose to
+ create test cases for test functions.
+ """
+ __test__ = False # do not collect
+
+ def __init__(self, test, setUp=None, tearDown=None, arg=tuple(),
+ descriptor=None):
+ """Initialize the MethodTestCase.
+
+ Required argument:
+
+ * test -- the test function to call.
+
+ Optional arguments:
+
+ * setUp -- function to run at setup.
+
+ * tearDown -- function to run at teardown.
+
+ * arg -- arguments to pass to the test function. This is to support
+ generator functions that yield arguments.
+
+ * descriptor -- the function, other than the test, that should be used
+ to construct the test name. This is to support generator functions.
+ """
+
+ self.test = test
+ self.setUpFunc = setUp
+ self.tearDownFunc = tearDown
+ self.arg = arg
+ self.descriptor = descriptor
+ TestBase.__init__(self)
+
+ def address(self):
+ """Return a round-trip name for this test, a name that can be
+ fed back as input to loadTestByName and (assuming the same
+ plugin configuration) result in the loading of this test.
+ """
+ if self.descriptor is not None:
+ return test_address(self.descriptor)
+ else:
+ return test_address(self.test)
+
+ def _context(self):
+ return resolve_name(self.test.__module__)
+ context = property(_context, None, None,
+ """Get context (module) of this test""")
+
+ def setUp(self):
+ """Run any setup function attached to the test function
+ """
+ if self.setUpFunc:
+ self.setUpFunc()
+ else:
+ names = ('setup', 'setUp', 'setUpFunc')
+ try_run(self.test, names)
+
+ def tearDown(self):
+ """Run any teardown function attached to the test function
+ """
+ if self.tearDownFunc:
+ self.tearDownFunc()
+ else:
+ names = ('teardown', 'tearDown', 'tearDownFunc')
+ try_run(self.test, names)
+
+ def __str__(self):
+ func, arg = self._descriptors()
+ if hasattr(func, 'compat_func_name'):
+ name = func.compat_func_name
+ else:
+ name = func.__name__
+ name = "%s.%s" % (func.__module__, name)
+ if arg:
+ name = "%s%s" % (name, arg)
+ # FIXME need to include the full dir path to disambiguate
+ # in cases where test module of the same name was seen in
+ # another directory (old fromDirectory)
+ return name
+ __repr__ = __str__
+
+ def _descriptors(self):
+ """Get the descriptors of the test function: the function and
+ arguments that will be used to construct the test name. In
+ most cases, this is the function itself and no arguments. For
+ tests generated by generator functions, the original
+ (generator) function and args passed to the generated function
+ are returned.
+ """
+ if self.descriptor:
+ return self.descriptor, self.arg
+ else:
+ return self.test, self.arg
+
+
+class MethodTestCase(TestBase):
+ """Test case wrapper for test methods.
+
+ Don't use this class directly; it is used internally in nose to
+ create test cases for test methods.
+ """
+ __test__ = False # do not collect
+
+ def __init__(self, method, test=None, arg=tuple(), descriptor=None):
+ """Initialize the MethodTestCase.
+
+ Required argument:
+
+ * method -- the method to call, may be bound or unbound. In either
+ case, a new instance of the method's class will be instantiated to
+ make the call. Note: In Python 3.x, if using an unbound method, you
+ must wrap it using pyversion.unbound_method.
+
+ Optional arguments:
+
+ * test -- the test function to call. If this is passed, it will be
+ called instead of getting a new bound method of the same name as the
+ desired method from the test instance. This is to support generator
+ methods that yield inline functions.
+
+ * arg -- arguments to pass to the test function. This is to support
+ generator methods that yield arguments.
+
+ * descriptor -- the function, other than the test, that should be used
+ to construct the test name. This is to support generator methods.
+ """
+ self.method = method
+ self.test = test
+ self.arg = arg
+ self.descriptor = descriptor
+ if isfunction(method):
+ raise ValueError("Unbound methods must be wrapped using pyversion.unbound_method before passing to MethodTestCase")
+ self.cls = method.im_class
+ self.inst = self.cls()
+ if self.test is None:
+ method_name = self.method.__name__
+ self.test = getattr(self.inst, method_name)
+ TestBase.__init__(self)
+
+ def __str__(self):
+ func, arg = self._descriptors()
+ if hasattr(func, 'compat_func_name'):
+ name = func.compat_func_name
+ else:
+ name = func.__name__
+ name = "%s.%s.%s" % (self.cls.__module__,
+ self.cls.__name__,
+ name)
+ if arg:
+ name = "%s%s" % (name, arg)
+ return name
+ __repr__ = __str__
+
+ def address(self):
+ """Return a round-trip name for this test, a name that can be
+ fed back as input to loadTestByName and (assuming the same
+ plugin configuration) result in the loading of this test.
+ """
+ if self.descriptor is not None:
+ return test_address(self.descriptor)
+ else:
+ return test_address(self.method)
+
+ def _context(self):
+ return self.cls
+ context = property(_context, None, None,
+ """Get context (class) of this test""")
+
+ def setUp(self):
+ try_run(self.inst, ('setup', 'setUp'))
+
+ def tearDown(self):
+ try_run(self.inst, ('teardown', 'tearDown'))
+
+ def _descriptors(self):
+ """Get the descriptors of the test method: the method and
+ arguments that will be used to construct the test name. In
+ most cases, this is the method itself and no arguments. For
+ tests generated by generator methods, the original
+ (generator) method and args passed to the generated method
+ or function are returned.
+ """
+ if self.descriptor:
+ return self.descriptor, self.arg
+ else:
+ return self.method, self.arg
diff --git a/nose/commands.py b/nose/commands.py
new file mode 100644
index 0000000..3b43ed0
--- /dev/null
+++ b/nose/commands.py
@@ -0,0 +1,163 @@
+"""
+nosetests setuptools command
+----------------------------
+
+The easiest way to run tests with nose is to use the `nosetests` setuptools
+command::
+
+ python setup.py nosetests
+
+This command has one *major* benefit over the standard `test` command: *all
+nose plugins are supported*.
+
+To configure the `nosetests` command, add a [nosetests] section to your
+setup.cfg. The [nosetests] section can contain any command line arguments that
+nosetests supports. The differences between issuing an option on the command
+line and adding it to setup.cfg are:
+
+* In setup.cfg, the -- prefix must be excluded
+* In setup.cfg, command line flags that take no arguments must be given an
+ argument flag (1, T or TRUE for active, 0, F or FALSE for inactive)
+
+Here's an example [nosetests] setup.cfg section::
+
+ [nosetests]
+ verbosity=1
+ detailed-errors=1
+ with-coverage=1
+ cover-package=nose
+ debug=nose.loader
+ pdb=1
+ pdb-failures=1
+
+If you commonly run nosetests with a large number of options, using
+the nosetests setuptools command and configuring with setup.cfg can
+make running your tests much less tedious. (Note that the same options
+and format supported in setup.cfg are supported in all other config
+files, and the nosetests script will also load config files.)
+
+Another reason to run tests with the command is that the command will
+install packages listed in your `tests_require`, as well as doing a
+complete build of your package before running tests. For packages with
+dependencies or that build C extensions, using the setuptools command
+can be more convenient than building by hand and running the nosetests
+script.
+
+Bootstrapping
+-------------
+
+If you are distributing your project and want users to be able to run tests
+without having to install nose themselves, add nose to the setup_requires
+section of your setup()::
+
+ setup(
+ # ...
+ setup_requires=['nose>=1.0']
+ )
+
+This will direct setuptools to download and activate nose during the setup
+process, making the ``nosetests`` command available.
+
+"""
+try:
+ from setuptools import Command
+except ImportError:
+ Command = nosetests = None
+else:
+ from nose.config import Config, option_blacklist, user_config_files, \
+ flag, _bool
+ from nose.core import TestProgram
+ from nose.plugins import DefaultPluginManager
+
+
+ def get_user_options(parser):
+ """convert a optparse option list into a distutils option tuple list"""
+ opt_list = []
+ for opt in parser.option_list:
+ if opt._long_opts[0][2:] in option_blacklist:
+ continue
+ long_name = opt._long_opts[0][2:]
+ if opt.action not in ('store_true', 'store_false'):
+ long_name = long_name + "="
+ short_name = None
+ if opt._short_opts:
+ short_name = opt._short_opts[0][1:]
+ opt_list.append((long_name, short_name, opt.help or ""))
+ return opt_list
+
+
+ class nosetests(Command):
+ description = "Run unit tests using nosetests"
+ __config = Config(files=user_config_files(),
+ plugins=DefaultPluginManager())
+ __parser = __config.getParser()
+ user_options = get_user_options(__parser)
+
+ def initialize_options(self):
+ """create the member variables, but change hyphens to
+ underscores
+ """
+
+ self.option_to_cmds = {}
+ for opt in self.__parser.option_list:
+ cmd_name = opt._long_opts[0][2:]
+ option_name = cmd_name.replace('-', '_')
+ self.option_to_cmds[option_name] = cmd_name
+ setattr(self, option_name, None)
+ self.attr = None
+
+ def finalize_options(self):
+ """nothing to do here"""
+ pass
+
+ def run(self):
+ """ensure tests are capable of being run, then
+ run nose.main with a reconstructed argument list"""
+ if getattr(self.distribution, 'use_2to3', False):
+ # If we run 2to3 we can not do this inplace:
+
+ # Ensure metadata is up-to-date
+ self.reinitialize_command('build_py', inplace=0)
+ self.run_command('build_py')
+ bpy_cmd = self.get_finalized_command("build_py")
+ build_path = bpy_cmd.build_lib
+
+ # Build extensions
+ self.reinitialize_command('egg_info', egg_base=build_path)
+ self.run_command('egg_info')
+
+ self.reinitialize_command('build_ext', inplace=0)
+ self.run_command('build_ext')
+ else:
+ self.run_command('egg_info')
+
+ # Build extensions in-place
+ self.reinitialize_command('build_ext', inplace=1)
+ self.run_command('build_ext')
+
+ if self.distribution.install_requires:
+ self.distribution.fetch_build_eggs(
+ self.distribution.install_requires)
+ if self.distribution.tests_require:
+ self.distribution.fetch_build_eggs(
+ self.distribution.tests_require)
+
+ ei_cmd = self.get_finalized_command("egg_info")
+ argv = ['nosetests', ei_cmd.egg_base]
+ for (option_name, cmd_name) in self.option_to_cmds.items():
+ if option_name in option_blacklist:
+ continue
+ value = getattr(self, option_name)
+ if value is not None:
+ argv.extend(
+ self.cfgToArg(option_name.replace('_', '-'), value))
+ TestProgram(argv=argv, config=self.__config)
+
+ def cfgToArg(self, optname, value):
+ argv = []
+ if flag(value):
+ if _bool(value):
+ argv.append('--' + optname)
+ else:
+ argv.extend(['--' + optname, value])
+ return argv
diff --git a/nose/config.py b/nose/config.py
new file mode 100644
index 0000000..e110b7a
--- /dev/null
+++ b/nose/config.py
@@ -0,0 +1,638 @@
+import logging
+import optparse
+import os
+import re
+import sys
+import ConfigParser
+from optparse import OptionParser
+from nose.util import absdir, tolist
+from nose.plugins.manager import NoPlugins
+from warnings import warn
+
+log = logging.getLogger(__name__)
+
+# not allowed in config files
+option_blacklist = ['help', 'verbose']
+
+config_files = [
+ # Linux users will prefer this
+ "~/.noserc",
+ # Windows users will prefer this
+ "~/nose.cfg"
+ ]
+
+# plaforms on which the exe check defaults to off
+# Windows and IronPython
+exe_allowed_platforms = ('win32', 'cli')
+
+
+class NoSuchOptionError(Exception):
+ def __init__(self, name):
+ Exception.__init__(self, name)
+ self.name = name
+
+
+class ConfigError(Exception):
+ pass
+
+
+class ConfiguredDefaultsOptionParser(object):
+ """
+ Handler for options from commandline and config files.
+ """
+ def __init__(self, parser, config_section, error=None, file_error=None):
+ self._parser = parser
+ self._config_section = config_section
+ if error is None:
+ error = self._parser.error
+ self._error = error
+ if file_error is None:
+ file_error = lambda msg, **kw: error(msg)
+ self._file_error = file_error
+
+ def _configTuples(self, cfg, filename):
+ config = []
+ if self._config_section in cfg.sections():
+ for name, value in cfg.items(self._config_section):
+ config.append((name, value, filename))
+ return config
+
+ def _readFromFilenames(self, filenames):
+ config = []
+ for filename in filenames:
+ cfg = ConfigParser.RawConfigParser()
+ try:
+ cfg.read(filename)
+ except ConfigParser.Error, exc:
+ raise ConfigError("Error reading config file %r: %s" %
+ (filename, str(exc)))
+ config.extend(self._configTuples(cfg, filename))
+ return config
+
+ def _readFromFileObject(self, fh):
+ cfg = ConfigParser.RawConfigParser()
+ try:
+ filename = fh.name
+ except AttributeError:
+ filename = '??>'
+ try:
+ cfg.readfp(fh)
+ except ConfigParser.Error, exc:
+ raise ConfigError("Error reading config file %r: %s" %
+ (filename, str(exc)))
+ return self._configTuples(cfg, filename)
+
+ def _readConfiguration(self, config_files):
+ try:
+ config_files.readline
+ except AttributeError:
+ filename_or_filenames = config_files
+ if isinstance(filename_or_filenames, basestring):
+ filenames = [filename_or_filenames]
+ else:
+ filenames = filename_or_filenames
+ config = self._readFromFilenames(filenames)
+ else:
+ fh = config_files
+ config = self._readFromFileObject(fh)
+ return config
+
+ def _processConfigValue(self, name, value, values, parser):
+ opt_str = '--' + name
+ option = parser.get_option(opt_str)
+ if option is None:
+ raise NoSuchOptionError(name)
+ else:
+ option.process(opt_str, value, values, parser)
+
+ def _applyConfigurationToValues(self, parser, config, values):
+ for name, value, filename in config:
+ if name in option_blacklist:
+ continue
+ try:
+ self._processConfigValue(name, value, values, parser)
+ except NoSuchOptionError, exc:
+ self._file_error(
+ "Error reading config file %r: "
+ "no such option %r" % (filename, exc.name),
+ name=name, filename=filename)
+ except optparse.OptionValueError, exc:
+ msg = str(exc).replace('--' + name, repr(name), 1)
+ self._file_error("Error reading config file %r: "
+ "%s" % (filename, msg),
+ name=name, filename=filename)
+
+ def parseArgsAndConfigFiles(self, args, config_files):
+ values = self._parser.get_default_values()
+ try:
+ config = self._readConfiguration(config_files)
+ except ConfigError, exc:
+ self._error(str(exc))
+ else:
+ self._applyConfigurationToValues(self._parser, config, values)
+ return self._parser.parse_args(args, values)
+
+
+class Config(object):
+ """nose configuration.
+
+ Instances of Config are used throughout nose to configure
+ behavior, including plugin lists. Here are the default values for
+ all config keys::
+
+ self.env = env = kw.pop('env', {})
+ self.args = ()
+ self.testMatch = re.compile(r'(?:^|[\\b_\\.%s-])[Tt]est' % os.sep)
+ self.addPaths = not env.get('NOSE_NOPATH', False)
+ self.configSection = 'nosetests'
+ self.debug = env.get('NOSE_DEBUG')
+ self.debugLog = env.get('NOSE_DEBUG_LOG')
+ self.exclude = None
+ self.getTestCaseNamesCompat = False
+ self.includeExe = env.get('NOSE_INCLUDE_EXE',
+ sys.platform in exe_allowed_platforms)
+ self.ignoreFiles = (re.compile(r'^\.'),
+ re.compile(r'^_'),
+ re.compile(r'^setup\.py$')
+ )
+ self.include = None
+ self.loggingConfig = None
+ self.logStream = sys.stderr
+ self.options = NoOptions()
+ self.parser = None
+ self.plugins = NoPlugins()
+ self.srcDirs = ('lib', 'src')
+ self.runOnInit = True
+ self.stopOnError = env.get('NOSE_STOP', False)
+ self.stream = sys.stderr
+ self.testNames = ()
+ self.verbosity = int(env.get('NOSE_VERBOSE', 1))
+ self.where = ()
+ self.py3where = ()
+ self.workingDir = None
+ """
+
+ def __init__(self, **kw):
+ self.env = env = kw.pop('env', {})
+ self.args = ()
+ self.testMatchPat = env.get('NOSE_TESTMATCH',
+ r'(?:^|[\b_\.%s-])[Tt]est' % os.sep)
+ self.testMatch = re.compile(self.testMatchPat)
+ self.addPaths = not env.get('NOSE_NOPATH', False)
+ self.configSection = 'nosetests'
+ self.debug = env.get('NOSE_DEBUG')
+ self.debugLog = env.get('NOSE_DEBUG_LOG')
+ self.exclude = None
+ self.getTestCaseNamesCompat = False
+ self.includeExe = env.get('NOSE_INCLUDE_EXE',
+ sys.platform in exe_allowed_platforms)
+ self.ignoreFilesDefaultStrings = [r'^\.',
+ r'^_',
+ r'^setup\.py$',
+ ]
+ self.ignoreFiles = map(re.compile, self.ignoreFilesDefaultStrings)
+ self.include = None
+ self.loggingConfig = None
+ self.logStream = sys.stderr
+ self.options = NoOptions()
+ self.parser = None
+ self.plugins = NoPlugins()
+ self.srcDirs = ('lib', 'src')
+ self.runOnInit = True
+ self.stopOnError = env.get('NOSE_STOP', False)
+ self.stream = sys.stderr
+ self.testNames = []
+ self.verbosity = int(env.get('NOSE_VERBOSE', 1))
+ self.where = ()
+ self.py3where = ()
+ self.workingDir = os.getcwd()
+ self.traverseNamespace = False
+ self.firstPackageWins = False
+ self.parserClass = OptionParser
+ self.worker = False
+
+ self._default = self.__dict__.copy()
+ self.update(kw)
+ self._orig = self.__dict__.copy()
+
+ def __getstate__(self):
+ state = self.__dict__.copy()
+ del state['stream']
+ del state['_orig']
+ del state['_default']
+ del state['env']
+ del state['logStream']
+ # FIXME remove plugins, have only plugin manager class
+ state['plugins'] = self.plugins.__class__
+ return state
+
+ def __setstate__(self, state):
+ plugincls = state.pop('plugins')
+ self.update(state)
+ self.worker = True
+ # FIXME won't work for static plugin lists
+ self.plugins = plugincls()
+ self.plugins.loadPlugins()
+ # needed so .can_configure gets set appropriately
+ dummy_parser = self.parserClass()
+ self.plugins.addOptions(dummy_parser, {})
+ self.plugins.configure(self.options, self)
+
+ def __repr__(self):
+ d = self.__dict__.copy()
+ # don't expose env, could include sensitive info
+ d['env'] = {}
+ keys = [ k for k in d.keys()
+ if not k.startswith('_') ]
+ keys.sort()
+ return "Config(%s)" % ', '.join([ '%s=%r' % (k, d[k])
+ for k in keys ])
+ __str__ = __repr__
+
+ def _parseArgs(self, argv, cfg_files):
+ def warn_sometimes(msg, name=None, filename=None):
+ if (hasattr(self.plugins, 'excludedOption') and
+ self.plugins.excludedOption(name)):
+ msg = ("Option %r in config file %r ignored: "
+ "excluded by runtime environment" %
+ (name, filename))
+ warn(msg, RuntimeWarning)
+ else:
+ raise ConfigError(msg)
+ parser = ConfiguredDefaultsOptionParser(
+ self.getParser(), self.configSection, file_error=warn_sometimes)
+ return parser.parseArgsAndConfigFiles(argv[1:], cfg_files)
+
+ def configure(self, argv=None, doc=None):
+ """Configure the nose running environment. Execute configure before
+ collecting tests with nose.TestCollector to enable output capture and
+ other features.
+ """
+ env = self.env
+ if argv is None:
+ argv = sys.argv
+
+ cfg_files = getattr(self, 'files', [])
+ options, args = self._parseArgs(argv, cfg_files)
+ # If -c --config has been specified on command line,
+ # load those config files and reparse
+ if getattr(options, 'files', []):
+ options, args = self._parseArgs(argv, options.files)
+
+ self.options = options
+ if args:
+ self.testNames = args
+ if options.testNames is not None:
+ self.testNames.extend(tolist(options.testNames))
+
+ if options.py3where is not None:
+ if sys.version_info >= (3,):
+ options.where = options.py3where
+
+ # `where` is an append action, so it can't have a default value
+ # in the parser, or that default will always be in the list
+ if not options.where:
+ options.where = env.get('NOSE_WHERE', None)
+
+ # include and exclude also
+ if not options.ignoreFiles:
+ options.ignoreFiles = env.get('NOSE_IGNORE_FILES', [])
+ if not options.include:
+ options.include = env.get('NOSE_INCLUDE', [])
+ if not options.exclude:
+ options.exclude = env.get('NOSE_EXCLUDE', [])
+
+ self.addPaths = options.addPaths
+ self.stopOnError = options.stopOnError
+ self.verbosity = options.verbosity
+ self.includeExe = options.includeExe
+ self.traverseNamespace = options.traverseNamespace
+ self.debug = options.debug
+ self.debugLog = options.debugLog
+ self.loggingConfig = options.loggingConfig
+ self.firstPackageWins = options.firstPackageWins
+ self.configureLogging()
+
+ if options.where is not None:
+ self.configureWhere(options.where)
+
+ if options.testMatch:
+ self.testMatch = re.compile(options.testMatch)
+
+ if options.ignoreFiles:
+ self.ignoreFiles = map(re.compile, tolist(options.ignoreFiles))
+ log.info("Ignoring files matching %s", options.ignoreFiles)
+ else:
+ log.info("Ignoring files matching %s", self.ignoreFilesDefaultStrings)
+
+ if options.include:
+ self.include = map(re.compile, tolist(options.include))
+ log.info("Including tests matching %s", options.include)
+
+ if options.exclude:
+ self.exclude = map(re.compile, tolist(options.exclude))
+ log.info("Excluding tests matching %s", options.exclude)
+
+ # When listing plugins we don't want to run them
+ if not options.showPlugins:
+ self.plugins.configure(options, self)
+ self.plugins.begin()
+
+ def configureLogging(self):
+ """Configure logging for nose, or optionally other packages. Any logger
+ name may be set with the debug option, and that logger will be set to
+ debug level and be assigned the same handler as the nose loggers, unless
+ it already has a handler.
+ """
+ if self.loggingConfig:
+ from logging.config import fileConfig
+ fileConfig(self.loggingConfig)
+ return
+
+ format = logging.Formatter('%(name)s: %(levelname)s: %(message)s')
+ if self.debugLog:
+ handler = logging.FileHandler(self.debugLog)
+ else:
+ handler = logging.StreamHandler(self.logStream)
+ handler.setFormatter(format)
+
+ logger = logging.getLogger('nose')
+ logger.propagate = 0
+
+ # only add our default handler if there isn't already one there
+ # this avoids annoying duplicate log messages.
+ if handler not in logger.handlers:
+ logger.addHandler(handler)
+
+ # default level
+ lvl = logging.WARNING
+ if self.verbosity >= 5:
+ lvl = 0
+ elif self.verbosity >= 4:
+ lvl = logging.DEBUG
+ elif self.verbosity >= 3:
+ lvl = logging.INFO
+ logger.setLevel(lvl)
+
+ # individual overrides
+ if self.debug:
+ # no blanks
+ debug_loggers = [ name for name in self.debug.split(',')
+ if name ]
+ for logger_name in debug_loggers:
+ l = logging.getLogger(logger_name)
+ l.setLevel(logging.DEBUG)
+ if not l.handlers and not logger_name.startswith('nose'):
+ l.addHandler(handler)
+
+ def configureWhere(self, where):
+ """Configure the working directory or directories for the test run.
+ """
+ from nose.importer import add_path
+ self.workingDir = None
+ where = tolist(where)
+ warned = False
+ for path in where:
+ if not self.workingDir:
+ abs_path = absdir(path)
+ if abs_path is None:
+ raise ValueError("Working directory %s not found, or "
+ "not a directory" % path)
+ log.info("Set working dir to %s", abs_path)
+ self.workingDir = abs_path
+ if self.addPaths and \
+ os.path.exists(os.path.join(abs_path, '__init__.py')):
+ log.info("Working directory %s is a package; "
+ "adding to sys.path" % abs_path)
+ add_path(abs_path)
+ continue
+ if not warned:
+ warn("Use of multiple -w arguments is deprecated and "
+ "support may be removed in a future release. You can "
+ "get the same behavior by passing directories without "
+ "the -w argument on the command line, or by using the "
+ "--tests argument in a configuration file.",
+ DeprecationWarning)
+ self.testNames.append(path)
+
+ def default(self):
+ """Reset all config values to defaults.
+ """
+ self.__dict__.update(self._default)
+
+ def getParser(self, doc=None):
+ """Get the command line option parser.
+ """
+ if self.parser:
+ return self.parser
+ env = self.env
+ parser = self.parserClass(doc)
+ parser.add_option(
+ "-V","--version", action="store_true",
+ dest="version", default=False,
+ help="Output nose version and exit")
+ parser.add_option(
+ "-p", "--plugins", action="store_true",
+ dest="showPlugins", default=False,
+ help="Output list of available plugins and exit. Combine with "
+ "higher verbosity for greater detail")
+ parser.add_option(
+ "-v", "--verbose",
+ action="count", dest="verbosity",
+ default=self.verbosity,
+ help="Be more verbose. [NOSE_VERBOSE]")
+ parser.add_option(
+ "--verbosity", action="store", dest="verbosity",
+ metavar='VERBOSITY',
+ type="int", help="Set verbosity; --verbosity=2 is "
+ "the same as -v")
+ parser.add_option(
+ "-q", "--quiet", action="store_const", const=0, dest="verbosity",
+ help="Be less verbose")
+ parser.add_option(
+ "-c", "--config", action="append", dest="files",
+ metavar="FILES",
+ help="Load configuration from config file(s). May be specified "
+ "multiple times; in that case, all config files will be "
+ "loaded and combined")
+ parser.add_option(
+ "-w", "--where", action="append", dest="where",
+ metavar="WHERE",
+ help="Look for tests in this directory. "
+ "May be specified multiple times. The first directory passed "
+ "will be used as the working directory, in place of the current "
+ "working directory, which is the default. Others will be added "
+ "to the list of tests to execute. [NOSE_WHERE]"
+ )
+ parser.add_option(
+ "--py3where", action="append", dest="py3where",
+ metavar="PY3WHERE",
+ help="Look for tests in this directory under Python 3.x. "
+ "Functions the same as 'where', but only applies if running under "
+ "Python 3.x or above. Note that, if present under 3.x, this "
+ "option completely replaces any directories specified with "
+ "'where', so the 'where' option becomes ineffective. "
+ "[NOSE_PY3WHERE]"
+ )
+ parser.add_option(
+ "-m", "--match", "--testmatch", action="store",
+ dest="testMatch", metavar="REGEX",
+ help="Files, directories, function names, and class names "
+ "that match this regular expression are considered tests. "
+ "Default: %s [NOSE_TESTMATCH]" % self.testMatchPat,
+ default=self.testMatchPat)
+ parser.add_option(
+ "--tests", action="store", dest="testNames", default=None,
+ metavar='NAMES',
+ help="Run these tests (comma-separated list). This argument is "
+ "useful mainly from configuration files; on the command line, "
+ "just pass the tests to run as additional arguments with no "
+ "switch.")
+ parser.add_option(
+ "-l", "--debug", action="store",
+ dest="debug", default=self.debug,
+ help="Activate debug logging for one or more systems. "
+ "Available debug loggers: nose, nose.importer, "
+ "nose.inspector, nose.plugins, nose.result and "
+ "nose.selector. Separate multiple names with a comma.")
+ parser.add_option(
+ "--debug-log", dest="debugLog", action="store",
+ default=self.debugLog, metavar="FILE",
+ help="Log debug messages to this file "
+ "(default: sys.stderr)")
+ parser.add_option(
+ "--logging-config", "--log-config",
+ dest="loggingConfig", action="store",
+ default=self.loggingConfig, metavar="FILE",
+ help="Load logging config from this file -- bypasses all other"
+ " logging config settings.")
+ parser.add_option(
+ "-I", "--ignore-files", action="append", dest="ignoreFiles",
+ metavar="REGEX",
+ help="Completely ignore any file that matches this regular "
+ "expression. Takes precedence over any other settings or "
+ "plugins. "
+ "Specifying this option will replace the default setting. "
+ "Specify this option multiple times "
+ "to add more regular expressions [NOSE_IGNORE_FILES]")
+ parser.add_option(
+ "-e", "--exclude", action="append", dest="exclude",
+ metavar="REGEX",
+ help="Don't run tests that match regular "
+ "expression [NOSE_EXCLUDE]")
+ parser.add_option(
+ "-i", "--include", action="append", dest="include",
+ metavar="REGEX",
+ help="This regular expression will be applied to files, "
+ "directories, function names, and class names for a chance "
+ "to include additional tests that do not match TESTMATCH. "
+ "Specify this option multiple times "
+ "to add more regular expressions [NOSE_INCLUDE]")
+ parser.add_option(
+ "-x", "--stop", action="store_true", dest="stopOnError",
+ default=self.stopOnError,
+ help="Stop running tests after the first error or failure")
+ parser.add_option(
+ "-P", "--no-path-adjustment", action="store_false",
+ dest="addPaths",
+ default=self.addPaths,
+ help="Don't make any changes to sys.path when "
+ "loading tests [NOSE_NOPATH]")
+ parser.add_option(
+ "--exe", action="store_true", dest="includeExe",
+ default=self.includeExe,
+ help="Look for tests in python modules that are "
+ "executable. Normal behavior is to exclude executable "
+ "modules, since they may not be import-safe "
+ "[NOSE_INCLUDE_EXE]")
+ parser.add_option(
+ "--noexe", action="store_false", dest="includeExe",
+ help="DO NOT look for tests in python modules that are "
+ "executable. (The default on the windows platform is to "
+ "do so.)")
+ parser.add_option(
+ "--traverse-namespace", action="store_true",
+ default=self.traverseNamespace, dest="traverseNamespace",
+ help="Traverse through all path entries of a namespace package")
+ parser.add_option(
+ "--first-package-wins", "--first-pkg-wins", "--1st-pkg-wins",
+ action="store_true", default=False, dest="firstPackageWins",
+ help="nose's importer will normally evict a package from sys."
+ "modules if it sees a package with the same name in a different "
+ "location. Set this option to disable that behavior.")
+
+ self.plugins.loadPlugins()
+ self.pluginOpts(parser)
+
+ self.parser = parser
+ return parser
+
+ def help(self, doc=None):
+ """Return the generated help message
+ """
+ return self.getParser(doc).format_help()
+
+ def pluginOpts(self, parser):
+ self.plugins.addOptions(parser, self.env)
+
+ def reset(self):
+ self.__dict__.update(self._orig)
+
+ def todict(self):
+ return self.__dict__.copy()
+
+ def update(self, d):
+ self.__dict__.update(d)
+
+
+class NoOptions(object):
+ """Options container that returns None for all options.
+ """
+ def __getstate__(self):
+ return {}
+
+ def __setstate__(self, state):
+ pass
+
+ def __getnewargs__(self):
+ return ()
+
+ def __getattr__(self, attr):
+ return None
+
+ def __nonzero__(self):
+ return False
+
+
+def user_config_files():
+ """Return path to any existing user config files
+ """
+ return filter(os.path.exists,
+ map(os.path.expanduser, config_files))
+
+
+def all_config_files():
+ """Return path to any existing user config files, plus any setup.cfg
+ in the current working directory.
+ """
+ user = user_config_files()
+ if os.path.exists('setup.cfg'):
+ return user + ['setup.cfg']
+ return user
+
+
+# used when parsing config files
+def flag(val):
+ """Does the value look like an on/off flag?"""
+ if val == 1:
+ return True
+ elif val == 0:
+ return False
+ val = str(val)
+ if len(val) > 5:
+ return False
+ return val.upper() in ('1', '0', 'F', 'T', 'TRUE', 'FALSE', 'ON', 'OFF')
+
+
+def _bool(val):
+ return str(val).upper() in ('1', 'T', 'TRUE', 'ON')
diff --git a/nose/core.py b/nose/core.py
new file mode 100644
index 0000000..b78f232
--- /dev/null
+++ b/nose/core.py
@@ -0,0 +1,324 @@
+"""Implements nose test program and collector.
+"""
+from __future__ import generators
+
+import logging
+import os
+import sys
+import time
+import unittest
+
+from nose.config import Config, all_config_files
+from nose.loader import defaultTestLoader
+from nose.plugins.manager import PluginManager, DefaultPluginManager, \
+ RestrictedPluginManager
+from nose.result import TextTestResult
+from nose.suite import FinalizingSuiteWrapper
+from nose.util import isclass, tolist
+
+
+log = logging.getLogger('nose.core')
+compat_24 = sys.version_info >= (2, 4)
+
+__all__ = ['TestProgram', 'main', 'run', 'run_exit', 'runmodule', 'collector',
+ 'TextTestRunner']
+
+
+class TextTestRunner(unittest.TextTestRunner):
+ """Test runner that uses nose's TextTestResult to enable errorClasses,
+ as well as providing hooks for plugins to override or replace the test
+ output stream, results, and the test case itself.
+ """
+ def __init__(self, stream=sys.stderr, descriptions=1, verbosity=1,
+ config=None):
+ if config is None:
+ config = Config()
+ self.config = config
+ unittest.TextTestRunner.__init__(self, stream, descriptions, verbosity)
+
+
+ def _makeResult(self):
+ return TextTestResult(self.stream,
+ self.descriptions,
+ self.verbosity,
+ self.config)
+
+ def run(self, test):
+ """Overrides to provide plugin hooks and defer all output to
+ the test result class.
+ """
+ wrapper = self.config.plugins.prepareTest(test)
+ if wrapper is not None:
+ test = wrapper
+
+ # plugins can decorate or capture the output stream
+ wrapped = self.config.plugins.setOutputStream(self.stream)
+ if wrapped is not None:
+ self.stream = wrapped
+
+ result = self._makeResult()
+ start = time.time()
+ test(result)
+ stop = time.time()
+ result.printErrors()
+ result.printSummary(start, stop)
+ self.config.plugins.finalize(result)
+ return result
+
+
+class TestProgram(unittest.TestProgram):
+ """Collect and run tests, returning success or failure.
+
+ The arguments to TestProgram() are the same as to
+ :func:`main()` and :func:`run()`:
+
+ * module: All tests are in this module (default: None)
+ * defaultTest: Tests to load (default: '.')
+ * argv: Command line arguments (default: None; sys.argv is read)
+ * testRunner: Test runner instance (default: None)
+ * testLoader: Test loader instance (default: None)
+ * env: Environment; ignored if config is provided (default: None;
+ os.environ is read)
+ * config: :class:`nose.config.Config` instance (default: None)
+ * suite: Suite or list of tests to run (default: None). Passing a
+ suite or lists of tests will bypass all test discovery and
+ loading. *ALSO NOTE* that if you pass a unittest.TestSuite
+ instance as the suite, context fixtures at the class, module and
+ package level will not be used, and many plugin hooks will not
+ be called. If you want normal nose behavior, either pass a list
+ of tests, or a fully-configured :class:`nose.suite.ContextSuite`.
+ * exit: Exit after running tests and printing report (default: True)
+ * plugins: List of plugins to use; ignored if config is provided
+ (default: load plugins with DefaultPluginManager)
+ * addplugins: List of **extra** plugins to use. Pass a list of plugin
+ instances in this argument to make custom plugins available while
+ still using the DefaultPluginManager.
+ """
+ verbosity = 1
+
+ def __init__(self, module=None, defaultTest='.', argv=None,
+ testRunner=None, testLoader=None, env=None, config=None,
+ suite=None, exit=True, plugins=None, addplugins=None):
+ if env is None:
+ env = os.environ
+ if config is None:
+ config = self.makeConfig(env, plugins)
+ if addplugins:
+ config.plugins.addPlugins(extraplugins=addplugins)
+ self.config = config
+ self.suite = suite
+ self.exit = exit
+ extra_args = {}
+ version = sys.version_info[0:2]
+ if version >= (2,7) and version != (3,0):
+ extra_args['exit'] = exit
+ unittest.TestProgram.__init__(
+ self, module=module, defaultTest=defaultTest,
+ argv=argv, testRunner=testRunner, testLoader=testLoader,
+ **extra_args)
+
+ def makeConfig(self, env, plugins=None):
+ """Load a Config, pre-filled with user config files if any are
+ found.
+ """
+ cfg_files = all_config_files()
+ if plugins:
+ manager = PluginManager(plugins=plugins)
+ else:
+ manager = DefaultPluginManager()
+ return Config(
+ env=env, files=cfg_files, plugins=manager)
+
+ def parseArgs(self, argv):
+ """Parse argv and env and configure running environment.
+ """
+ self.config.configure(argv, doc=self.usage())
+ log.debug("configured %s", self.config)
+
+ # quick outs: version, plugins (optparse would have already
+ # caught and exited on help)
+ if self.config.options.version:
+ from nose import __version__
+ sys.stdout = sys.__stdout__
+ print "%s version %s" % (os.path.basename(sys.argv[0]), __version__)
+ sys.exit(0)
+
+ if self.config.options.showPlugins:
+ self.showPlugins()
+ sys.exit(0)
+
+ if self.testLoader is None:
+ self.testLoader = defaultTestLoader(config=self.config)
+ elif isclass(self.testLoader):
+ self.testLoader = self.testLoader(config=self.config)
+ plug_loader = self.config.plugins.prepareTestLoader(self.testLoader)
+ if plug_loader is not None:
+ self.testLoader = plug_loader
+ log.debug("test loader is %s", self.testLoader)
+
+ # FIXME if self.module is a string, add it to self.testNames? not sure
+
+ if self.config.testNames:
+ self.testNames = self.config.testNames
+ else:
+ self.testNames = tolist(self.defaultTest)
+ log.debug('defaultTest %s', self.defaultTest)
+ log.debug('Test names are %s', self.testNames)
+ if self.config.workingDir is not None:
+ os.chdir(self.config.workingDir)
+ self.createTests()
+
+ def createTests(self):
+ """Create the tests to run. If a self.suite
+ is set, then that suite will be used. Otherwise, tests will be
+ loaded from the given test names (self.testNames) using the
+ test loader.
+ """
+ log.debug("createTests called with %s", self.suite)
+ if self.suite is not None:
+ # We were given an explicit suite to run. Make sure it's
+ # loaded and wrapped correctly.
+ self.test = self.testLoader.suiteClass(self.suite)
+ else:
+ self.test = self.testLoader.loadTestsFromNames(self.testNames)
+
+ def runTests(self):
+ """Run Tests. Returns true on success, false on failure, and sets
+ self.success to the same value.
+ """
+ log.debug("runTests called")
+ if self.testRunner is None:
+ self.testRunner = TextTestRunner(stream=self.config.stream,
+ verbosity=self.config.verbosity,
+ config=self.config)
+ plug_runner = self.config.plugins.prepareTestRunner(self.testRunner)
+ if plug_runner is not None:
+ self.testRunner = plug_runner
+ result = self.testRunner.run(self.test)
+ self.success = result.wasSuccessful()
+ if self.exit:
+ sys.exit(not self.success)
+ return self.success
+
+ def showPlugins(self):
+ """Print list of available plugins.
+ """
+ import textwrap
+
+ class DummyParser:
+ def __init__(self):
+ self.options = []
+ def add_option(self, *arg, **kw):
+ self.options.append((arg, kw.pop('help', '')))
+
+ v = self.config.verbosity
+ self.config.plugins.sort()
+ for p in self.config.plugins:
+ print "Plugin %s" % p.name
+ if v >= 2:
+ print " score: %s" % p.score
+ print '\n'.join(textwrap.wrap(p.help().strip(),
+ initial_indent=' ',
+ subsequent_indent=' '))
+ if v >= 3:
+ parser = DummyParser()
+ p.addOptions(parser)
+ if len(parser.options):
+ print
+ print " Options:"
+ for opts, help in parser.options:
+ print ' %s' % (', '.join(opts))
+ if help:
+ print '\n'.join(
+ textwrap.wrap(help.strip(),
+ initial_indent=' ',
+ subsequent_indent=' '))
+ print
+
+ def usage(cls):
+ import nose
+ if hasattr(nose, '__loader__'):
+ ld = nose.__loader__
+ if hasattr(ld, 'zipfile'):
+ # nose was imported from a zipfile
+ return ld.get_data(
+ os.path.join(ld.prefix, 'nose', 'usage.txt'))
+ return open(os.path.join(
+ os.path.dirname(__file__), 'usage.txt'), 'r').read()
+ usage = classmethod(usage)
+
+# backwards compatibility
+run_exit = main = TestProgram
+
+
+def run(*arg, **kw):
+ """Collect and run tests, returning success or failure.
+
+ The arguments to `run()` are the same as to `main()`:
+
+ * module: All tests are in this module (default: None)
+ * defaultTest: Tests to load (default: '.')
+ * argv: Command line arguments (default: None; sys.argv is read)
+ * testRunner: Test runner instance (default: None)
+ * testLoader: Test loader instance (default: None)
+ * env: Environment; ignored if config is provided (default: None;
+ os.environ is read)
+ * config: :class:`nose.config.Config` instance (default: None)
+ * suite: Suite or list of tests to run (default: None). Passing a
+ suite or lists of tests will bypass all test discovery and
+ loading. *ALSO NOTE* that if you pass a unittest.TestSuite
+ instance as the suite, context fixtures at the class, module and
+ package level will not be used, and many plugin hooks will not
+ be called. If you want normal nose behavior, either pass a list
+ of tests, or a fully-configured :class:`nose.suite.ContextSuite`.
+ * plugins: List of plugins to use; ignored if config is provided
+ (default: load plugins with DefaultPluginManager)
+ * addplugins: List of **extra** plugins to use. Pass a list of plugin
+ instances in this argument to make custom plugins available while
+ still using the DefaultPluginManager.
+
+ With the exception that the ``exit`` argument is always set
+ to False.
+ """
+ kw['exit'] = False
+ return TestProgram(*arg, **kw).success
+
+
+def runmodule(name='__main__', **kw):
+ """Collect and run tests in a single module only. Defaults to running
+ tests in __main__. Additional arguments to TestProgram may be passed
+ as keyword arguments.
+ """
+ main(defaultTest=name, **kw)
+
+
+def collector():
+ """TestSuite replacement entry point. Use anywhere you might use a
+ unittest.TestSuite. The collector will, by default, load options from
+ all config files and execute loader.loadTestsFromNames() on the
+ configured testNames, or '.' if no testNames are configured.
+ """
+ # plugins that implement any of these methods are disabled, since
+ # we don't control the test runner and won't be able to run them
+ # finalize() is also not called, but plugins that use it aren't disabled,
+ # because capture needs it.
+ setuptools_incompat = ('report', 'prepareTest',
+ 'prepareTestLoader', 'prepareTestRunner',
+ 'setOutputStream')
+
+ plugins = RestrictedPluginManager(exclude=setuptools_incompat)
+ conf = Config(files=all_config_files(),
+ plugins=plugins)
+ conf.configure(argv=['collector'])
+ loader = defaultTestLoader(conf)
+
+ if conf.testNames:
+ suite = loader.loadTestsFromNames(conf.testNames)
+ else:
+ suite = loader.loadTestsFromNames(('.',))
+ return FinalizingSuiteWrapper(suite, plugins.finalize)
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/nose/exc.py b/nose/exc.py
new file mode 100644
index 0000000..8b780db
--- /dev/null
+++ b/nose/exc.py
@@ -0,0 +1,9 @@
+"""Exceptions for marking tests as skipped or deprecated.
+
+This module exists to provide backwards compatibility with previous
+versions of nose where skipped and deprecated tests were core
+functionality, rather than being provided by plugins. It may be
+removed in a future release.
+"""
+from nose.plugins.skip import SkipTest
+from nose.plugins.deprecated import DeprecatedTest
diff --git a/nose/ext/__init__.py b/nose/ext/__init__.py
new file mode 100644
index 0000000..5fd1516
--- /dev/null
+++ b/nose/ext/__init__.py
@@ -0,0 +1,3 @@
+"""
+External or vendor files
+"""
diff --git a/nose/ext/dtcompat.py b/nose/ext/dtcompat.py
new file mode 100644
index 0000000..332cf08
--- /dev/null
+++ b/nose/ext/dtcompat.py
@@ -0,0 +1,2272 @@
+# Module doctest.
+# Released to the public domain 16-Jan-2001, by Tim Peters (tim@python.org).
+# Major enhancements and refactoring by:
+# Jim Fulton
+# Edward Loper
+
+# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
+#
+# Modified for inclusion in nose to provide support for DocFileTest in
+# python 2.3:
+#
+# - all doctests removed from module (they fail under 2.3 and 2.5)
+# - now handles the $py.class extension when ran under Jython
+
+r"""Module doctest -- a framework for running examples in docstrings.
+
+In simplest use, end each module M to be tested with:
+
+def _test():
+ import doctest
+ doctest.testmod()
+
+if __name__ == "__main__":
+ _test()
+
+Then running the module as a script will cause the examples in the
+docstrings to get executed and verified:
+
+python M.py
+
+This won't display anything unless an example fails, in which case the
+failing example(s) and the cause(s) of the failure(s) are printed to stdout
+(why not stderr? because stderr is a lame hack <0.2 wink>), and the final
+line of output is "Test failed.".
+
+Run it with the -v switch instead:
+
+python M.py -v
+
+and a detailed report of all examples tried is printed to stdout, along
+with assorted summaries at the end.
+
+You can force verbose mode by passing "verbose=True" to testmod, or prohibit
+it by passing "verbose=False". In either of those cases, sys.argv is not
+examined by testmod.
+
+There are a variety of other ways to run doctests, including integration
+with the unittest framework, and support for running non-Python text
+files containing doctests. There are also many ways to override parts
+of doctest's default behaviors. See the Library Reference Manual for
+details.
+"""
+
+__docformat__ = 'reStructuredText en'
+
+__all__ = [
+ # 0, Option Flags
+ 'register_optionflag',
+ 'DONT_ACCEPT_TRUE_FOR_1',
+ 'DONT_ACCEPT_BLANKLINE',
+ 'NORMALIZE_WHITESPACE',
+ 'ELLIPSIS',
+ 'IGNORE_EXCEPTION_DETAIL',
+ 'COMPARISON_FLAGS',
+ 'REPORT_UDIFF',
+ 'REPORT_CDIFF',
+ 'REPORT_NDIFF',
+ 'REPORT_ONLY_FIRST_FAILURE',
+ 'REPORTING_FLAGS',
+ # 1. Utility Functions
+ 'is_private',
+ # 2. Example & DocTest
+ 'Example',
+ 'DocTest',
+ # 3. Doctest Parser
+ 'DocTestParser',
+ # 4. Doctest Finder
+ 'DocTestFinder',
+ # 5. Doctest Runner
+ 'DocTestRunner',
+ 'OutputChecker',
+ 'DocTestFailure',
+ 'UnexpectedException',
+ 'DebugRunner',
+ # 6. Test Functions
+ 'testmod',
+ 'testfile',
+ 'run_docstring_examples',
+ # 7. Tester
+ 'Tester',
+ # 8. Unittest Support
+ 'DocTestSuite',
+ 'DocFileSuite',
+ 'set_unittest_reportflags',
+ # 9. Debugging Support
+ 'script_from_examples',
+ 'testsource',
+ 'debug_src',
+ 'debug',
+]
+
+import __future__
+
+import sys, traceback, inspect, linecache, os, re
+import unittest, difflib, pdb, tempfile
+import warnings
+from StringIO import StringIO
+
+# Don't whine about the deprecated is_private function in this
+# module's tests.
+warnings.filterwarnings("ignore", "is_private", DeprecationWarning,
+ __name__, 0)
+
+# There are 4 basic classes:
+# - Example: a