From e0e9dc173237bc56815e30e0c7d3de0d79b46f82 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= <miro@hroncok.cz>
Date: Wed, 18 Oct 2023 13:01:21 +0200
Subject: [PATCH] Run 2to3 on the code base and docs

    $ 2to3 --write --nobackups --no-diffs .
    $ 2to3 --write --nobackups --no-diffs -d $(find -name '*.rst')

    $ rpm -qf /usr/bin/2to3
    python3-devel-3.11.6-1.fc37.x86_64
---
 distribute_setup.py                           |  2 +-
 doc/conf.py                                   |  8 +-
 doc/docstring.py                              |  2 +-
 examples/attrib_plugin.py                     | 12 +--
 .../test_init_plugin/init_plugin.rst          |  3 +-
 .../test_issue097/plugintest_environment.rst  | 13 +--
 .../test_issue107/plugin_exceptions.rst       |  5 +-
 .../doc_tests/test_issue119/empty_plugin.rst  | 15 +--
 .../doc_tests/test_issue119/test_zeronine.py  |  2 +-
 .../test_issue145/imported_tests.rst          |  3 +-
 .../support/package1/__init__.py              |  2 +-
 .../support/package2c/__init__.py             |  2 +-
 .../support/package2f/__init__.py             |  2 +-
 .../support/test_can_split.py                 |  4 +-
 .../support/test_not_shared.py                |  4 +-
 .../test_multiprocess/support/test_shared.py  |  4 +-
 .../restricted_plugin_options.rst             |  3 +-
 .../test_selector_plugin/selector_plugin.rst  |  3 +-
 functional_tests/support/coverage/blah.py     |  4 +-
 functional_tests/support/coverage2/blah.py    |  4 +-
 functional_tests/support/coverage2/moo.py     |  2 +-
 functional_tests/support/fdp/test_fdp.py      |  2 +-
 functional_tests/support/gen/test.py          |  2 +-
 functional_tests/support/ipt/test1/ipthelp.py |  4 +-
 functional_tests/support/ipt/test1/tests.py   |  4 +-
 functional_tests/support/ipt/test2/ipthelp.py |  4 +-
 functional_tests/support/ipt/test2/tests.py   |  4 +-
 functional_tests/support/issue072/test.py     |  2 +-
 functional_tests/support/issue134/test.py     |  2 +-
 functional_tests/support/issue649/test.py     |  2 +-
 functional_tests/support/issue680/test.py     |  2 +-
 functional_tests/support/issue720/test.py     |  2 +-
 .../support/package2/test_pak/__init__.py     |  2 +-
 .../support/package2/test_pak/test_mod.py     |  8 +-
 .../support/xunit/test_xunit_as_suite.py      |  2 +-
 functional_tests/test_attribute_plugin.py     |  6 +-
 functional_tests/test_buggy_generators.py     |  4 +-
 functional_tests/test_collector.py            |  2 +-
 functional_tests/test_commands.py             |  6 +-
 functional_tests/test_coverage_plugin.py      |  2 +-
 functional_tests/test_doctest_plugin.py       |  4 +-
 functional_tests/test_failure.py              | 10 +-
 functional_tests/test_failuredetail_plugin.py | 18 ++--
 functional_tests/test_generator_fixtures.py   |  8 +-
 functional_tests/test_id_plugin.py            | 36 +++----
 functional_tests/test_importer.py             |  4 +-
 functional_tests/test_isolate_plugin.py       |  4 +-
 functional_tests/test_issue_072.py            | 20 ++--
 functional_tests/test_issue_082.py            |  8 +-
 functional_tests/test_issue_649.py            |  2 +-
 .../test_load_tests_from_test_case.py         |  8 +-
 functional_tests/test_loader.py               | 44 ++++-----
 .../support/fake_nosetest.py                  |  2 +-
 .../test_keyboardinterrupt.py                 | 20 ++--
 .../test_multiprocessing/test_nameerror.py    |  2 +-
 functional_tests/test_namespace_pkg.py        |  2 +-
 functional_tests/test_plugin_api.py           |  6 +-
 functional_tests/test_plugins.py              |  4 +-
 functional_tests/test_plugintest.py           |  2 +-
 functional_tests/test_program.py              | 20 ++--
 functional_tests/test_result.py               |  6 +-
 functional_tests/test_string_exception.py     | 10 +-
 functional_tests/test_success.py              |  4 +-
 functional_tests/test_suite.py                |  2 +-
 functional_tests/test_xunit.py                | 24 ++---
 nose/case.py                                  |  2 +-
 nose/commands.py                              |  2 +-
 nose/config.py                                | 36 +++----
 nose/core.py                                  | 24 ++---
 nose/ext/dtcompat.py                          | 80 +++++++--------
 nose/failure.py                               |  4 +-
 nose/inspector.py                             |  6 +-
 nose/loader.py                                | 11 +--
 nose/plugins/attrib.py                        |  4 +-
 nose/plugins/base.py                          |  2 +-
 nose/plugins/capture.py                       | 18 ++--
 nose/plugins/cover.py                         | 12 +--
 nose/plugins/doctests.py                      | 29 +++---
 nose/plugins/errorclass.py                    |  7 +-
 nose/plugins/isolate.py                       |  2 +-
 nose/plugins/logcapture.py                    | 10 +-
 nose/plugins/manager.py                       |  8 +-
 nose/plugins/multiprocess.py                  | 16 +--
 nose/plugins/plugintest.py                    |  8 +-
 nose/plugins/testid.py                        |  4 +-
 nose/plugins/xunit.py                         | 28 +++---
 nose/pyversion.py                             | 18 ++--
 nose/result.py                                | 10 +-
 nose/selector.py                              | 10 +-
 nose/suite.py                                 |  8 +-
 nose/tools/nontrivial.py                      |  2 +-
 nose/twistedtools.py                          |  4 +-
 nose/util.py                                  | 16 +--
 patch.py                                      |  4 +-
 unit_tests/mock.py                            | 16 +--
 unit_tests/support/issue135/tests.py          |  2 +-
 unit_tests/support/script.py                  |  2 +-
 unit_tests/test_bug105.py                     |  8 +-
 unit_tests/test_capture_plugin.py             | 14 +--
 unit_tests/test_cases.py                      |  9 +-
 unit_tests/test_config_defaults.rst           | 11 ++-
 unit_tests/test_core.py                       | 10 +-
 unit_tests/test_deprecated_plugin.py          |  4 +-
 unit_tests/test_doctest_munging.rst           | 25 ++---
 unit_tests/test_id_plugin.py                  |  2 +-
 unit_tests/test_inspector.py                  | 12 +--
 unit_tests/test_issue135.py                   |  2 +-
 unit_tests/test_issue155.rst                  |  9 +-
 unit_tests/test_issue_006.py                  | 10 +-
 unit_tests/test_issue_227.py                  |  2 +-
 unit_tests/test_issue_230.py                  |  2 +-
 unit_tests/test_loader.py                     | 97 +++++++++----------
 unit_tests/test_logcapture_plugin.py          | 10 +-
 unit_tests/test_ls_tree.rst                   |  5 +-
 unit_tests/test_multiprocess_runner.py        | 12 +--
 unit_tests/test_pdb_plugin.py                 |  2 +-
 unit_tests/test_plugin_manager.py             |  2 +-
 unit_tests/test_plugins.py                    | 16 +--
 unit_tests/test_result_proxy.py               |  8 +-
 unit_tests/test_selector.py                   |  4 +-
 unit_tests/test_skip_plugin.py                |  6 +-
 unit_tests/test_suite.py                      | 12 +--
 unit_tests/test_tools.py                      | 16 +--
 unit_tests/test_twisted.py                    |  2 +-
 unit_tests/test_utils.py                      | 11 +--
 unit_tests/test_xunit.py                      | 16 +--
 126 files changed, 587 insertions(+), 588 deletions(-)

diff --git a/distribute_setup.py b/distribute_setup.py
index a447f7e..8d13a7e 100644
--- a/distribute_setup.py
+++ b/distribute_setup.py
@@ -190,7 +190,7 @@ def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
     try:
         from urllib.request import urlopen
     except ImportError:
-        from urllib2 import urlopen
+        from urllib.request import urlopen
     tgz_name = "distribute-%s.tar.gz" % version
     url = download_base + tgz_name
     saveto = os.path.join(to_dir, tgz_name)
diff --git a/doc/conf.py b/doc/conf.py
index 34ea147..f2c2e4f 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -49,8 +49,8 @@ source_suffix = '.rst'
 master_doc = 'index'
 
 # General information about the project.
-project = u'nose'
-copyright = u'2009, Jason Pellerin'
+project = 'nose'
+copyright = '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
@@ -213,8 +213,8 @@ html_theme = 'default'
 # 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'),
+  ('index', 'nose.tex', r'nose Documentation',
+   r'Jason Pellerin', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
diff --git a/doc/docstring.py b/doc/docstring.py
index 5652bd2..af9ef15 100644
--- a/doc/docstring.py
+++ b/doc/docstring.py
@@ -9,7 +9,7 @@ def docstring_directive(dirname, arguments, options, content, lineno,
     obj = resolve_name(obj_name)
     rst = ViewList()
     rst.append(obj.__doc__, '<docstring>')
-    print "CALLED", obj_name, obj, rst
+    print("CALLED", obj_name, obj, rst)
     node = nodes.section()
     surrounding_title_styles = state.memo.title_styles
     surrounding_section_level = state.memo.section_level
diff --git a/examples/attrib_plugin.py b/examples/attrib_plugin.py
index c1f8458..7c94111 100644
--- a/examples/attrib_plugin.py
+++ b/examples/attrib_plugin.py
@@ -41,7 +41,7 @@ def attr(**kwargs):
 # test function with single attribute
 @attr(priority = 1)
 def test_dummy():
-    print "dummy"
+    print("dummy")
     
 # test function with multiple attributes
 @attr(status = "stable",              # simple string attribute
@@ -51,11 +51,11 @@ def test_dummy():
       tags = ["http", "pop", "imap"]) # will be run if any of the list items
                                       #   matches
 def test_foobar():
-    print "foobar"
+    print("foobar")
 
 # another way of adding attributes...
 def test_fluffy():
-    print "fluffy"
+    print("fluffy")
 test_fluffy.status = "unstable"
 test_fluffy.slow = True
 test_fluffy.priority = 2
@@ -64,7 +64,7 @@ test_fluffy.priority = 2
 class TestSomething:
     @attr(status = "stable", priority = 2)
     def test_xyz(self):
-        print "xyz"
+        print("xyz")
 
 # class methods "inherit" attributes from the class but can override them
 class TestOverride:
@@ -74,9 +74,9 @@ class TestOverride:
     @attr(value = "method")
     def test_override(self):
         # run with "nosetests -a value=method"
-        print "override"
+        print("override")
     
     def test_inherit(self):
         # run with "nosetests -a value=class"
-        print "inherit"
+        print("inherit")
     
diff --git a/functional_tests/doc_tests/test_init_plugin/init_plugin.rst b/functional_tests/doc_tests/test_init_plugin/init_plugin.rst
index d89bfa4..bdc3fd2 100644
--- a/functional_tests/doc_tests/test_init_plugin/init_plugin.rst
+++ b/functional_tests/doc_tests/test_init_plugin/init_plugin.rst
@@ -130,7 +130,7 @@ specify a configuration file on the command line:
     ...     def begin(self):
     ...         ConfigurableWidget.cfg = self.cfg
     ...     def load_config(self, path):
-    ...         from ConfigParser import ConfigParser
+    ...         from configparser import ConfigParser
     ...         p = ConfigParser()
     ...         p.read([path])
     ...         self.cfg = dict(p.items('DEFAULT'))
@@ -164,3 +164,4 @@ resetting the widget system to an unconfigured state.
 
 .. _Pylons: http://pylonshq.com/
 .. _Django: http://www.djangoproject.com/
+
diff --git a/functional_tests/doc_tests/test_issue097/plugintest_environment.rst b/functional_tests/doc_tests/test_issue097/plugintest_environment.rst
index 99b37cf..5cb9f4f 100644
--- a/functional_tests/doc_tests/test_issue097/plugintest_environment.rst
+++ b/functional_tests/doc_tests/test_issue097/plugintest_environment.rst
@@ -20,16 +20,16 @@ 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
+    ...         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
@@ -37,9 +37,9 @@ 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
+    ...         print("argv:", argv)
     ...         old_config.configure(self, argv, doc)
     >>> nose.config.Config = PrintArgvConfig
 
@@ -52,7 +52,7 @@ subclassing.
     ...               FailureDetail(),
     ...               Capture(),
     ...               ]
-    ...
+    ... 
     ...    def makeSuite(self):
     ...        return unittest.TestSuite(tests=[])
 
@@ -158,3 +158,4 @@ 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
index 2c595f0..2a2e775 100644
--- a/functional_tests/doc_tests/test_issue107/plugin_exceptions.rst
+++ b/functional_tests/doc_tests/test_issue107/plugin_exceptions.rst
@@ -19,9 +19,9 @@ 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={}):
@@ -147,3 +147,4 @@ following test would crash nose:
     Ran 1 test in ...s
     <BLANKLINE>
     FAILED (errors=1)
+
diff --git a/functional_tests/doc_tests/test_issue119/empty_plugin.rst b/functional_tests/doc_tests/test_issue119/empty_plugin.rst
index 6194c19..8a82e15 100644
--- a/functional_tests/doc_tests/test_issue119/empty_plugin.rst
+++ b/functional_tests/doc_tests/test_issue119/empty_plugin.rst
@@ -6,14 +6,14 @@ 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
@@ -31,19 +31,19 @@ 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
@@ -55,3 +55,4 @@ Enabled plugin that's otherwise empty
     Ran 0 tests in ...s
     <BLANKLINE>
     OK
+
diff --git a/functional_tests/doc_tests/test_issue119/test_zeronine.py b/functional_tests/doc_tests/test_issue119/test_zeronine.py
index 6a4f450..5c09c13 100644
--- a/functional_tests/doc_tests/test_issue119/test_zeronine.py
+++ b/functional_tests/doc_tests/test_issue119/test_zeronine.py
@@ -18,7 +18,7 @@ class TestEmptyPlugin(PluginTester, unittest.TestCase):
     suitepath = os.path.join(here, 'empty_plugin.rst')
 
     def test_empty_zero_nine_does_not_crash(self):
-        print self.output
+        print(self.output)
         assert "'EmptyPlugin' object has no attribute 'loadTestsFromPath'" \
             not in self.output
 
diff --git a/functional_tests/doc_tests/test_issue145/imported_tests.rst b/functional_tests/doc_tests/test_issue145/imported_tests.rst
index caad752..87113e3 100644
--- a/functional_tests/doc_tests/test_issue145/imported_tests.rst
+++ b/functional_tests/doc_tests/test_issue145/imported_tests.rst
@@ -11,7 +11,7 @@ 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
+    >>> print(ls_tree(support)) # doctest: +REPORT_NDIFF
     |-- package1
     |   |-- __init__.py
     |   `-- test_module.py
@@ -115,3 +115,4 @@ command-line.
     Ran 1 test in ...s
     <BLANKLINE>
     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
index c715fdb..18aef31 100644
--- a/functional_tests/doc_tests/test_issue145/support/package1/__init__.py
+++ b/functional_tests/doc_tests/test_issue145/support/package1/__init__.py
@@ -1,2 +1,2 @@
 def setup():
-    print 'package1 setup'
+    print('package1 setup')
diff --git a/functional_tests/doc_tests/test_issue145/support/package2c/__init__.py b/functional_tests/doc_tests/test_issue145/support/package2c/__init__.py
index 106401f..0162765 100644
--- a/functional_tests/doc_tests/test_issue145/support/package2c/__init__.py
+++ b/functional_tests/doc_tests/test_issue145/support/package2c/__init__.py
@@ -1,2 +1,2 @@
 def setup():
-    print 'package2c setup'
+    print('package2c setup')
diff --git a/functional_tests/doc_tests/test_issue145/support/package2f/__init__.py b/functional_tests/doc_tests/test_issue145/support/package2f/__init__.py
index fc203eb..d8886da 100644
--- a/functional_tests/doc_tests/test_issue145/support/package2f/__init__.py
+++ b/functional_tests/doc_tests/test_issue145/support/package2f/__init__.py
@@ -1,2 +1,2 @@
 def setup():
-    print 'package2f setup'
+    print('package2f setup')
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
index a7ae6e7..08bb9e3 100644
--- a/functional_tests/doc_tests/test_multiprocess/support/test_can_split.py
+++ b/functional_tests/doc_tests/test_multiprocess/support/test_can_split.py
@@ -4,12 +4,12 @@ called = []
 _multiprocess_can_split_ = 1
 
 def setup():
-    print >> sys.stderr, "setup called"
+    print("setup called", file=sys.stderr)
     called.append('setup')
 
 
 def teardown():
-    print >> sys.stderr, "teardown called"
+    print("teardown called", file=sys.stderr)
     called.append('teardown')
 
 
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
index 8542109..03016dd 100644
--- a/functional_tests/doc_tests/test_multiprocess/support/test_not_shared.py
+++ b/functional_tests/doc_tests/test_multiprocess/support/test_not_shared.py
@@ -4,12 +4,12 @@ called = []
 _multiprocess_ = 1
 
 def setup():
-    print >> sys.stderr, "setup called"
+    print("setup called", file=sys.stderr)
     called.append('setup')
 
 
 def teardown():
-    print >> sys.stderr, "teardown called"
+    print("teardown called", file=sys.stderr)
     called.append('teardown')
 
 
diff --git a/functional_tests/doc_tests/test_multiprocess/support/test_shared.py b/functional_tests/doc_tests/test_multiprocess/support/test_shared.py
index d798aac..b847751 100644
--- a/functional_tests/doc_tests/test_multiprocess/support/test_shared.py
+++ b/functional_tests/doc_tests/test_multiprocess/support/test_shared.py
@@ -28,12 +28,12 @@ def logged():
 
 
 def setup():
-    print >> sys.stderr, "setup called"
+    print("setup called", file=sys.stderr)
     _log('setup')
 
 
 def teardown():
-    print >> sys.stderr, "teardown called"
+    print("teardown called", file=sys.stderr)
     _clear()
 
 
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
index 6a08eaf..53609cb 100644
--- 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
@@ -18,7 +18,7 @@ method.
     >>> from nose.plugins.manager import RestrictedPluginManager
     >>> class StartPlugin(Plugin):
     ...     def startTest(self, test):
-    ...         print "started %s" % test
+    ...         print("started %s" % test)
 
 .. Note ::
 
@@ -87,3 +87,4 @@ error is raised.
     Traceback (most recent call last):
     ...
     SystemExit: 2
+
diff --git a/functional_tests/doc_tests/test_selector_plugin/selector_plugin.rst b/functional_tests/doc_tests/test_selector_plugin/selector_plugin.rst
index 5463cf1..b7b7acb 100644
--- a/functional_tests/doc_tests/test_selector_plugin/selector_plugin.rst
+++ b/functional_tests/doc_tests/test_selector_plugin/selector_plugin.rst
@@ -19,7 +19,7 @@ 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)
+    >>> print(ls_tree(support))
     |-- mymodule.py
     |-- mypackage
     |   |-- __init__.py
@@ -117,3 +117,4 @@ project's tests will be collected.
     Ran 4 tests in ...s
     <BLANKLINE>
     OK
+
diff --git a/functional_tests/support/coverage/blah.py b/functional_tests/support/coverage/blah.py
index ef6657c..721a2b1 100644
--- a/functional_tests/support/coverage/blah.py
+++ b/functional_tests/support/coverage/blah.py
@@ -1,6 +1,6 @@
 def dostuff():
-    print 'hi'
+    print('hi')
 
 
 def notcov():
-    print 'not covered'
+    print('not covered')
diff --git a/functional_tests/support/coverage2/blah.py b/functional_tests/support/coverage2/blah.py
index ef6657c..721a2b1 100644
--- a/functional_tests/support/coverage2/blah.py
+++ b/functional_tests/support/coverage2/blah.py
@@ -1,6 +1,6 @@
 def dostuff():
-    print 'hi'
+    print('hi')
 
 
 def notcov():
-    print 'not covered'
+    print('not covered')
diff --git a/functional_tests/support/coverage2/moo.py b/functional_tests/support/coverage2/moo.py
index 7ad09bf..2e3d4ce 100644
--- a/functional_tests/support/coverage2/moo.py
+++ b/functional_tests/support/coverage2/moo.py
@@ -1,2 +1,2 @@
 def moo():
-    print 'covered'
+    print('covered')
diff --git a/functional_tests/support/fdp/test_fdp.py b/functional_tests/support/fdp/test_fdp.py
index bcaab0d..61d7778 100644
--- a/functional_tests/support/fdp/test_fdp.py
+++ b/functional_tests/support/fdp/test_fdp.py
@@ -2,7 +2,7 @@ def test_err():
     raise TypeError("I can't type")
 
 def test_fail():
-    print "Hello"
+    print("Hello")
     a = 2
     assert a == 4, "a is not 4"
 
diff --git a/functional_tests/support/gen/test.py b/functional_tests/support/gen/test.py
index 13a0c3e..5d6dc62 100644
--- a/functional_tests/support/gen/test.py
+++ b/functional_tests/support/gen/test.py
@@ -7,6 +7,6 @@ def test1():
     def func(_l, _n):
         eq_(len(_l), _n)
     l = []
-    for i in xrange(5):
+    for i in range(5):
         yield func, l, i
         l.append(None)
diff --git a/functional_tests/support/ipt/test1/ipthelp.py b/functional_tests/support/ipt/test1/ipthelp.py
index fdbe2e4..e7020cf 100644
--- a/functional_tests/support/ipt/test1/ipthelp.py
+++ b/functional_tests/support/ipt/test1/ipthelp.py
@@ -1,4 +1,4 @@
-print "1help imported"
+print("1help imported")
 def help():
-    print "1help called"
+    print("1help called")
     pass
diff --git a/functional_tests/support/ipt/test1/tests.py b/functional_tests/support/ipt/test1/tests.py
index a9595f7..fe9592e 100644
--- a/functional_tests/support/ipt/test1/tests.py
+++ b/functional_tests/support/ipt/test1/tests.py
@@ -1,7 +1,7 @@
 import sys
-print 'ipthelp', sys.modules.get('ipthelp')
+print('ipthelp', sys.modules.get('ipthelp'))
 import ipthelp
-print ipthelp
+print(ipthelp)
 
 def test1():
     ipthelp.help()
diff --git a/functional_tests/support/ipt/test2/ipthelp.py b/functional_tests/support/ipt/test2/ipthelp.py
index cafd917..3731981 100644
--- a/functional_tests/support/ipt/test2/ipthelp.py
+++ b/functional_tests/support/ipt/test2/ipthelp.py
@@ -1,5 +1,5 @@
-print "2help imported"
+print("2help imported")
 
 def help(a):
-    print "2 help %s" % 1
+    print("2 help %s" % 1)
     pass
diff --git a/functional_tests/support/ipt/test2/tests.py b/functional_tests/support/ipt/test2/tests.py
index 1c95896..875a0c7 100644
--- a/functional_tests/support/ipt/test2/tests.py
+++ b/functional_tests/support/ipt/test2/tests.py
@@ -1,8 +1,8 @@
 import sys
 
-print 'ipthelp', sys.modules.get('ipthelp')
+print('ipthelp', sys.modules.get('ipthelp'))
 import ipthelp
-print ipthelp
+print(ipthelp)
 
 def test2():
     ipthelp.help(1)
diff --git a/functional_tests/support/issue072/test.py b/functional_tests/support/issue072/test.py
index 2aab0bd..d9f49e2 100644
--- a/functional_tests/support/issue072/test.py
+++ b/functional_tests/support/issue072/test.py
@@ -1,4 +1,4 @@
 def test():
-    print "something"
+    print("something")
     a = 4
     assert a == 2
diff --git a/functional_tests/support/issue134/test.py b/functional_tests/support/issue134/test.py
index 78e1e22..f2da19d 100644
--- a/functional_tests/support/issue134/test.py
+++ b/functional_tests/support/issue134/test.py
@@ -1,3 +1,3 @@
 def test():
-    print "something"
+    print("something")
     raise IOError(42, "test")
diff --git a/functional_tests/support/issue649/test.py b/functional_tests/support/issue649/test.py
index ebc6f91..51b07c7 100644
--- a/functional_tests/support/issue649/test.py
+++ b/functional_tests/support/issue649/test.py
@@ -5,5 +5,5 @@ import unittest
 class TestUnicodeInAssertion(unittest.TestCase):
 
     def test_unicodeInAssertion(self):
-        print "Wurst!"
+        print("Wurst!")
         raise ValueError("Käse!")
diff --git a/functional_tests/support/issue680/test.py b/functional_tests/support/issue680/test.py
index d0d43b4..def96da 100644
--- a/functional_tests/support/issue680/test.py
+++ b/functional_tests/support/issue680/test.py
@@ -1,3 +1,3 @@
 # coding: utf-8
 def test_foo():
-    print(u"abc€")
+    print("abc€")
diff --git a/functional_tests/support/issue720/test.py b/functional_tests/support/issue720/test.py
index 0a194fd..4a0df53 100644
--- a/functional_tests/support/issue720/test.py
+++ b/functional_tests/support/issue720/test.py
@@ -2,5 +2,5 @@
 import unittest
 class Test(unittest.TestCase):
     def test(self):
-        print u"Unicöde"
+        print("Unicöde")
         assert 1 == 2
diff --git a/functional_tests/support/package2/test_pak/__init__.py b/functional_tests/support/package2/test_pak/__init__.py
index b65d6c0..9cc0374 100644
--- a/functional_tests/support/package2/test_pak/__init__.py
+++ b/functional_tests/support/package2/test_pak/__init__.py
@@ -1,4 +1,4 @@
-print "*** test_pak imported"
+print("*** test_pak imported")
 state = []
 
 def setup():
diff --git a/functional_tests/support/package2/test_pak/test_mod.py b/functional_tests/support/package2/test_pak/test_mod.py
index 09dc9e5..cd46c97 100644
--- a/functional_tests/support/package2/test_pak/test_mod.py
+++ b/functional_tests/support/package2/test_pak/test_mod.py
@@ -1,14 +1,14 @@
-print "test_mod imported!"
+print("test_mod imported!")
 
 import maths
 from test_pak import state
 
 def setup():
-    print "MOD setup called", state, id(state)
+    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)
+    print("MOD.test_add called", state, id(state))
     state.append('test_pak.test_mod.test_add')
     assert maths.add(1, 2) == 3
 
@@ -16,5 +16,5 @@ def test_minus():
     state.append('test_pak.test_mod.test_minus')
     
 def teardown():
-    print "MOD teardown called", state, id(state)
+    print("MOD teardown called", state, id(state))
     state.append('test_pak.test_mod.teardown')
diff --git a/functional_tests/support/xunit/test_xunit_as_suite.py b/functional_tests/support/xunit/test_xunit_as_suite.py
index ec256b5..9109907 100644
--- a/functional_tests/support/xunit/test_xunit_as_suite.py
+++ b/functional_tests/support/xunit/test_xunit_as_suite.py
@@ -15,7 +15,7 @@ class TestForXunit(unittest.TestCase):
         raise TypeError("oops, wrong type")
     
     def test_non_ascii_error(self):
-        raise Exception(u"日本")
+        raise Exception("日本")
     
     def test_output(self):
         sys.stdout.write("test-generated output\n")
diff --git a/functional_tests/test_attribute_plugin.py b/functional_tests/test_attribute_plugin.py
index df2cfd3..406ace8 100644
--- a/functional_tests/test_attribute_plugin.py
+++ b/functional_tests/test_attribute_plugin.py
@@ -17,9 +17,9 @@ class AttributePluginTester(PluginTester, unittest.TestCase):
     activate = '-v'
 
     def runTest(self):
-        print '*' * 70
-        print str(self.output)
-        print '*' * 70
+        print('*' * 70)
+        print(str(self.output))
+        print('*' * 70)
         self.verify()
 
     def verify(self):
diff --git a/functional_tests/test_buggy_generators.py b/functional_tests/test_buggy_generators.py
index 9e6e168..4ce70af 100644
--- a/functional_tests/test_buggy_generators.py
+++ b/functional_tests/test_buggy_generators.py
@@ -1,6 +1,6 @@
 import os
 import unittest
-from cStringIO import StringIO
+from io import StringIO
 from nose.core import TestProgram
 from nose.config import Config
 from nose.result import _TextTestResult
@@ -27,7 +27,7 @@ class TestBuggyGenerators(unittest.TestCase):
             config=Config(),
             exit=False)
         res = runner.result
-        print stream.getvalue()
+        print(stream.getvalue())
         self.assertEqual(res.testsRun, 12,
                          "Expected to run 12 tests, ran %s" % res.testsRun)
         assert not res.wasSuccessful()
diff --git a/functional_tests/test_collector.py b/functional_tests/test_collector.py
index c3b9dca..5739eaf 100644
--- a/functional_tests/test_collector.py
+++ b/functional_tests/test_collector.py
@@ -2,7 +2,7 @@ import os
 import sys
 import unittest
 import warnings
-from cStringIO import StringIO
+from io import StringIO
 from nose.result import _TextTestResult
 here = os.path.dirname(__file__)
 support = os.path.join(here, 'support')
diff --git a/functional_tests/test_commands.py b/functional_tests/test_commands.py
index 682af04..9323e26 100644
--- a/functional_tests/test_commands.py
+++ b/functional_tests/test_commands.py
@@ -3,7 +3,7 @@ import sys
 import unittest
 from nose.plugins.skip import SkipTest
 from nose import commands
-from StringIO import StringIO
+from io import StringIO
 
 support = os.path.join(
     os.path.dirname(__file__), 'support', 'issue191')
@@ -32,12 +32,12 @@ class TestCommands(unittest.TestCase):
                                 'package_dir': {'issue191': support}}))
         cmd.finalize_options()
         ## FIXME why doesn't Config see the chdir above?
-        print cmd._nosetests__config.workingDir
+        print(cmd._nosetests__config.workingDir)
         cmd._nosetests__config.workingDir = support
         cmd._nosetests__config.stream = buf
         try:
             cmd.run()
-        except SystemExit, e:
+        except SystemExit as e:
             self.assertFalse(e.args[0], buf.getvalue())
         else:
             self.fail("cmd.run() did not exit")
diff --git a/functional_tests/test_coverage_plugin.py b/functional_tests/test_coverage_plugin.py
index eb465e8..dbe7268 100644
--- a/functional_tests/test_coverage_plugin.py
+++ b/functional_tests/test_coverage_plugin.py
@@ -40,7 +40,7 @@ class TestCoveragePlugin(PluginTester, unittest.TestCase):
         super(TestCoveragePlugin, self).setUp()
 
     def runTest(self):
-        print(self.output)
+        print((self.output))
         self.assertTrue(
                 # Coverage < 4.0
                 ("blah        4      3    25%   1" in self.output) or
diff --git a/functional_tests/test_doctest_plugin.py b/functional_tests/test_doctest_plugin.py
index c91ecc5..441fffd 100644
--- a/functional_tests/test_doctest_plugin.py
+++ b/functional_tests/test_doctest_plugin.py
@@ -12,7 +12,7 @@ class TestDoctestPlugin(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'dtt')
     
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
         
         assert 'Doctest: some_mod ... ok' in self.output
         assert 'Doctest: some_mod.foo ... ok' in self.output
@@ -27,7 +27,7 @@ class TestDoctestFiles(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'dtt', 'docs')
     
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
 
         expect = [
             'Doctest: doc.txt ... ok',
diff --git a/functional_tests/test_failure.py b/functional_tests/test_failure.py
index e9d17e9..93ca0b4 100644
--- a/functional_tests/test_failure.py
+++ b/functional_tests/test_failure.py
@@ -15,11 +15,11 @@ class TestPrintedTraceback(PluginTester, unittest.TestCase):
         return None
 
     def test_correct_exception_raised(self):
-        print
-        print '!' * 70
-        print str(self.output)
-        print '!' * 70
-        print
+        print()
+        print('!' * 70)
+        print(str(self.output))
+        print('!' * 70)
+        print()
 
         # Look for the line in the traceback causing the failure
         assert "raise '\\xf1'.encode('ASCII')" in str(self.output)
diff --git a/functional_tests/test_failuredetail_plugin.py b/functional_tests/test_failuredetail_plugin.py
index 8484461..847c415 100644
--- a/functional_tests/test_failuredetail_plugin.py
+++ b/functional_tests/test_failuredetail_plugin.py
@@ -14,9 +14,9 @@ class TestFailureDetail(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'fdp')
 
     def runTest(self):
-        print '*' * 70
-        print str(self.output)
-        print '*' * 70
+        print('*' * 70)
+        print(str(self.output))
+        print('*' * 70)
 
         expect = \
         'AssertionError: a is not 4\n'
@@ -34,9 +34,9 @@ class TestFailureDetailWithCapture(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'fdp/test_fdp_no_capt.py')
 
     def runTest(self):
-        print '*' * 70
-        print str(self.output)
-        print '*' * 70
+        print('*' * 70)
+        print(str(self.output))
+        print('*' * 70)
 
         expect = \
         'AssertionError: a is not 4\n'
@@ -53,9 +53,9 @@ class TestFailureDetailWithUnicodeAndCapture(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'issue720')
 
     def runTest(self):
-        print '*' * 70
-        print str(self.output)
-        print '*' * 70
+        print('*' * 70)
+        print(str(self.output))
+        print('*' * 70)
 
         assert 'UnicodeDecodeError' not in self.output
         assert 'UnicodeEncodeError' not in self.output
diff --git a/functional_tests/test_generator_fixtures.py b/functional_tests/test_generator_fixtures.py
index 3240141..8d357a3 100644
--- a/functional_tests/test_generator_fixtures.py
+++ b/functional_tests/test_generator_fixtures.py
@@ -35,21 +35,21 @@ check.teardown = inner_teardown
 
 class TestClass(object):
     def setup(self):
-        print "setup called in", self
+        print("setup called in", self)
         self.called = ['setup']
 
     def teardown(self):
-        print "teardown called in", self
+        print("teardown called in", self)
         eq_(self.called, ['setup'])
         self.called.append('teardown')
 
     def test(self):
-        print "test called in", 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
+        print("check called in", self)
         expect = ['setup']
         #for x in range(0, i):
         #    expect.append('setup')
diff --git a/functional_tests/test_id_plugin.py b/functional_tests/test_id_plugin.py
index 7b3d39d..6ffc1c0 100644
--- a/functional_tests/test_id_plugin.py
+++ b/functional_tests/test_id_plugin.py
@@ -7,7 +7,7 @@ import unittest
 from nose.plugins import PluginTester
 from nose.plugins.builtin import Doctest
 from nose.plugins.builtin import TestId
-from cPickle import dump, load
+from pickle import dump, load
 
 support = os.path.join(os.path.dirname(__file__), 'support')
 idfile = tempfile.mktemp()
@@ -49,9 +49,9 @@ class TestDiscoveryMode(PluginTester, unittest.TestCase):
         ids = load(fh)['ids']
         fh.close()
         assert ids
-        assert ids.keys()
-        self.assertEqual(map(int, ids.keys()), ids.keys())
-        assert ids.values()
+        assert list(ids.keys())
+        self.assertEqual(list(map(int, list(ids.keys()))), list(ids.keys()))
+        assert list(ids.values())
 
 
 class TestLoadNamesMode(PluginTester, unittest.TestCase):
@@ -81,10 +81,10 @@ class TestLoadNamesMode(PluginTester, unittest.TestCase):
         ids = load(fh)
         fh.close()
         assert ids
-        assert ids.keys()
+        assert list(ids.keys())
         ids = ids['ids']
-        self.assertEqual(filter(lambda i: int(i), ids.keys()), ids.keys())
-        assert len(ids.keys()) > 2
+        self.assertEqual([i for i in list(ids.keys()) if int(i)], list(ids.keys()))
+        assert len(list(ids.keys())) > 2
 
 
 class TestLoadNamesMode_2(PluginTester, unittest.TestCase):
@@ -142,7 +142,7 @@ class TestWithDoctest_1(PluginTester, unittest.TestCase):
         fh = open(idfile, 'rb')
         ids = load(fh)['ids']
         fh.close()
-        for key, (file, mod, call) in ids.items():
+        for key, (file, mod, call) in list(ids.items()):
             assert mod != 'doctest', \
                    "Doctest test was incorrectly identified as being part of "\
                    "the doctest module itself (#%s)" % key
@@ -166,9 +166,9 @@ class TestWithDoctest_2(PluginTester, unittest.TestCase):
         return None
 
     def test_load_ids_doctest(self):
-        print '*' * 70
-        print str(self.output)
-        print '*' * 70
+        print('*' * 70)
+        print(str(self.output))
+        print('*' * 70)
 
         assert 'Doctest: exm.add_one ... FAIL' in self.output
         
@@ -188,9 +188,9 @@ class TestWithDoctestFileTests_1(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'dtt', 'docs')
 
     def test_docfile_tests_get_ids(self):
-        print '>' * 70
-        print str(self.output)
-        print '>' * 70
+        print('>' * 70)
+        print(str(self.output))
+        print('>' * 70)
 
         last = None
         for line in self.output:
@@ -209,7 +209,7 @@ class TestWithDoctestFileTests_1(PluginTester, unittest.TestCase):
         fh = open(idfile, 'rb')
         ids = load(fh)['ids']
         fh.close()
-        for key, (file, mod, call) in ids.items():
+        for key, (file, mod, call) in list(ids.items()):
             assert mod != 'doctest', \
                    "Doctest test was incorrectly identified as being part of "\
                    "the doctest module itself (#%s)" % key    
@@ -234,9 +234,9 @@ class TestWithDoctestFileTests_2(PluginTester, unittest.TestCase):
         return None
 
     def test_load_from_name_id_docfile_test(self):
-        print '*' * 70
-        print str(self.output)
-        print '*' * 70
+        print('*' * 70)
+        print(str(self.output))
+        print('*' * 70)
 
         assert 'Doctest: errdoc.txt ... FAIL' in self.output
         
diff --git a/functional_tests/test_importer.py b/functional_tests/test_importer.py
index 20fb15d..297bd05 100644
--- a/functional_tests/test_importer.py
+++ b/functional_tests/test_importer.py
@@ -27,7 +27,7 @@ class TestImporter(unittest.TestCase):
             self.has_symlinks = True
 
     def tearDown(self):
-        to_del = [ m for m in sys.modules.keys() if
+        to_del = [ m for m in list(sys.modules.keys()) if
                    m not in self._mods ]
         if to_del:
             for mod in to_del:
@@ -115,7 +115,7 @@ class TestImporter(unittest.TestCase):
         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)
+        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"
diff --git a/functional_tests/test_isolate_plugin.py b/functional_tests/test_isolate_plugin.py
index 087dcaa..30b71ae 100644
--- a/functional_tests/test_isolate_plugin.py
+++ b/functional_tests/test_isolate_plugin.py
@@ -13,7 +13,7 @@ class TestDiscovery(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'ipt')
     
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
 
         for line in self.output:
             if not line.strip():
@@ -43,7 +43,7 @@ class TestLoadFromNames(PluginTester, unittest.TestCase):
         return None
     
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
 
         for line in self.output:
             if not line.strip():
diff --git a/functional_tests/test_issue_072.py b/functional_tests/test_issue_072.py
index 3848f6f..9e400f8 100644
--- a/functional_tests/test_issue_072.py
+++ b/functional_tests/test_issue_072.py
@@ -15,11 +15,11 @@ class TestFailureDetailWorks(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'issue072')
 
     def test_assert_info_in_output(self):
-        print
-        print '!' * 70
-        print str(self.output)
-        print '!' * 70
-        print
+        print()
+        print('!' * 70)
+        print(str(self.output))
+        print('!' * 70)
+        print()
         assert '>>  assert 4 == 2' in str(self.output)
 
 class TestFailureDetailWorksWhenChained(PluginTester, unittest.TestCase):
@@ -30,11 +30,11 @@ class TestFailureDetailWorksWhenChained(PluginTester, unittest.TestCase):
 
     def test_assert_info_and_capt_stdout_in_output(self):
         out = str(self.output)
-        print
-        print 'x' * 70
-        print out
-        print 'x' * 70
-        print
+        print()
+        print('x' * 70)
+        print(out)
+        print('x' * 70)
+        print()
         
         assert '>>  assert 4 == 2' in out, \
                "Assert info not found in chained output"
diff --git a/functional_tests/test_issue_082.py b/functional_tests/test_issue_082.py
index 06fa019..4f7ca11 100644
--- a/functional_tests/test_issue_082.py
+++ b/functional_tests/test_issue_082.py
@@ -1,9 +1,9 @@
 import os
 import re
 try:
-    from cStringIO import StringIO
+    from io import StringIO
 except ImportError:
-    from StringIO import StringIO
+    from io import StringIO
 import sys
 import unittest
 
@@ -47,7 +47,7 @@ class TestIncludeUnderscoreFiles(PluginTester, unittest.TestCase):
                    )
 
     def test_assert_info_in_output(self):
-        print self.output
+        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)
@@ -63,7 +63,7 @@ class TestExcludeUnderscoreFilesByDefault(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'issue082')
 
     def test_assert_info_in_output(self):
-        print self.output
+        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)
diff --git a/functional_tests/test_issue_649.py b/functional_tests/test_issue_649.py
index 74e516e..2182014 100644
--- a/functional_tests/test_issue_649.py
+++ b/functional_tests/test_issue_649.py
@@ -14,5 +14,5 @@ class TestIssue649(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'issue649')
 
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
         assert 'UnicodeDecodeError' not in self.output
diff --git a/functional_tests/test_load_tests_from_test_case.py b/functional_tests/test_load_tests_from_test_case.py
index 934d43b..830e2af 100644
--- a/functional_tests/test_load_tests_from_test_case.py
+++ b/functional_tests/test_load_tests_from_test_case.py
@@ -16,15 +16,15 @@ class NoFixturePlug(Plugin):
     enabled = True
 
     def options(self, parser, env):
-        print "options"        
+        print("options")        
         pass
     
     def configure(self, options, conf):
-        print "configure"
+        print("configure")
         pass
 
     def loadTestsFromTestCase(self, testCaseClass):
-        print "Called!"
+        print("Called!")
         class Derived(testCaseClass):
             def setUp(self):
                 pass
@@ -53,7 +53,7 @@ class TestLoadTestsFromTestCaseHook(PluginTester, unittest.TestCase):
             expect = [
                 'test_value (%s.Derived) ... ERROR' % __name__,
                 'test_value (tests.Tests) ... ok']
-        print str(self.output)
+        print(str(self.output))
         for line in self.output:
             if expect:
                 self.assertEqual(line.strip(), expect.pop(0))
diff --git a/functional_tests/test_loader.py b/functional_tests/test_loader.py
index 3f82122..cdd0f99 100644
--- a/functional_tests/test_loader.py
+++ b/functional_tests/test_loader.py
@@ -2,7 +2,7 @@ import os
 import sys
 import unittest
 from difflib import ndiff
-from cStringIO import StringIO
+from io import StringIO
 
 from nose.config import Config
 from nose.plugins.manager import PluginManager
@@ -25,7 +25,7 @@ class TestNoseTestLoader(unittest.TestCase):
         suite.ContextSuiteFactory.suiteClass = TreePrintContextSuite
 
     def tearDown(self):
-        to_del = [ m for m in sys.modules.keys() if
+        to_del = [ m for m in list(sys.modules.keys()) if
                    m not in self._mods ]
         if to_del:
             for mod in to_del:
@@ -71,7 +71,7 @@ class TestNoseTestLoader(unittest.TestCase):
         dir_suite(res)
 
         m = sys.modules['test_pak']
-        print "test pak state", m.state
+        print("test pak state", m.state)
 
         assert not res.errors, res.errors
         assert not res.failures, res.failures
@@ -112,7 +112,7 @@ class TestNoseTestLoader(unittest.TestCase):
         assert 'test_pak' in sys.modules, \
                "Context did not load test_pak"
         m = sys.modules['test_pak']
-        print "test pak state", m.state
+        print("test pak state", m.state)
         expect = ['test_pak.setup',
                   'test_pak.test_mod.setup',
                   'test_pak.test_mod.test_add',
@@ -133,7 +133,7 @@ class TestNoseTestLoader(unittest.TestCase):
         assert 'test_pak' in sys.modules, \
                "Context did not load test_pak"
         m = sys.modules['test_pak']
-        print "test pak state", m.state
+        print("test pak state", m.state)
         expect = ['test_pak.setup',
                   'test_pak.test_mod.setup',
                   'test_pak.test_mod.test_add',
@@ -182,7 +182,7 @@ class TestNoseTestLoader(unittest.TestCase):
         assert 'test_pak' in sys.modules, \
                "Context not load test_pak"
         m = sys.modules['test_pak']
-        print "test pak state", m.state
+        print("test pak state", m.state)
         expect = ['test_pak.setup',
                   'test_pak.test_sub.setup',
                   'test_pak.test_sub.test_mod.setup',
@@ -204,14 +204,14 @@ class TestNoseTestLoader(unittest.TestCase):
             ['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
+        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
+        print("test pak state", m.state)
         expect = ['test_pak.setup',
                   'test_pak.test_sub.setup',
                   'test_pak.test_sub.test_mod.setup',
@@ -240,16 +240,16 @@ class TestNoseTestLoader(unittest.TestCase):
             ['test_pak1.test_mod',
              'test_pak2:test_two_two',
              'test_pak1:test_one_one'])
-        print suite
+        print(suite)
         suite(res)
         res.printErrors()
-        print stream.getvalue()
+        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
+        print("state", m.called)
 
         expect = ['test_pak1.setup',
                   'test_pak1.test_mod.setup',
@@ -271,16 +271,16 @@ class TestNoseTestLoader(unittest.TestCase):
             ['test_pak1.test_mod',
              'test_pak2:test_two_two',
              'test_mod'])
-        print suite
+        print(suite)
         suite(res)
         res.printErrors()
-        print stream.getvalue()
+        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
+        print("state", m.called)
 
         expect = ['test_pak1.setup',
                   'test_pak1.test_mod.setup',
@@ -348,7 +348,7 @@ class TestNoseTestLoader(unittest.TestCase):
             descriptions=0, verbosity=1)
         suite(res)
 
-        print res.errors
+        print(res.errors)
         res.printErrors()
         assert res.errors, "Expected errors but got none"
         assert not res.failures, res.failures
@@ -364,7 +364,7 @@ class TestNoseTestLoader(unittest.TestCase):
             stream=_WritelnDecorator(sys.stdout),
             descriptions=0, verbosity=1)
         suite(res)
-        print res.errors
+        print(res.errors)
         res.printErrors()
         assert res.errors, "Expected errors but got none"
         assert not res.failures, res.failures
@@ -381,7 +381,7 @@ class TestNoseTestLoader(unittest.TestCase):
             stream=_WritelnDecorator(sys.stdout),
             descriptions=0, verbosity=1)
         suite(res)
-        print res.errors
+        print(res.errors)
         assert res.errors, "Expected errors but got none"
         assert not res.failures, res.failures
 
@@ -412,7 +412,7 @@ class TestNoseTestLoader(unittest.TestCase):
             stream=_WritelnDecorator(sys.stdout),
             descriptions=0, verbosity=1)
         suite(res)
-        print res.errors
+        print(res.errors)
         self.assertEqual(len(res.errors), 1)
         assert 'raise Exception("pow")' in res.errors[0][1]
 
@@ -426,7 +426,7 @@ class TestNoseTestLoader(unittest.TestCase):
         assert 'test_pak' in sys.modules, \
                "Context did not load test_pak"
         m = sys.modules['test_pak']
-        print "test pak state", m.state
+        print("test pak state", m.state)
         expect = ['test_pak.setup',
                   'test_pak.test_sub.setup',
                   'test_pak.test_sub.test_sub_init',
@@ -447,7 +447,7 @@ class TestNoseTestLoader(unittest.TestCase):
         assert 'test_pak' in sys.modules, \
                "Context did not load test_pak"
         m = sys.modules['test_pak']
-        print "test pak state", m.state
+        print("test pak state", m.state)
         expect = ['test_pak.setup',
                   'test_pak.test_sub.setup',
                   'test_pak.test_sub.test_sub_init',
@@ -480,7 +480,7 @@ class TreePrintContextSuite(suite.ContextSuite):
     indent = ''
 
     def setUp(self):
-        print self, 'setup -->'
+        print(self, 'setup -->')
         suite.ContextSuite.setUp(self)
         TreePrintContextSuite.indent += '  '
 
@@ -489,7 +489,7 @@ class TreePrintContextSuite(suite.ContextSuite):
         try:
             suite.ContextSuite.tearDown(self)
         finally:
-            print self, 'teardown <--'
+            print(self, 'teardown <--')
     def __repr__(self):
         
         return '%s<%s>' % (self.indent,
diff --git a/functional_tests/test_multiprocessing/support/fake_nosetest.py b/functional_tests/test_multiprocessing/support/fake_nosetest.py
index 8319da8..65e7db5 100644
--- a/functional_tests/test_multiprocessing/support/fake_nosetest.py
+++ b/functional_tests/test_multiprocessing/support/fake_nosetest.py
@@ -8,7 +8,7 @@ from nose.plugins.manager import PluginManager
 
 if __name__ == '__main__':
     if len(sys.argv) < 3:
-        print "USAGE: %s TEST_FILE LOG_FILE KILL_FILE" % sys.argv[0]
+        print("USAGE: %s TEST_FILE LOG_FILE KILL_FILE" % sys.argv[0])
         sys.exit(1)
     os.environ['NOSE_MP_LOG']=sys.argv[2]
     os.environ['NOSE_MP_KILL']=sys.argv[3]
diff --git a/functional_tests/test_multiprocessing/test_keyboardinterrupt.py b/functional_tests/test_multiprocessing/test_keyboardinterrupt.py
index 18c8af1..d62fcc3 100644
--- a/functional_tests/test_multiprocessing/test_keyboardinterrupt.py
+++ b/functional_tests/test_multiprocessing/test_keyboardinterrupt.py
@@ -66,11 +66,11 @@ def test_keyboardinterrupt():
     process, logfile, _ = keyboardinterrupt('keyboardinterrupt.py')
     stdout, stderr = [s.decode('utf-8') for s in process.communicate(None)]
     log = get_log_content(logfile)
-    print stderr
-    print '----'
-    print stdout
-    print '----'
-    print log
+    print(stderr)
+    print('----')
+    print(stdout)
+    print('----')
+    print(log)
     assert 'setup' in log
     assert 'test_timeout' in log
     assert 'test_timeout_finished' not in log
@@ -88,11 +88,11 @@ def test_keyboardinterrupt_twice():
     os.killpg(process.pid, signal.SIGINT)
     stdout, stderr = [s.decode('utf-8') for s in process.communicate(None)]
     log = get_log_content(logfile)
-    print stderr
-    print '----'
-    print stdout
-    print '----'
-    print log
+    print(stderr)
+    print('----')
+    print(stdout)
+    print('----')
+    print(log)
     assert 'setup' in log
     assert 'test_timeout' in log
     assert 'test_timeout_finished' not in log
diff --git a/functional_tests/test_multiprocessing/test_nameerror.py b/functional_tests/test_multiprocessing/test_nameerror.py
index 5e58226..75c22b7 100644
--- a/functional_tests/test_multiprocessing/test_nameerror.py
+++ b/functional_tests/test_multiprocessing/test_nameerror.py
@@ -7,7 +7,7 @@ class TestMPNameError(MPTestBase):
     suitepath = os.path.join(os.path.dirname(__file__), 'support', 'nameerror.py')
 
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
         assert 'NameError' in self.output
         assert "'undefined_variable' is not defined" in self.output
 
diff --git a/functional_tests/test_namespace_pkg.py b/functional_tests/test_namespace_pkg.py
index 2db051e..a4d3ae3 100644
--- a/functional_tests/test_namespace_pkg.py
+++ b/functional_tests/test_namespace_pkg.py
@@ -1,7 +1,7 @@
 import os
 import sys
 import unittest
-from cStringIO import StringIO
+from io import StringIO
 from nose.core import TestProgram
 from test_program import TestRunner
 
diff --git a/functional_tests/test_plugin_api.py b/functional_tests/test_plugin_api.py
index c508ded..8e64d39 100644
--- a/functional_tests/test_plugin_api.py
+++ b/functional_tests/test_plugin_api.py
@@ -31,9 +31,9 @@ class TestPrepareTestCase_MakeAllFail(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'package2')
     
     def runTest(self):
-        print "x" * 70
-        print str(self.output)
-        print "x" * 70
+        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'), \
diff --git a/functional_tests/test_plugins.py b/functional_tests/test_plugins.py
index eff6c7a..debe2a6 100644
--- a/functional_tests/test_plugins.py
+++ b/functional_tests/test_plugins.py
@@ -23,7 +23,7 @@ class TestPluginCalls(unittest.TestCase):
         conf = Config(plugins=man, stream=sys.stdout)
         t = TestProgram(defaultTest=wdir, config=conf,
                         argv=['test_plugin_calls_package1'], exit=False)
-        print man.calls()
+        print(man.calls())
         assert man.called
 
         self.assertEqual(
@@ -47,7 +47,7 @@ class TestPluginCalls(unittest.TestCase):
         conf = Config(plugins=man, stream=sys.stdout)
         t = TestProgram(defaultTest=wdir, config=conf,
                         argv=['test_plugin_calls_package1', '-v'], exit=False)
-        print man.calls()
+        print(man.calls())
         assert man.called
 
         self.assertEqual(
diff --git a/functional_tests/test_plugintest.py b/functional_tests/test_plugintest.py
index 7d1a65b..a680cd9 100644
--- a/functional_tests/test_plugintest.py
+++ b/functional_tests/test_plugintest.py
@@ -2,7 +2,7 @@
 import unittest, os
 from nose.plugins import PluginTester, Plugin
 from nose.tools import eq_
-from cStringIO import StringIO
+from io import StringIO
 
 class StubPlugin(Plugin):
     def options(self, parser, env=os.environ):
diff --git a/functional_tests/test_program.py b/functional_tests/test_program.py
index 27c245f..3b29065 100644
--- a/functional_tests/test_program.py
+++ b/functional_tests/test_program.py
@@ -1,6 +1,6 @@
 import os
 import unittest
-from cStringIO import StringIO
+from io import StringIO
 from nose import SkipTest
 from nose.core import TestProgram
 from nose.config import Config
@@ -35,7 +35,7 @@ class TestTestProgram(unittest.TestCase):
                            config=Config(),
                            exit=False)
         res = runner.result
-        print stream.getvalue()
+        print(stream.getvalue())
         self.assertEqual(res.testsRun, 0,
                          "Expected to run 0 tests, ran %s" % res.testsRun)
         assert res.wasSuccessful()
@@ -55,7 +55,7 @@ class TestTestProgram(unittest.TestCase):
                            config=Config(),
                            exit=False)
         res = runner.result
-        print stream.getvalue()
+        print(stream.getvalue())
         self.assertEqual(res.testsRun, 6,
                          "Expected to run 6 tests, ran %s" % res.testsRun)
         assert res.wasSuccessful()
@@ -84,7 +84,7 @@ class TestTestProgram(unittest.TestCase):
                            config=Config(),
                            exit=False)
         res = runner.result
-        print stream.getvalue()
+        print(stream.getvalue())
         self.assertEqual(res.testsRun, 2,
                          "Expected to run 2 tests, ran %s" % res.testsRun)
         assert res.wasSuccessful()
@@ -109,9 +109,9 @@ class TestTestProgram(unittest.TestCase):
                            config=Config(stream=stream),
                            exit=False)
         res = runner.result
-        print stream.getvalue()
-        print "-----"
-        print repr(res)
+        print(stream.getvalue())
+        print("-----")
+        print(repr(res))
 
         self.assertEqual(res.testsRun, 4,
                          "Expected to run 4 tests, ran %s" % (res.testsRun,))
@@ -147,7 +147,7 @@ class TestTestProgram(unittest.TestCase):
                                          plugins=DefaultPluginManager()),
                            exit=False)
         res = runner.result
-        print stream.getvalue()
+        print(stream.getvalue())
         self.assertEqual(res.testsRun, 0) # error is in setup
         assert not res.wasSuccessful()
         assert res.errors
@@ -164,7 +164,7 @@ class TestTestProgram(unittest.TestCase):
                            config=Config(),
                            exit=False)
         res = runner.result
-        print stream.getvalue()
+        print(stream.getvalue())
         self.assertEqual(res.testsRun, 8)
 
     def test_illegal_packages_not_selected(self):
@@ -178,7 +178,7 @@ class TestTestProgram(unittest.TestCase):
                                          plugins=DefaultPluginManager()),
                            exit=False)
         res = runner.result
-        print stream.getvalue()
+        print(stream.getvalue())
         self.assertEqual(res.testsRun, 0)
         assert res.wasSuccessful()
         assert not res.errors
diff --git a/functional_tests/test_result.py b/functional_tests/test_result.py
index 7206020..4ef2167 100644
--- a/functional_tests/test_result.py
+++ b/functional_tests/test_result.py
@@ -1,7 +1,7 @@
 import os
 import sys
 import unittest
-from cStringIO import StringIO
+from io import StringIO
 from nose.config import Config
 from nose.core import TestProgram
 from nose.plugins.manager import PluginManager
@@ -23,8 +23,8 @@ class TestResultSummary(unittest.TestCase):
         TestProgram(argv=['t', '--with-todo', pkpath],
                     config=config, exit=False)
         out = stream.getvalue()
-        print out
-        self.assert_('FAILED (TODO=1)' in out)
+        print(out)
+        self.assertTrue('FAILED (TODO=1)' in out)
 
 
 if __name__ == '__main__':
diff --git a/functional_tests/test_string_exception.py b/functional_tests/test_string_exception.py
index 396c92a..5dbf1f5 100644
--- a/functional_tests/test_string_exception.py
+++ b/functional_tests/test_string_exception.py
@@ -21,11 +21,11 @@ class TestStringException(PluginTester, unittest.TestCase):
             raise SkipTest("String exceptions are not supported in this "
                            "version of Python")
 
-        print
-        print '!' * 70
-        print str(self.output)
-        print '!' * 70
-        print
+        print()
+        print('!' * 70)
+        print(str(self.output))
+        print('!' * 70)
+        print()
         assert 'raise "string exception"' in str(self.output)
         assert 'raise "string exception in setup"' in str(self.output)
         assert 'raise "string exception in teardown"' in str(self.output)
diff --git a/functional_tests/test_success.py b/functional_tests/test_success.py
index 760a7d1..badfd68 100644
--- a/functional_tests/test_success.py
+++ b/functional_tests/test_success.py
@@ -15,7 +15,7 @@ class TestSingleTestPass(PluginTester, unittest.TestCase):
         # 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
+        print(self.output)
         output = remove_timings(str(self.output))
         assert output == """\
 test.test ... ok
@@ -32,7 +32,7 @@ class TestZeroTestsPass(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'empty')
 
     def test_zero_tests_pass(self):
-        print self.output
+        print(self.output)
         output = remove_timings(str(self.output))
         assert output == """\
 
diff --git a/functional_tests/test_suite.py b/functional_tests/test_suite.py
index a411469..b6e4a18 100644
--- a/functional_tests/test_suite.py
+++ b/functional_tests/test_suite.py
@@ -14,7 +14,7 @@ class TestContextSuiteFactory(unittest.TestCase):
         sys.path.insert(0, os.path.join(support, 'package2'))
 
     def tearDown(self):
-        to_del = [ m for m in sys.modules.keys() if
+        to_del = [ m for m in list(sys.modules.keys()) if
                    m not in self._mods ]
         if to_del:
             for mod in to_del:
diff --git a/functional_tests/test_xunit.py b/functional_tests/test_xunit.py
index 6e76a7d..22f3fec 100644
--- a/functional_tests/test_xunit.py
+++ b/functional_tests/test_xunit.py
@@ -21,7 +21,7 @@ class TestXUnitPlugin(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'xunit')
     
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
         
         assert "ERROR: test_error" in self.output
         assert "FAIL: test_fail" in self.output
@@ -34,7 +34,7 @@ class TestXUnitPlugin(PluginTester, unittest.TestCase):
         f = codecs.open(xml_results_filename,'r', encoding='utf8')
         result = f.read()
         f.close()
-        print result.encode('utf8', 'replace')
+        print(result.encode('utf8', 'replace'))
         
         assert '<?xml version="1.0" encoding="UTF-8"?>' in result
         assert '<testsuite name="nosetests" tests="6" errors="2" failures="1" skip="1">' in result
@@ -56,11 +56,11 @@ class TestIssue134(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'issue134')
 
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
         f = open(xml_results_filename,'r')
         result = f.read()
         f.close()
-        print result
+        print(result)
         assert 'raise IOError(42, "test")' in result
         assert 'tests="1" errors="1" failures="0" skip="0"' in result
 
@@ -72,11 +72,11 @@ class TestIssue279(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'issue279')
 
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
         f = open(xml_results_filename,'r')
         result = f.read()
         f.close()
-        print result
+        print(result)
         assert 'tests="1" errors="1" failures="0" skip="0"' in result
         assert "Exception: I would prefer not to" in result
 
@@ -88,11 +88,11 @@ class TestIssue680(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'issue680')
 
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
         f = open(xml_results_filename,'rb')
         result = f.read().decode('utf-8')
         f.close()
-        print result
+        print(result)
         assert 'tests="1" errors="0" failures="0" skip="0"' in result
 
 
@@ -103,11 +103,11 @@ class TestIssue700(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'issue700')
 
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
         f = open(xml_results_filename,'r')
         result = f.read()
         f.close()
-        print result
+        print(result)
         assert 'tests="1" errors="0" failures="0" skip="0"' in result
         assert 'line1\n' in result
         assert 'line2\n' in result
@@ -121,10 +121,10 @@ class TestIssue859(PluginTester, unittest.TestCase):
     suitepath = os.path.join(support, 'issue859')
 
     def runTest(self):
-        print str(self.output)
+        print(str(self.output))
         f = open(xml_results_filename, 'r')
         result = f.read()
         f.close()
-        print result
+        print(result)
         assert 'tests="1" errors="0" failures="0" skip="0"' in result
         assert 'testsuite name="TestIssue859"' in result
diff --git a/nose/case.py b/nose/case.py
index 97fabf0..4c589f8 100644
--- a/nose/case.py
+++ b/nose/case.py
@@ -345,7 +345,7 @@ class MethodTestCase(TestBase):
         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.cls = method.__self__.__class__
         self.inst = self.cls()
         if self.test is None:
             method_name = self.method.__name__
diff --git a/nose/commands.py b/nose/commands.py
index ef0e9ca..db9fe31 100644
--- a/nose/commands.py
+++ b/nose/commands.py
@@ -148,7 +148,7 @@ else:
 
             ei_cmd = self.get_finalized_command("egg_info")
             argv = ['nosetests', '--where', ei_cmd.egg_base] 
-            for (option_name, cmd_name) in self.option_to_cmds.items():
+            for (option_name, cmd_name) in list(self.option_to_cmds.items()):
                 if option_name in option_blacklist:
                     continue
                 value = getattr(self, option_name)
diff --git a/nose/config.py b/nose/config.py
index d9aec2d..ec81a20 100644
--- a/nose/config.py
+++ b/nose/config.py
@@ -3,7 +3,7 @@ import optparse
 import os
 import re
 import sys
-import ConfigParser
+import configparser
 from optparse import OptionParser
 from nose.util import absdir, tolist
 from nose.plugins.manager import NoPlugins
@@ -62,24 +62,24 @@ class ConfiguredDefaultsOptionParser(object):
     def _readFromFilenames(self, filenames):
         config = []
         for filename in filenames:
-            cfg = ConfigParser.RawConfigParser()
+            cfg = configparser.RawConfigParser()
             try:
                 cfg.read(filename)
-            except ConfigParser.Error, exc:
+            except configparser.Error as 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()
+        cfg = configparser.RawConfigParser()
         try:
             filename = fh.name
         except AttributeError:
             filename = '<???>'
         try:
             cfg.read_file(fh)
-        except ConfigParser.Error, exc:
+        except configparser.Error as exc:
             raise ConfigError("Error reading config file %r: %s" %
                               (filename, str(exc)))
         return self._configTuples(cfg, filename)
@@ -89,7 +89,7 @@ class ConfiguredDefaultsOptionParser(object):
             config_files.readline
         except AttributeError:
             filename_or_filenames = config_files
-            if isinstance(filename_or_filenames, basestring):
+            if isinstance(filename_or_filenames, str):
                 filenames = [filename_or_filenames]
             else:
                 filenames = filename_or_filenames
@@ -113,12 +113,12 @@ class ConfiguredDefaultsOptionParser(object):
                 continue
             try:
                 self._processConfigValue(name, value, values, parser)
-            except NoSuchOptionError, exc:
+            except NoSuchOptionError as exc:
                 self._file_error(
                     "Error reading config file %r: "
                     "no such option %r" % (filename, exc.name),
                     name=name, filename=filename)
-            except optparse.OptionValueError, exc:
+            except optparse.OptionValueError as exc:
                 msg = str(exc).replace('--' + name, repr(name), 1)
                 self._file_error("Error reading config file %r: "
                                  "%s" % (filename, msg),
@@ -128,12 +128,12 @@ class ConfiguredDefaultsOptionParser(object):
         values = self._parser.get_default_values()
         try:
             config = self._readConfiguration(config_files)
-        except ConfigError, exc:
+        except ConfigError as exc:
             self._error(str(exc))
         else:
             try:
                 self._applyConfigurationToValues(self._parser, config, values)
-            except ConfigError, exc:
+            except ConfigError as exc:
                 self._error(str(exc))
         return self._parser.parse_args(args, values)
 
@@ -195,7 +195,7 @@ class Config(object):
                                           r'^_',
                                           r'^setup\.py$',
                                           ]
-        self.ignoreFiles = map(re.compile, self.ignoreFilesDefaultStrings)
+        self.ignoreFiles = list(map(re.compile, self.ignoreFilesDefaultStrings))
         self.include = None
         self.loggingConfig = None
         self.logStream = sys.stderr
@@ -247,7 +247,7 @@ class Config(object):
         d = self.__dict__.copy()
         # don't expose env, could include sensitive info
         d['env'] = {}
-        keys = [ k for k in d.keys()
+        keys = [ k for k in list(d.keys())
                  if not k.startswith('_') ]
         keys.sort()
         return "Config(%s)" % ', '.join([ '%s=%r' % (k, d[k])
@@ -328,17 +328,17 @@ class Config(object):
             self.testMatch = re.compile(options.testMatch)
 
         if options.ignoreFiles:
-            self.ignoreFiles = map(re.compile, tolist(options.ignoreFiles))
+            self.ignoreFiles = list(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))
+            self.include = list(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))
+            self.exclude = list(map(re.compile, tolist(options.exclude)))
             log.info("Excluding tests matching %s", options.exclude)
 
         # When listing plugins we don't want to run them
@@ -623,15 +623,15 @@ class NoOptions(object):
     def __getnewargs__(self):
         return ()
 
-    def __nonzero__(self):
+    def __bool__(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))
+    return list(filter(os.path.exists,
+                  list(map(os.path.expanduser, config_files))))
 
 
 def all_config_files():
diff --git a/nose/core.py b/nose/core.py
index 49e7939..ceacc9a 100644
--- a/nose/core.py
+++ b/nose/core.py
@@ -1,6 +1,6 @@
 """Implements nose test program and collector.
 """
-from __future__ import generators
+
 
 import logging
 import os
@@ -150,7 +150,7 @@ class TestProgram(unittest.TestProgram):
         if self.config.options.version:
             from nose import __version__
             sys.stdout = sys.__stdout__
-            print "%s version %s" % (os.path.basename(sys.argv[0]), __version__)
+            print("%s version %s" % (os.path.basename(sys.argv[0]), __version__))
             sys.exit(0)
 
         if self.config.options.showPlugins:
@@ -224,26 +224,26 @@ class TestProgram(unittest.TestProgram):
         v = self.config.verbosity
         self.config.plugins.sort()
         for p in self.config.plugins:
-            print "Plugin %s" % p.name
+            print("Plugin %s" % p.name)
             if v >= 2:
-                print "  score: %s" % p.score
-                print '\n'.join(textwrap.wrap(p.help().strip(),
+                print("  score: %s" % p.score)
+                print('\n'.join(textwrap.wrap(p.help().strip(),
                                               initial_indent='  ',
-                                              subsequent_indent='  '))
+                                              subsequent_indent='  ')))
                 if v >= 3:
                     parser = DummyParser()
                     p.addOptions(parser)
                     if len(parser.options):
-                        print
-                        print "  Options:"
+                        print()
+                        print("  Options:")
                         for opts, help in parser.options:
-                            print '  %s' % (', '.join(opts))
+                            print('  %s' % (', '.join(opts)))
                             if help:
-                                print '\n'.join(
+                                print('\n'.join(
                                     textwrap.wrap(help.strip(),
                                                   initial_indent='    ',
-                                                  subsequent_indent='    '))
-                print
+                                                  subsequent_indent='    ')))
+                print()
 
     def usage(cls):
         import nose
diff --git a/nose/ext/dtcompat.py b/nose/ext/dtcompat.py
index b5698c5..56a4c5f 100644
--- a/nose/ext/dtcompat.py
+++ b/nose/ext/dtcompat.py
@@ -104,7 +104,7 @@ import __future__
 import sys, traceback, inspect, linecache, os, re
 import unittest, difflib, pdb, tempfile
 import warnings
-from StringIO import StringIO
+from io import StringIO
 
 # Don't whine about the deprecated is_private function in this
 # module's tests.
@@ -219,7 +219,7 @@ def _normalize_module(module, depth=2):
     """
     if inspect.ismodule(module):
         return module
-    elif isinstance(module, (str, unicode)):
+    elif isinstance(module, str):
         return __import__(module, globals(), locals(), ["*"])
     elif module is None:
         return sys.modules[sys._getframe(depth).f_globals['__name__']]
@@ -341,9 +341,9 @@ class _OutputRedirectingPdb(pdb.Pdb):
 # [XX] Normalize with respect to os.path.pardir?
 def _module_relative_path(module, path):
     if not inspect.ismodule(module):
-        raise TypeError, 'Expected a module: %r' % module
+        raise TypeError('Expected a module: %r' % module)
     if path.startswith('/'):
-        raise ValueError, 'Module-relative files may not have absolute paths'
+        raise ValueError('Module-relative files may not have absolute paths')
 
     # Find the base directory for the path.
     if hasattr(module, '__file__'):
@@ -457,7 +457,7 @@ class DocTest:
         Create a new DocTest containing the given examples.  The
         DocTest's globals are initialized with a copy of `globs`.
         """
-        assert not isinstance(examples, basestring), \
+        assert not isinstance(examples, str), \
                "DocTest no longer accepts str; use DocTestParser instead"
         self.examples = examples
         self.docstring = docstring
@@ -856,7 +856,7 @@ class DocTestFinder:
         if module is None:
             return True
         elif inspect.isfunction(object):
-            return module.__dict__ is object.func_globals
+            return module.__dict__ is object.__globals__
         elif inspect.isclass(object):
             # Some jython classes don't set __module__
             return module.__name__ == getattr(object, '__module__', None)
@@ -875,7 +875,7 @@ class DocTestFinder:
         add them to `tests`.
         """
         if self._verbose:
-            print 'Finding tests in %s' % name
+            print('Finding tests in %s' % name)
 
         # If we've already processed this object, then ignore it.
         if id(obj) in seen:
@@ -889,7 +889,7 @@ class DocTestFinder:
 
         # Look for tests in a module's contained objects.
         if inspect.ismodule(obj) and self._recurse:
-            for valname, val in obj.__dict__.items():
+            for valname, val in list(obj.__dict__.items()):
                 # Check if this contained object should be ignored.
                 if self._filter(val, name, valname):
                     continue
@@ -902,14 +902,14 @@ class DocTestFinder:
 
         # Look for tests in a module's __test__ dictionary.
         if inspect.ismodule(obj) and self._recurse:
-            for valname, val in getattr(obj, '__test__', {}).items():
-                if not isinstance(valname, basestring):
+            for valname, val in list(getattr(obj, '__test__', {}).items()):
+                if not isinstance(valname, str):
                     raise ValueError("DocTestFinder.find: __test__ keys "
                                      "must be strings: %r" %
                                      (type(valname),))
                 if not (inspect.isfunction(val) or inspect.isclass(val) or
                         inspect.ismethod(val) or inspect.ismodule(val) or
-                        isinstance(val, basestring)):
+                        isinstance(val, str)):
                     raise ValueError("DocTestFinder.find: __test__ values "
                                      "must be strings, functions, methods, "
                                      "classes, or modules: %r" %
@@ -920,7 +920,7 @@ class DocTestFinder:
 
         # Look for tests in a class's contained objects.
         if inspect.isclass(obj) and self._recurse:
-            for valname, val in obj.__dict__.items():
+            for valname, val in list(obj.__dict__.items()):
                 # Check if this contained object should be ignored.
                 if self._filter(val, name, valname):
                     continue
@@ -928,7 +928,7 @@ class DocTestFinder:
                 if isinstance(val, staticmethod):
                     val = getattr(obj, valname)
                 if isinstance(val, classmethod):
-                    val = getattr(obj, valname).im_func
+                    val = getattr(obj, valname).__func__
 
                 # Recurse to methods, properties, and nested classes.
                 if ((inspect.isfunction(val) or inspect.isclass(val) or
@@ -945,7 +945,7 @@ class DocTestFinder:
         """
         # Extract the object's docstring.  If it doesn't have one,
         # then return None (no test for this object).
-        if isinstance(obj, basestring):
+        if isinstance(obj, str):
             docstring = obj
         else:
             try:
@@ -953,7 +953,7 @@ class DocTestFinder:
                     docstring = ''
                 else:
                     docstring = obj.__doc__
-                    if not isinstance(docstring, basestring):
+                    if not isinstance(docstring, str):
                         docstring = str(docstring)
             except (TypeError, AttributeError):
                 docstring = ''
@@ -1003,8 +1003,8 @@ class DocTestFinder:
                     break
 
         # Find the line number for functions & methods.
-        if inspect.ismethod(obj): obj = obj.im_func
-        if inspect.isfunction(obj): obj = obj.func_code
+        if inspect.ismethod(obj): obj = obj.__func__
+        if inspect.isfunction(obj): obj = obj.__code__
         if inspect.istraceback(obj): obj = obj.tb_frame
         if inspect.isframe(obj): obj = obj.f_code
         if inspect.iscode(obj):
@@ -1143,7 +1143,7 @@ class DocTestRunner:
         # to modify them).
         original_optionflags = self.optionflags
 
-        SUCCESS, FAILURE, BOOM = range(3) # `outcome` state
+        SUCCESS, FAILURE, BOOM = list(range(3)) # `outcome` state
 
         check = self._checker.check_output
 
@@ -1158,7 +1158,7 @@ class DocTestRunner:
             # Merge in the example's options.
             self.optionflags = original_optionflags
             if example.options:
-                for (optionflag, val) in example.options.items():
+                for (optionflag, val) in list(example.options.items()):
                     if val:
                         self.optionflags |= optionflag
                     else:
@@ -1179,8 +1179,8 @@ class DocTestRunner:
             # keyboard interrupts.)
             try:
                 # Don't blink!  This is where the user's code gets run.
-                exec compile(example.source, filename, "single",
-                             compileflags, 1) in test.globs
+                exec(compile(example.source, filename, "single",
+                             compileflags, 1), test.globs)
                 self.debugger.set_continue() # ==== Example Finished ====
                 exception = None
             except KeyboardInterrupt:
@@ -1341,7 +1341,7 @@ class DocTestRunner:
         passed = []
         failed = []
         totalt = totalf = 0
-        for x in self._name2ft.items():
+        for x in list(self._name2ft.items()):
             name, (f, t) = x
             assert f <= t
             totalt += t
@@ -1354,28 +1354,28 @@ class DocTestRunner:
                 failed.append(x)
         if verbose:
             if notests:
-                print len(notests), "items had no tests:"
+                print(len(notests), "items had no tests:")
                 notests.sort()
                 for thing in notests:
-                    print "   ", thing
+                    print("   ", thing)
             if passed:
-                print len(passed), "items passed all tests:"
+                print(len(passed), "items passed all tests:")
                 passed.sort()
                 for thing, count in passed:
-                    print " %3d tests in %s" % (count, thing)
+                    print(" %3d tests in %s" % (count, thing))
         if failed:
-            print self.DIVIDER
-            print len(failed), "items had failures:"
+            print(self.DIVIDER)
+            print(len(failed), "items had failures:")
             failed.sort()
             for thing, (f, t) in failed:
-                print " %3d of %3d in %s" % (f, t, thing)
+                print(" %3d of %3d in %s" % (f, t, thing))
         if verbose:
-            print totalt, "tests in", len(self._name2ft), "items."
-            print totalt - totalf, "passed and", totalf, "failed."
+            print(totalt, "tests in", len(self._name2ft), "items.")
+            print(totalt - totalf, "passed and", totalf, "failed.")
         if totalf:
-            print "***Test Failed***", totalf, "failures."
+            print("***Test Failed***", totalf, "failures.")
         elif verbose:
-            print "Test passed."
+            print("Test passed.")
         return totalf, totalt
 
     #/////////////////////////////////////////////////////////////////
@@ -1383,10 +1383,10 @@ class DocTestRunner:
     #/////////////////////////////////////////////////////////////////
     def merge(self, other):
         d = self._name2ft
-        for name, (f, t) in other._name2ft.items():
+        for name, (f, t) in list(other._name2ft.items()):
             if name in d:
-                print "*** DocTestRunner.merge: '" + name + "' in both" \
-                    " testers; summing outcomes."
+                print("*** DocTestRunner.merge: '" + name + "' in both" \
+                    " testers; summing outcomes.")
                 f2, t2 = d[name]
                 f = f + f2
                 t = t + t2
@@ -1875,10 +1875,10 @@ class Tester:
     def runstring(self, s, name):
         test = DocTestParser().get_doctest(s, self.globs, name, None, None)
         if self.verbose:
-            print "Running string", name
+            print("Running string", name)
         (f,t) = self.testrunner.run(test)
         if self.verbose:
-            print f, "of", t, "examples failed in string", name
+            print(f, "of", t, "examples failed in string", name)
         return (f,t)
 
     def rundoc(self, object, name=None, module=None):
@@ -2245,9 +2245,9 @@ def debug_script(src, pm=False, globs=None):
 
         if pm:
             try:
-                execfile(srcfilename, globs, globs)
+                exec(compile(open(srcfilename, "rb").read(), srcfilename, 'exec'), globs, globs)
             except:
-                print sys.exc_info()[1]
+                print(sys.exc_info()[1])
                 pdb.post_mortem(sys.exc_info()[2])
         else:
             # Note that %r is vital here.  '%s' instead can, e.g., cause
diff --git a/nose/failure.py b/nose/failure.py
index c5fabfd..dad5253 100644
--- a/nose/failure.py
+++ b/nose/failure.py
@@ -36,7 +36,7 @@ class Failure(unittest.TestCase):
     def runTest(self):
         if self.tb is not None:
             if is_base_exception(self.exc_val):
-                raise self.exc_val, None, self.tb
-            raise self.exc_class, self.exc_val, self.tb
+                raise self.exc_val.with_traceback(self.tb)
+            raise self.exc_class(self.exc_val).with_traceback(self.tb)
         else:
             raise self.exc_class(self.exc_val)
diff --git a/nose/inspector.py b/nose/inspector.py
index ad22c0c..d6b4a5a 100644
--- a/nose/inspector.py
+++ b/nose/inspector.py
@@ -9,9 +9,9 @@ import textwrap
 import tokenize
 
 try:
-    from cStringIO import StringIO
+    from io import StringIO
 except ImportError:
-    from StringIO import StringIO
+    from io import StringIO
 
 log = logging.getLogger(__name__)
 
@@ -38,7 +38,7 @@ def inspect_traceback(tb):
         try:
             for tok in tokenize.generate_tokens(src.readline):
                 exp(*tok)
-        except tokenize.TokenError, e:
+        except tokenize.TokenError as e:
             # this can happen if our inspectable region happens to butt up
             # against the end of a construct like a docstring with the closing
             # """ on separate line
diff --git a/nose/loader.py b/nose/loader.py
index 3744e54..17bcae3 100644
--- a/nose/loader.py
+++ b/nose/loader.py
@@ -6,7 +6,7 @@ nose's test loader implements the same basic functionality as its
 superclass, unittest.TestLoader, but extends it by more liberal
 interpretations of what may be a test and how a test may be named.
 """
-from __future__ import generators
+
 
 import logging
 import os
@@ -113,7 +113,7 @@ class TestLoader(unittest.TestLoader):
                 return False
             return sel.wantMethod(item)
 
-        cases = filter(wanted, dir(testCaseClass))
+        cases = list(filter(wanted, dir(testCaseClass)))
 
         # add runTest if nothing else picked
         if not cases and hasattr(testCaseClass, 'runTest'):
@@ -224,7 +224,7 @@ class TestLoader(unittest.TestLoader):
                 # Plugins can yield False to indicate that they were
                 # unable to load tests from a file, but it was not an
                 # error -- the file just had no tests to load.
-                tests = filter(None, tests)
+                tests = [_f for _f in tests if _f]
                 return self.suiteClass(tests)
             else:
                 # Nothing was able to even try to load from this file
@@ -274,7 +274,7 @@ class TestLoader(unittest.TestLoader):
         # convert the unbound generator method
         # into a bound method so it can be called below
         if hasattr(generator, 'im_class'):
-            cls = generator.im_class
+            cls = generator.__self__.__class__
         inst = cls()
         method = generator.__name__
         generator = getattr(inst, method)
@@ -329,8 +329,7 @@ class TestLoader(unittest.TestLoader):
                     test_funcs.append(test)
             sort_list(test_classes, lambda x: x.__name__)
             sort_list(test_funcs, func_lineno)
-            tests = map(lambda t: self.makeTest(t, parent=module),
-                        test_classes + test_funcs)
+            tests = [self.makeTest(t, parent=module) for t in test_classes + test_funcs]
 
         # Now, descend into packages
         # FIXME can or should this be lazy?
diff --git a/nose/plugins/attrib.py b/nose/plugins/attrib.py
index 3d4422a..8ac9239 100644
--- a/nose/plugins/attrib.py
+++ b/nose/plugins/attrib.py
@@ -118,7 +118,7 @@ def attr(*args, **kwargs):
     def wrap_ob(ob):
         for name in args:
             setattr(ob, name, True)
-        for name, value in kwargs.iteritems():
+        for name, value in kwargs.items():
             setattr(ob, name, value)
         return ob
     return wrap_ob
@@ -280,7 +280,7 @@ class AttributeSelector(Plugin):
         """Accept the method if its attributes match.
         """
         try:
-            cls = method.im_class
+            cls = method.__self__.__class__
         except AttributeError:
             return False
         return self.validateAttrib(method, cls)
diff --git a/nose/plugins/base.py b/nose/plugins/base.py
index f09beb6..0e1c68f 100644
--- a/nose/plugins/base.py
+++ b/nose/plugins/base.py
@@ -67,7 +67,7 @@ class Plugin(object):
         try:
             self.options(parser, env)
             self.can_configure = True
-        except OptionConflictError, e:
+        except OptionConflictError as e:
             warn("Plugin %s has conflicting option string: %s and will "
                  "be disabled" % (self, e), RuntimeWarning)
             self.enabled = False
diff --git a/nose/plugins/capture.py b/nose/plugins/capture.py
index 888a552..fa2736a 100644
--- a/nose/plugins/capture.py
+++ b/nose/plugins/capture.py
@@ -16,7 +16,7 @@ import traceback
 from nose.plugins.base import Plugin
 from nose.pyversion import exc_to_unicode, force_unicode
 from nose.util import ln
-from StringIO import StringIO
+from io import StringIO
 
 
 log = logging.getLogger(__name__)
@@ -111,17 +111,17 @@ class Capture(Plugin):
         # from an exception raised while trying to get the captured output.
         ev = exc_to_unicode(ev)
         output = force_unicode(output)
-        error_text = [ev, ln(u'>> begin captured stdout <<'),
-                      output, ln(u'>> end captured stdout <<')]
+        error_text = [ev, ln('>> begin captured stdout <<'),
+                      output, ln('>> end captured stdout <<')]
         if output_exc_info:
-            error_text.extend([u'OUTPUT ERROR: Could not get captured output.',
+            error_text.extend(['OUTPUT ERROR: Could not get captured output.',
                                # <https://github.com/python/cpython/blob/2.7/Lib/StringIO.py#L258>
                                # <https://github.com/nose-devs/nose/issues/816>
-                               u"The test might've printed both 'unicode' strings and non-ASCII 8-bit 'str' strings.",
-                               ln(u'>> begin captured stdout exception traceback <<'),
-                               u''.join(traceback.format_exception(*output_exc_info)),
-                               ln(u'>> end captured stdout exception traceback <<')])
-        return u'\n'.join(error_text)
+                               "The test might've printed both 'unicode' strings and non-ASCII 8-bit 'str' strings.",
+                               ln('>> begin captured stdout exception traceback <<'),
+                               ''.join(traceback.format_exception(*output_exc_info)),
+                               ln('>> end captured stdout exception traceback <<')])
+        return '\n'.join(error_text)
 
     def start(self):
         self.stdout.append(sys.stdout)
diff --git a/nose/plugins/cover.py b/nose/plugins/cover.py
index b9bfc82..24bf535 100644
--- a/nose/plugins/cover.py
+++ b/nose/plugins/cover.py
@@ -13,7 +13,7 @@ variable.
 import logging
 import re
 import sys
-import StringIO
+import io
 from nose.plugins.base import Plugin
 from nose.util import src, tolist
 
@@ -145,7 +145,7 @@ class Coverage(Plugin):
             self.coverInstance.exclude('#pragma[: ]+[nN][oO] [cC][oO][vV][eE][rR]')
 
             log.debug("Coverage begin")
-            self.skipModules = sys.modules.keys()[:]
+            self.skipModules = list(sys.modules.keys())[:]
             if self.coverErase:
                 log.debug("Clearing previously collected coverage statistics")
                 self.coverInstance.combine()
@@ -184,7 +184,7 @@ class Coverage(Plugin):
         self.coverInstance.combine()
         self.coverInstance.save()
         modules = [module
-                    for name, module in sys.modules.items()
+                    for name, module in list(sys.modules.items())
                     if self.wantModuleCoverage(name, module)]
         log.debug("Coverage report will cover modules: %s", modules)
         self.coverInstance.report(modules, file=stream, show_missing=True)
@@ -194,19 +194,19 @@ class Coverage(Plugin):
             log.debug("Generating HTML coverage report")
             try:
                 self.coverInstance.html_report(modules, self.coverHtmlDir)
-            except coverage.misc.CoverageException, e:
+            except coverage.misc.CoverageException as e:
                 log.warning("Failed to generate HTML report: %s" % str(e))
 
         if self.coverXmlFile:
             log.debug("Generating XML coverage report")
             try:
                 self.coverInstance.xml_report(modules, self.coverXmlFile)
-            except coverage.misc.CoverageException, e:
+            except coverage.misc.CoverageException as e:
                 log.warning("Failed to generate XML report: %s" % str(e))
 
         # make sure we have minimum required coverage
         if self.coverMinPercentage:
-            f = StringIO.StringIO()
+            f = io.StringIO()
             self.coverInstance.report(modules, file=f, show_missing=True)
 
             multiPackageRe = (r'-------\s\w+\s+\d+\s+\d+(?:\s+\d+\s+\d+)?'
diff --git a/nose/plugins/doctests.py b/nose/plugins/doctests.py
index 528cd63..32736b6 100644
--- a/nose/plugins/doctests.py
+++ b/nose/plugins/doctests.py
@@ -47,7 +47,7 @@ test.
    additional documentation and examples.
 
 """
-from __future__ import generators
+
 
 import codecs
 import logging
@@ -60,11 +60,11 @@ from nose.suite import ContextList
 from nose.util import anyp, getpackage, test_address, resolve_name, \
      src, tolist, isproperty
 try:
-    from cStringIO import StringIO
+    from io import StringIO
 except ImportError:
-    from StringIO import StringIO
+    from io import StringIO
 import sys
-import __builtin__ as builtin_mod
+import builtins as builtin_mod
 
 log = logging.getLogger(__name__)
 
@@ -276,7 +276,7 @@ class Doctest(Plugin):
                 try:
                     fixture_context = __import__(
                         fixt_mod, globals(), locals(), ["nop"])
-                except ImportError, e:
+                except ImportError as e:
                     log.debug(
                         "Could not import %s: %s (%s)", fixt_mod, e, sys.path)
                 log.debug("Fixture module %s resolved to %s",
@@ -322,13 +322,11 @@ class Doctest(Plugin):
         # FIXME don't think we need include/exclude checks here?
         return ((self.doctest_tests or not self.conf.testMatch.search(name)
                  or (self.conf.include 
-                     and filter(None,
-                                [inc.search(name)
-                                 for inc in self.conf.include])))
+                     and [_f for _f in [inc.search(name)
+                                 for inc in self.conf.include] if _f]))
                 and (not self.conf.exclude 
-                     or not filter(None,
-                                   [exc.search(name)
-                                    for exc in self.conf.exclude])))
+                     or not [_f for _f in [exc.search(name)
+                                    for exc in self.conf.exclude] if _f]))
     
     def wantFile(self, file):
         """Override to select all modules and any file ending with
@@ -341,9 +339,8 @@ class Doctest(Plugin):
         if (self.extension
             and anyp(file.endswith, self.extension)
             and (not self.conf.exclude
-                 or not filter(None, 
-                               [exc.search(file)
-                                for exc in self.conf.exclude]))):
+                 or not [_f for _f in [exc.search(file)
+                                for exc in self.conf.exclude] if _f])):
             return True
         return None
 
@@ -414,7 +411,7 @@ class DocTestCase(doctest.DocTestCase):
         if value is None:
             return
         setattr(builtin_mod, self._result_var,  value)
-        print repr(value)
+        print(repr(value))
 
     def tearDown(self):
         super(DocTestCase, self).tearDown()
@@ -447,7 +444,7 @@ class DocFileCase(doctest.DocFileCase):
         if value is None:
             return
         setattr(builtin_mod, self._result_var, value)
-        print repr(value)
+        print(repr(value))
 
     def tearDown(self):
         super(DocFileCase, self).tearDown()
diff --git a/nose/plugins/errorclass.py b/nose/plugins/errorclass.py
index 38ecec9..0e0927d 100644
--- a/nose/plugins/errorclass.py
+++ b/nose/plugins/errorclass.py
@@ -114,7 +114,7 @@ class MetaErrorClass(type):
     """
     def __init__(self, name, bases, attr):
         errorClasses = []
-        for name, detail in attr.items():
+        for name, detail in list(attr.items()):
             if isinstance(detail, ErrorClass):
                 attr.pop(name)
                 for cls in detail:
@@ -138,12 +138,11 @@ class ErrorClass(object):
         return iter(self.errorClasses)
 
 
-class ErrorClassPlugin(Plugin):
+class ErrorClassPlugin(Plugin, metaclass=MetaErrorClass):
     """
     Base class for ErrorClass plugins. Subclass this class and declare the
     exceptions that you wish to handle as attributes of the subclass.
     """
-    __metaclass__ = MetaErrorClass
     score = 1000
     errorClasses = ()
 
@@ -152,7 +151,7 @@ class ErrorClassPlugin(Plugin):
         if not isclass(err_cls):
             return
         classes = [e[0] for e in self.errorClasses]
-        if filter(lambda c: issubclass(err_cls, c), classes):
+        if [c for c in classes if issubclass(err_cls, c)]:
             return True
 
     def prepareTestResult(self, result):
diff --git a/nose/plugins/isolate.py b/nose/plugins/isolate.py
index 13235df..77a2de5 100644
--- a/nose/plugins/isolate.py
+++ b/nose/plugins/isolate.py
@@ -72,7 +72,7 @@ class IsolationPlugin(Plugin):
         it was in when mod stack was pushed.
         """
         mods = self._mod_stack.pop()
-        to_del = [ m for m in sys.modules.keys() if m not in mods ]
+        to_del = [ m for m in list(sys.modules.keys()) if m not in mods ]
         if to_del:
             log.debug('removing sys modules entries: %s', to_del)
             for mod in to_del:
diff --git a/nose/plugins/logcapture.py b/nose/plugins/logcapture.py
index 4c9a79f..2af79ad 100644
--- a/nose/plugins/logcapture.py
+++ b/nose/plugins/logcapture.py
@@ -23,9 +23,9 @@ from nose.plugins.base import Plugin
 from nose.util import anyp, ln, safe_str
 
 try:
-    from cStringIO import StringIO
+    from io import StringIO
 except ImportError:
-    from StringIO import StringIO
+    from io import StringIO
 
 log = logging.getLogger(__name__)
 
@@ -57,7 +57,7 @@ class FilterSet(object):
         any item in `matchers`"""
         def record_matches_key(key):
             return record == key or record.startswith(key + '.')
-        return anyp(bool, map(record_matches_key, matchers))
+        return anyp(bool, list(map(record_matches_key, matchers)))
     _any_match = staticmethod(_any_match)
 
     def _allow(self, record):
@@ -180,7 +180,7 @@ class LogCapture(Plugin):
             if hasattr(root_logger, "handlers"):
                 for handler in root_logger.handlers:
                     root_logger.removeHandler(handler)
-            for logger in logging.Logger.manager.loggerDict.values():
+            for logger in list(logging.Logger.manager.loggerDict.values()):
                 if hasattr(logger, "handlers"):
                     for handler in logger.handlers:
                         logger.removeHandler(handler)
@@ -237,7 +237,7 @@ class LogCapture(Plugin):
         return (ec, self.addCaptureToErr(ev, records), tb)
 
     def formatLogRecords(self):
-        return map(safe_str, self.handler.buffer)
+        return list(map(safe_str, self.handler.buffer))
 
     def addCaptureToErr(self, ev, records):
         return '\n'.join([safe_str(ev), ln('>> begin captured logging <<')] + \
diff --git a/nose/plugins/manager.py b/nose/plugins/manager.py
index daa9edb..52a7c96 100644
--- a/nose/plugins/manager.py
+++ b/nose/plugins/manager.py
@@ -60,13 +60,13 @@ from nose.plugins.base import IPluginInterface
 from nose.pyversion import sort_list
 
 try:
-    import cPickle as pickle
+    import pickle as pickle
 except:
     import pickle
 try:
-    from cStringIO import StringIO
+    from io import StringIO
 except:
-    from StringIO import StringIO
+    from io import StringIO
 
 
 __all__ = ['DefaultPluginManager', 'PluginManager', 'EntryPointPluginManager',
@@ -387,7 +387,7 @@ class EntryPointPluginManager(PluginManager):
                     plugcls = ep.load()
                 except KeyboardInterrupt:
                     raise
-                except Exception, e:
+                except Exception as e:
                     # never want a plugin load to kill the test run
                     # but we can't log here because the logger is not yet
                     # configured
diff --git a/nose/plugins/multiprocess.py b/nose/plugins/multiprocess.py
index 2cae744..a0c53c6 100644
--- a/nose/plugins/multiprocess.py
+++ b/nose/plugins/multiprocess.py
@@ -115,12 +115,12 @@ try:
     from unittest.runner import _WritelnDecorator
 except ImportError:
     from unittest import _WritelnDecorator
-from Queue import Empty
+from queue import Empty
 from warnings import warn
 try:
-    from cStringIO import StringIO
+    from io import StringIO
 except ImportError:
-    import StringIO
+    import io
 
 # this is a list of plugin classes that will be checked for and created inside 
 # each worker process
@@ -478,7 +478,7 @@ class MultiProcessTestRunner(TextTestRunner):
                                 self.config.multiprocess_timeout-timeprocessing)
             log.debug("Completed %s tasks (%s remain)", len(completed), len(tasks))
 
-        except (KeyboardInterrupt, SystemExit), e:
+        except (KeyboardInterrupt, SystemExit) as e:
             log.info('parent received ctrl-c when waiting for test results')
             thrownError = e
             #resultQueue.get(False)
@@ -633,7 +633,7 @@ class MultiProcessTestRunner(TextTestRunner):
         result.testsRun += testsRun
         result.failures.extend(failures)
         result.errors.extend(errors)
-        for key, (storage, label, isfail) in errorClasses.items():
+        for key, (storage, label, isfail) in list(errorClasses.items()):
             if key not in result.errorClasses:
                 # Ordinarily storage is result attribute
                 # but it's only processed through the errorClasses
@@ -688,7 +688,7 @@ def __runner(ix, testQueue, resultQueue, currentaddr, currentstart,
         failures = [(TestLet(c), err) for c, err in result.failures]
         errors = [(TestLet(c), err) for c, err in result.errors]
         errorClasses = {}
-        for key, (storage, label, isfail) in result.errorClasses.items():
+        for key, (storage, label, isfail) in list(result.errorClasses.items()):
             errorClasses[key] = ([(TestLet(c), err) for c, err in storage],
                                  label, isfail)
         return (
@@ -715,7 +715,7 @@ def __runner(ix, testQueue, resultQueue, currentaddr, currentstart,
             test(result)
             currentaddr.value = bytes_('')
             resultQueue.put((ix, test_addr, test.tasks, batch(result)))
-        except KeyboardInterrupt, e: #TimedOutException:
+        except KeyboardInterrupt as e: #TimedOutException:
             timeout = isinstance(e, TimedOutException)
             if timeout:
                 keyboardCaught.set()
@@ -810,7 +810,7 @@ class NoSharedFixtureContextSuite(ContextSuite):
                 #log.debug('running test %s in suite %s', test, self);
                 try:
                     test(orig)
-                except KeyboardInterrupt, e:
+                except KeyboardInterrupt as e:
                     timeout = isinstance(e, TimedOutException)
                     if timeout:
                         msg = 'Timeout when running test %s in suite %s'
diff --git a/nose/plugins/plugintest.py b/nose/plugins/plugintest.py
index 76d0d2c..00b67f5 100644
--- a/nose/plugins/plugintest.py
+++ b/nose/plugins/plugintest.py
@@ -100,9 +100,9 @@ import sys
 from warnings import warn
 
 try:
-    from cStringIO import StringIO
+    from io import StringIO
 except ImportError:
-    from StringIO import StringIO
+    from io import StringIO
 
 __all__ = ['PluginTester', 'run']
 
@@ -135,7 +135,7 @@ class MultiProcessFile(object):
         if getpid() != self.__master:
             return
 
-        from Queue import Empty
+        from queue import Empty
         from collections import defaultdict
         cache = defaultdict(str)
         while True:
@@ -404,7 +404,7 @@ def run(*arg, **kw):
             sys.stderr = stderr
             sys.stdout = stdout
     out = buffer.getvalue()
-    print munge_nose_output_for_doctest(out)
+    print(munge_nose_output_for_doctest(out))
 
 
 def run_buffered(*arg, **kw):
diff --git a/nose/plugins/testid.py b/nose/plugins/testid.py
index ae8119b..caa4c5b 100644
--- a/nose/plugins/testid.py
+++ b/nose/plugins/testid.py
@@ -100,7 +100,7 @@ from nose.plugins import Plugin
 from nose.util import src, set
 
 try:
-    from cPickle import dump, load
+    from pickle import dump, load
 except ImportError:
     from pickle import dump, load
 
@@ -198,7 +198,7 @@ class TestId(Plugin):
                 self.ids, self.tests, self.failed, self.source_names,
                 self.idfile)
             fh.close()
-        except ValueError, e:
+        except ValueError as e:
             # load() may throw a ValueError when reading the ids file, if it
             # was generated with a newer version of Python than we are currently
             # running.
diff --git a/nose/plugins/xunit.py b/nose/plugins/xunit.py
index 90b52f5..c42567f 100644
--- a/nose/plugins/xunit.py
+++ b/nose/plugins/xunit.py
@@ -46,7 +46,7 @@ import sys
 import traceback
 import re
 import inspect
-from StringIO import StringIO
+from io import StringIO
 from time import time
 from xml.sax import saxutils
 
@@ -110,7 +110,7 @@ def exc_message(exc_info):
             result = str(exc)
         except UnicodeEncodeError:
             try:
-                result = unicode(exc)
+                result = str(exc)
             except UnicodeError:
                 # Fallback to args as neither str nor
                 # unicode(Exception(u'\xe6')) work in Python < 2.6
@@ -213,13 +213,13 @@ class Xunit(Plugin):
         self.stats['total'] = (self.stats['errors'] + self.stats['failures']
                                + self.stats['passes'] + self.stats['skipped'])
         self.error_report_file.write(
-            u'<?xml version="1.0" encoding="%(encoding)s"?>'
-            u'<testsuite name="%(testsuite_name)s" tests="%(total)d" '
-            u'errors="%(errors)d" failures="%(failures)d" '
-            u'skip="%(skipped)d">' % self.stats)
-        self.error_report_file.write(u''.join([force_unicode(e, self.encoding)
+            '<?xml version="1.0" encoding="%(encoding)s"?>'
+            '<testsuite name="%(testsuite_name)s" tests="%(total)d" '
+            'errors="%(errors)d" failures="%(failures)d" '
+            'skip="%(skipped)d">' % self.stats)
+        self.error_report_file.write(''.join([force_unicode(e, self.encoding)
                                                for e in self.errorlist]))
-        self.error_report_file.write(u'</testsuite>')
+        self.error_report_file.write('</testsuite>')
         self.error_report_file.close()
         if self.config.verbosity > 1:
             stream.writeln("-" * 70)
@@ -288,9 +288,9 @@ class Xunit(Plugin):
         id = test.id()
 
         self.errorlist.append(
-            u'<testcase classname=%(cls)s name=%(name)s time="%(taken).3f">'
-            u'<%(type)s type=%(errtype)s message=%(message)s><![CDATA[%(tb)s]]>'
-            u'</%(type)s>%(systemout)s%(systemerr)s</testcase>' %
+            '<testcase classname=%(cls)s name=%(name)s time="%(taken).3f">'
+            '<%(type)s type=%(errtype)s message=%(message)s><![CDATA[%(tb)s]]>'
+            '</%(type)s>%(systemout)s%(systemerr)s</testcase>' %
             {'cls': self._quoteattr(id_split(id)[0]),
              'name': self._quoteattr(id_split(id)[-1]),
              'taken': taken,
@@ -311,9 +311,9 @@ class Xunit(Plugin):
         id = test.id()
 
         self.errorlist.append(
-            u'<testcase classname=%(cls)s name=%(name)s time="%(taken).3f">'
-            u'<failure type=%(errtype)s message=%(message)s><![CDATA[%(tb)s]]>'
-            u'</failure>%(systemout)s%(systemerr)s</testcase>' %
+            '<testcase classname=%(cls)s name=%(name)s time="%(taken).3f">'
+            '<failure type=%(errtype)s message=%(message)s><![CDATA[%(tb)s]]>'
+            '</failure>%(systemout)s%(systemerr)s</testcase>' %
             {'cls': self._quoteattr(id_split(id)[0]),
              'name': self._quoteattr(id_split(id)[-1]),
              'taken': taken,
diff --git a/nose/pyversion.py b/nose/pyversion.py
index 091238d..3de934d 100644
--- a/nose/pyversion.py
+++ b/nose/pyversion.py
@@ -16,12 +16,12 @@ __all__ = ['make_instancemethod', 'cmp_to_key', 'sort_list', 'ClassType',
 # In Python 3.x, all strings are unicode (the call to 'unicode()' in the 2.x
 # source will be replaced with 'str()' when running 2to3, so this test will
 # then become true)
-UNICODE_STRINGS = (type(unicode()) == type(str()))
+UNICODE_STRINGS = (type(str()) == type(str()))
 
 if sys.version_info[:2] < (3, 0):
     def force_unicode(s, encoding='UTF-8'):
         try:
-            s = unicode(s)
+            s = str(s)
         except UnicodeDecodeError:
             s = str(s).decode(encoding, 'replace')
 
@@ -35,7 +35,7 @@ else:
 try:
     import new
     def make_instancemethod(function, instance):
-        return new.instancemethod(function.im_func, instance,
+        return new.instancemethod(function.__func__, instance,
                                   instance.__class__)
 except ImportError:
     def make_instancemethod(function, instance):
@@ -73,8 +73,8 @@ else:
 # thus types.ClassType and types.TypeType don't exist anymore.  For
 # compatibility, we make sure they still work.
 if hasattr(types, 'ClassType'):
-    ClassType = types.ClassType
-    TypeType = types.TypeType
+    ClassType = type
+    TypeType = type
 else:
     ClassType = type
     TypeType = type
@@ -90,7 +90,7 @@ class UnboundMethod:
         self._func = func
         self.__self__ = UnboundSelf(cls)
         if sys.version_info < (3, 0):
-            self.im_class = cls
+            self.__self__.__class__ = cls
         self.__doc__ = getattr(func, '__doc__', None)
 
     def address(self):
@@ -161,7 +161,7 @@ else:
 
     def isgenerator(func):
         try:
-            return func.func_code.co_flags & CO_GENERATOR != 0
+            return func.__code__.co_flags & CO_GENERATOR != 0
         except AttributeError:
             return False
 
@@ -187,8 +187,8 @@ if sys.version_info[:2] < (3, 0):
                 msg = force_unicode(msg, encoding=encoding)
                 clsname = force_unicode(ev.__class__.__name__,
                         encoding=encoding)
-                ev = u'%s: %s' % (clsname, msg)
-        elif not isinstance(ev, unicode):
+                ev = '%s: %s' % (clsname, msg)
+        elif not isinstance(ev, str):
             ev = repr(ev)
 
         return force_unicode(ev, encoding=encoding)
diff --git a/nose/result.py b/nose/result.py
index 228a42c..518fa65 100644
--- a/nose/result.py
+++ b/nose/result.py
@@ -62,7 +62,7 @@ class TextTestResult(_TextTestResult):
         except TypeError:
             # 2.3 compat
             exc_info = self._exc_info_to_string(err)
-        for cls, (storage, label, isfail) in self.errorClasses.items():
+        for cls, (storage, label, isfail) in list(self.errorClasses.items()):
             #if 'Skip' in cls.__name__ or 'Skip' in ec.__name__:
             #    from nose.tools import set_trace
             #    set_trace()
@@ -101,7 +101,7 @@ class TextTestResult(_TextTestResult):
         """Overrides to print all errorClasses errors as well.
         """
         _TextTestResult.printErrors(self)
-        for cls in self.errorClasses.keys():
+        for cls in list(self.errorClasses.keys()):
             storage, label, isfail = self.errorClasses[cls]
             if isfail:
                 self.printErrorList(label, storage)
@@ -124,7 +124,7 @@ class TextTestResult(_TextTestResult):
         writeln()
 
         summary = {}
-        eckeys = self.errorClasses.keys()
+        eckeys = list(self.errorClasses.keys())
         for cls in eckeys:
             storage, label, isfail = self.errorClasses[cls]
             count = len(storage)
@@ -140,7 +140,7 @@ class TextTestResult(_TextTestResult):
             write("FAILED")
         else:
             write("OK")
-        items = summary.items()
+        items = list(summary.items())
         if items:
             items.sort()
             write(" (")
@@ -157,7 +157,7 @@ class TextTestResult(_TextTestResult):
         """
         if self.errors or self.failures:
             return False
-        for cls in self.errorClasses.keys():
+        for cls in list(self.errorClasses.keys()):
             storage, label, isfail = self.errorClasses[cls]
             if not isfail:
                 continue
diff --git a/nose/selector.py b/nose/selector.py
index b63f7af..0764282 100644
--- a/nose/selector.py
+++ b/nose/selector.py
@@ -52,11 +52,9 @@ class Selector(object):
         """
         return ((self.match.search(name)
                  or (self.include and
-                     filter(None,
-                            [inc.search(name) for inc in self.include])))
+                     [_f for _f in [inc.search(name) for inc in self.include] if _f]))
                 and ((not self.exclude)
-                     or not filter(None,
-                                   [exc.search(name) for exc in self.exclude])
+                     or not [_f for _f in [exc.search(name) for exc in self.exclude] if _f]
                  ))
     
     def wantClass(self, cls):
@@ -89,9 +87,7 @@ class Selector(object):
         tail = op_basename(dirname)
         if ispackage(dirname):
             wanted = (not self.exclude
-                      or not filter(None,
-                                    [exc.search(tail) for exc in self.exclude]
-                                    ))
+                      or not [_f for _f in [exc.search(tail) for exc in self.exclude] if _f])
         else:
             wanted = (self.matches(tail)
                       or (self.config.srcDirs
diff --git a/nose/suite.py b/nose/suite.py
index a831105..20dc21c 100644
--- a/nose/suite.py
+++ b/nose/suite.py
@@ -7,7 +7,7 @@ function, and ContextSuite,which can run fixtures (setup/teardown
 functions or methods) for the context that contains its tests.
 
 """
-from __future__ import generators
+
 
 import logging
 import sys
@@ -75,14 +75,14 @@ class LazySuite(unittest.TestSuite):
             test(result)
         return result
 
-    def __nonzero__(self):
+    def __bool__(self):
         log.debug("tests in %s?", id(self))
         if self._precache:
             return True
         if self.test_generator is None:
             return False
         try:
-            test = self.test_generator.next()
+            test = next(self.test_generator)
             if test is not None:
                 self._precache.append(test)
                 return True
@@ -439,7 +439,7 @@ class ContextSuiteFactory(object):
         # don't want that, instead want the module the class is in now
         # (classes are re-ancestored elsewhere).
         if hasattr(context, 'im_class'):
-            context = context.im_class
+            context = context.__self__.__class__
         elif hasattr(context, '__self__'):
             context = context.__self__.__class__
         if hasattr(context, '__module__'):
diff --git a/nose/tools/nontrivial.py b/nose/tools/nontrivial.py
index 2839732..62e221e 100644
--- a/nose/tools/nontrivial.py
+++ b/nose/tools/nontrivial.py
@@ -26,7 +26,7 @@ def make_decorator(func):
         newfunc.__doc__ = func.__doc__
         newfunc.__module__ = func.__module__
         if not hasattr(newfunc, 'compat_co_firstlineno'):
-            newfunc.compat_co_firstlineno = func.func_code.co_firstlineno
+            newfunc.compat_co_firstlineno = func.__code__.co_firstlineno
         try:
             newfunc.__name__ = name
         except TypeError:
diff --git a/nose/twistedtools.py b/nose/twistedtools.py
index 8d9c6ff..9239307 100644
--- a/nose/twistedtools.py
+++ b/nose/twistedtools.py
@@ -29,7 +29,7 @@ Or, more realistically::
 """
 
 import sys
-from Queue import Queue, Empty
+from queue import Queue, Empty
 from nose.tools import make_decorator, TimeExpired
 
 __all__ = [
@@ -166,7 +166,7 @@ def deferred(timeout=None):
             # Re-raise all exceptions
             if error is not None:
                 exc_type, exc_value, tb = error
-                raise exc_type, exc_value, tb
+                raise exc_type(exc_value).with_traceback(tb)
         wrapper = make_decorator(func)(wrapper)
         return wrapper
     return decorate
diff --git a/nose/util.py b/nose/util.py
index 21770ae..c38e5e0 100644
--- a/nose/util.py
+++ b/nose/util.py
@@ -151,7 +151,7 @@ def func_lineno(func):
         return func.compat_co_firstlineno
     except AttributeError:
         try:
-            return func.func_code.co_firstlineno
+            return func.__code__.co_firstlineno
         except AttributeError:
             return -1
 
@@ -400,7 +400,7 @@ def test_address(test):
         file = getattr(test, '__file__', None)
         module = getattr(test, '__name__', None)
         return (src(file), module, call)
-    if t == types.FunctionType or issubclass(t, type) or t == types.ClassType:
+    if t == types.FunctionType or issubclass(t, type) or t == type:
         module = getattr(test, '__module__', None)
         if module is not None:
             m = sys.modules[module]
@@ -410,7 +410,7 @@ def test_address(test):
         call = getattr(test, '__name__', None)
         return (src(file), module, call)
     if t == types.MethodType:
-        cls_adr = test_address(test.im_class)
+        cls_adr = test_address(test.__self__.__class__)
         return (src(cls_adr[0]), cls_adr[1],
                 "%s.%s" % (cls_adr[2], test.__name__))
     # handle unittest.TestCase instances
@@ -552,7 +552,7 @@ class odict(dict):
             self._keys.append(key)
 
     def __str__(self):
-        return "{%s}" % ', '.join(["%r: %r" % (k, v) for k, v in self.items()])
+        return "{%s}" % ', '.join(["%r: %r" % (k, v) for k, v in list(self.items())])
 
     def clear(self):
         super(odict, self).clear()
@@ -564,7 +564,7 @@ class odict(dict):
         return d
 
     def items(self):
-        return zip(self._keys, self.values())
+        return list(zip(self._keys, list(self.values())))
 
     def keys(self):
         return self._keys[:]
@@ -577,12 +577,12 @@ class odict(dict):
 
     def update(self, dict):
         super(odict, self).update(dict)
-        for key in dict.keys():
+        for key in list(dict.keys()):
             if key not in self._keys:
                 self._keys.append(key)
 
     def values(self):
-        return map(self.get, self._keys)
+        return list(map(self.get, self._keys))
 
 
 def transplant_func(func, module):
@@ -654,7 +654,7 @@ def safe_str(val, encoding='utf-8'):
         if isinstance(val, Exception):
             return ' '.join([safe_str(arg, encoding)
                              for arg in val])
-        return unicode(val).encode(encoding)
+        return str(val).encode(encoding)
 
 
 def is_executable(file):
diff --git a/patch.py b/patch.py
index 981097c..1152e8d 100644
--- a/patch.py
+++ b/patch.py
@@ -26,7 +26,7 @@ import sys
 
 try:
   # cStringIO doesn't support unicode in 2.5
-  from StringIO import StringIO
+  from io import StringIO
 except ImportError:
   # StringIO has been renamed to 'io' in 3.x
   from io import StringIO
@@ -48,7 +48,7 @@ else:
     # Python 3.x has changed iter.next() to be next(iter) instead, so for
     # backwards compatibility, we'll just define a next() function under 2.x
     def next(iter):
-        return iter.next()
+        return iter.__next__()
 
 
 #------------------------------------------------
diff --git a/unit_tests/mock.py b/unit_tests/mock.py
index 9da9e12..3f8868e 100644
--- a/unit_tests/mock.py
+++ b/unit_tests/mock.py
@@ -28,27 +28,27 @@ class ResultProxy(proxy.ResultProxy):
         self.assertMyTest(test)
         self.called.append(('beforeTest', test))
     def startTest(self, test):
-        print "proxy startTest"
+        print("proxy startTest")
         self.assertMyTest(test)
         self.called.append(('startTest', test))
     def stopTest(self, test):
-        print "proxy stopTest"
+        print("proxy stopTest")
         self.assertMyTest(test)
         self.called.append(('stopTest', test))
     def addDeprecated(self, test, err):
-        print "proxy addDeprecated"
+        print("proxy addDeprecated")
         self.assertMyTest(test)
         self.called.append(('addDeprecated', test, err))
     def addError(self, test, err):
-        print "proxy addError"
+        print("proxy addError")
         self.assertMyTest(test)
         self.called.append(('addError', test, err))
     def addFailure(self, test, err):
-        print "proxy addFailure"
+        print("proxy addFailure")
         self.assertMyTest(test)
         self.called.append(('addFailure', test, err))
     def addSkip(self, test, err):
-        print "proxy addSkip"
+        print("proxy addSkip")
         self.assertMyTest(test)
         self.called.append(('addSkip', test, err))
     def addSuccess(self, test):
@@ -72,7 +72,7 @@ class RecordingPluginManager(object):
         self.called = odict()
 
     def calls(self):
-        return self.called.keys()
+        return list(self.called.keys())
 
 
 class RecordingPluginProxy(object):
@@ -92,7 +92,7 @@ class Bucket(object):
         self.__dict__['d'].update(kw)
         
     def __getattr__(self, attr):
-        if not self.__dict__.has_key('d'):
+        if 'd' not in self.__dict__:
             return None
         return self.__dict__['d'].get(attr)
 
diff --git a/unit_tests/support/issue135/tests.py b/unit_tests/support/issue135/tests.py
index f76f4fa..d312e41 100644
--- a/unit_tests/support/issue135/tests.py
+++ b/unit_tests/support/issue135/tests.py
@@ -2,5 +2,5 @@ import unittest
 
 class TestIssue135(unittest.TestCase):
     def test_issue135(self):
-        print "something"
+        print("something")
         raise KeyError("fake")
\ No newline at end of file
diff --git a/unit_tests/support/script.py b/unit_tests/support/script.py
index 9e33d77..26772f5 100755
--- a/unit_tests/support/script.py
+++ b/unit_tests/support/script.py
@@ -1,3 +1,3 @@
 #!/usr/bin/env python
 
-print "FAIL"
+print("FAIL")
diff --git a/unit_tests/test_bug105.py b/unit_tests/test_bug105.py
index e0362a8..0c007b0 100644
--- a/unit_tests/test_bug105.py
+++ b/unit_tests/test_bug105.py
@@ -10,8 +10,8 @@ class TestBug105(unittest.TestCase):
                                              'support', 'bug105'))
 
         l = TestLoader()
-        testmod = l.loadTestsFromDir(where).next()
-        print testmod
+        testmod = next(l.loadTestsFromDir(where))
+        print(testmod)
         testmod.setUp()
 
         def fix(t):
@@ -20,8 +20,8 @@ class TestBug105(unittest.TestCase):
                 return s[s.index(': ')+2:]
             return s
         
-        tests = map(fix, testmod)
-        print tests
+        tests = list(map(fix, testmod))
+        print(tests)
         self.assertEqual(tests, ['tests.test_z', 'tests.test_a',
                                  'tests.test_dz', 'tests.test_mdz',
                                  'tests.test_b'])
diff --git a/unit_tests/test_capture_plugin.py b/unit_tests/test_capture_plugin.py
index c8cff82..534f84f 100644
--- a/unit_tests/test_capture_plugin.py
+++ b/unit_tests/test_capture_plugin.py
@@ -57,14 +57,14 @@ class TestCapturePlugin(unittest.TestCase):
     def test_captures_stdout(self):
         c = Capture()
         c.start()
-        print "Hello"
+        print("Hello")
         c.end()
         self.assertEqual(c.buffer, "Hello\n")
         
     def test_captures_nonascii_stdout(self):
         c = Capture()
         c.start()
-        print "test 日本"
+        print("test 日本")
         c.end()
         self.assertEqual(c.buffer, "test 日本\n")
 
@@ -76,8 +76,8 @@ class TestCapturePlugin(unittest.TestCase):
         c.start()
         printed_nonascii_str = force_unicode("test 日本").encode('utf-8')
         printed_unicode = force_unicode("Hello")
-        print printed_nonascii_str
-        print printed_unicode
+        print(printed_nonascii_str)
+        print(printed_unicode)
         try:
             raise Exception("boom")
         except:
@@ -104,7 +104,7 @@ class TestCapturePlugin(unittest.TestCase):
         c = Capture()
         c.start()
         try:
-            print "Oh my!"
+            print("Oh my!")
             raise Exception("boom")
         except:
             err = sys.exc_info()
@@ -125,8 +125,8 @@ class TestCapturePlugin(unittest.TestCase):
         c = Capture()
         c.start()
         try:
-            print "debug 日本"
-            raise AssertionError(u'response does not contain 名')
+            print("debug 日本")
+            raise AssertionError('response does not contain 名')
         except:
             err = sys.exc_info()
         formatted = c.formatError(d, err)
diff --git a/unit_tests/test_cases.py b/unit_tests/test_cases.py
index af399e5..7df472f 100644
--- a/unit_tests/test_cases.py
+++ b/unit_tests/test_cases.py
@@ -40,8 +40,7 @@ class TestNoseCases(unittest.TestCase):
             def __new__(cls, name, bases, dct):
                 return type.__new__(cls, name, bases, dct)
         a = []
-        class TestClass(object):
-            __metaclass__ = TestType
+        class TestClass(object, metaclass=TestType):
             def test_func(self, a=a):
                 a.append(1)
 
@@ -124,13 +123,13 @@ class TestNoseTestWrapper(unittest.TestCase):
                         
         class TC(unittest.TestCase):
             def setUp(self):
-                print "TC setUp %s" % self
+                print("TC setUp %s" % self)
                 called.append('setUp')
             def runTest(self):
-                print "TC runTest %s" % self
+                print("TC runTest %s" % self)
                 called.append('runTest')
             def tearDown(self):
-                print "TC tearDown %s" % self
+                print("TC tearDown %s" % self)
                 called.append('tearDown')
 
         case = nose.case.Test(TC())
diff --git a/unit_tests/test_config_defaults.rst b/unit_tests/test_config_defaults.rst
index 034f58e..9b4673e 100644
--- a/unit_tests/test_config_defaults.rst
+++ b/unit_tests/test_config_defaults.rst
@@ -1,6 +1,6 @@
     >>> from optparse import OptionParser
     >>> import os
-    >>> from cStringIO import StringIO
+    >>> from io import StringIO
 
     >>> import nose.config
 
@@ -12,7 +12,7 @@ configuration files.  The configuration lives in a single section
     ...                        "config_defaults")
 
     >>> def error(msg):
-    ...     print "error: %s" % msg
+    ...     print("error: %s" % msg)
 
     >>> def get_parser():
     ...     parser = OptionParser()
@@ -129,18 +129,19 @@ Missing config files don't deserve an error or warning
 (filename)
 
     >>> options, args = parse([], os.path.join(support, "nonexistent.cfg"))
-    >>> print options.__dict__
+    >>> print(options.__dict__)
     {'verbosity': 1}
 
 (filenames)
 
     >>> options, args = parse([], [os.path.join(support, "nonexistent.cfg")])
-    >>> print options.__dict__
+    >>> print(options.__dict__)
     {'verbosity': 1}
 
 
 The same goes for missing config file section ("nosetests")
 
     >>> options, args = parse([], StringIO("[spam]\nfoo=bar\n"))
-    >>> print options.__dict__
+    >>> print(options.__dict__)
     {'verbosity': 1}
+
diff --git a/unit_tests/test_core.py b/unit_tests/test_core.py
index 94b9436..735285c 100644
--- a/unit_tests/test_core.py
+++ b/unit_tests/test_core.py
@@ -1,7 +1,7 @@
 import os
 import sys
 import unittest
-from cStringIO import StringIO
+from io import StringIO
 from optparse import OptionParser
 import nose.core
 from nose.config import Config, all_config_files
@@ -16,16 +16,16 @@ class NullLoader:
 class TestAPI_run(unittest.TestCase):
 
     def test_restore_stdout(self):
-        print "AHOY"
+        print("AHOY")
         s = StringIO()
-        print s
+        print(s)
         stdout = sys.stdout
         conf = Config(stream=s)
         # set_trace()
-        print "About to run"
+        print("About to run")
         res = nose.core.run(
             testLoader=NullLoader(), argv=['test_run'], env={}, config=conf)
-        print "Done running"
+        print("Done running")
         stdout_after = sys.stdout
         self.assertEqual(stdout, stdout_after)
 
diff --git a/unit_tests/test_deprecated_plugin.py b/unit_tests/test_deprecated_plugin.py
index 6c62481..e113016 100644
--- a/unit_tests/test_deprecated_plugin.py
+++ b/unit_tests/test_deprecated_plugin.py
@@ -2,7 +2,7 @@ import unittest
 from nose.config import Config
 from nose.plugins.deprecated import Deprecated, DeprecatedTest
 from nose.result import TextTestResult, _TextTestResult
-from StringIO import StringIO
+from io import StringIO
 from optparse import OptionParser
 try:
     # 2.7+
@@ -107,7 +107,7 @@ class TestDeprecatedPlugin(unittest.TestCase):
 
         res.printErrors()
         out = stream.getvalue()
-        print out
+        print(out)
         assert out
 
         assert ' ... DEPRECATED' in out
diff --git a/unit_tests/test_doctest_munging.rst b/unit_tests/test_doctest_munging.rst
index fdbce64..0441bee 100644
--- a/unit_tests/test_doctest_munging.rst
+++ b/unit_tests/test_doctest_munging.rst
@@ -28,13 +28,13 @@ an ellipsis.  Note the first line here is chosen not to be "Traceback
 the example should raise an exception!
 
     >>> from nose.plugins.plugintest import remove_stack_traces
-    >>> print remove_stack_traces("""\
+    >>> print(remove_stack_traces("""\
     ... Ceci n'est pas une traceback.
     ... Traceback (most recent call last):
     ...   File "/some/dir/foomodule.py", line 15, in runTest
     ...   File "/some/dir/spam.py", line 293, in who_knows_what
     ... AssertionError: something bad happened
-    ... """)
+    ... """))
     Ceci n'est pas une traceback.
     Traceback (most recent call last):
     ...
@@ -44,16 +44,16 @@ the example should raise an exception!
 Multiple tracebacks in an example are all replaced, as long as they're
 separated by blank lines.
 
-    >>> print remove_stack_traces("""\
+    >>> print(remove_stack_traces("""\
     ... Ceci n'est pas une traceback.
     ... Traceback (most recent call last):
     ...   File spam
     ... AttributeError: eggs
-    ...
+    ... 
     ... Traceback (most recent call last):
     ...   File eggs
     ... AttributeError: spam
-    ... """)
+    ... """))
     Ceci n'est pas une traceback.
     Traceback (most recent call last):
     ...
@@ -70,10 +70,10 @@ traces, removes test timings from "Ran n test(s)" output, and strips
 trailing blank lines.
 
     >>> from nose.plugins.plugintest import munge_nose_output_for_doctest
-    >>> print munge_nose_output_for_doctest("""\
+    >>> print(munge_nose_output_for_doctest("""\
     ... runTest (foomodule.PassingTest) ... ok
     ... runTest (foomodule.FailingTest) ... FAIL
-    ...
+    ... 
     ... ======================================================================
     ... FAIL: runTest (foomodule.FailingTest)
     ... ----------------------------------------------------------------------
@@ -81,14 +81,14 @@ trailing blank lines.
     ...   File "/some/dir/foomodule.py", line 15, in runTest
     ...   File "/some/dir/spam.py", line 293, in who_knows_what
     ... AssertionError: something bad happened
-    ...
+    ... 
     ... ----------------------------------------------------------------------
     ... Ran 1 test in 0.082s
-    ...
+    ... 
     ... FAILED (failures=1)
-    ...
-    ...
-    ... """)
+    ... 
+    ... 
+    ... """))
     runTest (foomodule.PassingTest) ... ok
     runTest (foomodule.FailingTest) ... FAIL
     <BLANKLINE>
@@ -103,3 +103,4 @@ trailing blank lines.
     Ran 1 test in ...s
     <BLANKLINE>
     FAILED (failures=1)
+
diff --git a/unit_tests/test_id_plugin.py b/unit_tests/test_id_plugin.py
index d70fc07..bb9173b 100644
--- a/unit_tests/test_id_plugin.py
+++ b/unit_tests/test_id_plugin.py
@@ -11,7 +11,7 @@ class TestTestIdPlugin(unittest.TestCase):
         opt = mock.Bucket()
         opt.testIdFile = '.noseids'
         tid.configure(opt, c)
-        print tid.idfile
+        print(tid.idfile)
         assert tid.idfile.startswith(c.workingDir), \
                "%s is not under %s" % (tid.idfile, c.workingDir)
 
diff --git a/unit_tests/test_inspector.py b/unit_tests/test_inspector.py
index bbc4b19..e9426d2 100644
--- a/unit_tests/test_inspector.py
+++ b/unit_tests/test_inspector.py
@@ -6,9 +6,9 @@ import traceback
 import unittest
 
 try:
-    from cStringIO import StringIO
+    from io import StringIO
 except ImportError:
-    from StringIO import StringIO
+    from io import StringIO
 
 from nose.inspector import inspect_traceback, Expander, tbsource
 
@@ -52,7 +52,7 @@ class TestExpander(unittest.TestCase):
     def test_get_tb_source_func(self):        
         # func frame
         def check_even(n):
-            print n
+            print(n)
             assert n % 2 == 0
         try:
             check_even(1)
@@ -108,14 +108,14 @@ class TestExpander(unittest.TestCase):
         S = {'setup':1}
         def check_even(n, nn):
             assert S['setup']
-            print n, nn
+            print(n, nn)
             assert n % 2 == 0 or nn % 2 == 0
         try:
             check_even(1, 3)
         except AssertionError:
             et, ev, tb = sys.exc_info()
             out = inspect_traceback(tb)
-            print "'%s'" % out.strip()
+            print("'%s'" % out.strip())
             if sys.version_info < (3,):
                 print_line = "    print 1, 3\n"
             else:
@@ -136,7 +136,7 @@ class TestExpander(unittest.TestCase):
         except AssertionError:
             et, ev, tb = sys.exc_info()
             out = inspect_traceback(tb)
-            print "'%s'" % out.strip()
+            print("'%s'" % out.strip())
             self.assertEqual(out.strip(),
                              "2 = 2\n"
                              ">>  assert 2 == 4")
diff --git a/unit_tests/test_issue135.py b/unit_tests/test_issue135.py
index de330ab..7f39356 100644
--- a/unit_tests/test_issue135.py
+++ b/unit_tests/test_issue135.py
@@ -4,7 +4,7 @@ from nose import main
 import sys
 import re
 try:
-    from StringIO import StringIO
+    from io import StringIO
 except ImportError:
     from io import BytesIO as StringIO
 
diff --git a/unit_tests/test_issue155.rst b/unit_tests/test_issue155.rst
index 450866a..1e6dbb6 100644
--- a/unit_tests/test_issue155.rst
+++ b/unit_tests/test_issue155.rst
@@ -11,18 +11,18 @@ handling intended to ignore the case where the method is not present.
     >>> import nose.plugins.doctests
 
     >>> class Result(nose.result.TextTestResult):
-    ...
+    ... 
     ...     def afterTest(self, test):
     ...         raise AttributeError("bug in Result")
-    ...
+    ... 
     ...     def beforeTest(self, test):
     ...         raise AttributeError("bug in Result")
 
     >>> class TestCase(unittest.TestCase):
-    ...
+    ... 
     ...     def address(self):
     ...         raise AttributeError("bug in TestCase")
-    ...
+    ... 
     ...     def runTest(self):
     ...         pass
 
@@ -44,3 +44,4 @@ handling intended to ignore the case where the method is not present.
     >>> nose.util.test_address(test)
     Traceback (most recent call last):
     AttributeError: bug in TestCase
+
diff --git a/unit_tests/test_issue_006.py b/unit_tests/test_issue_006.py
index d04c174..3290ef4 100644
--- a/unit_tests/test_issue_006.py
+++ b/unit_tests/test_issue_006.py
@@ -9,11 +9,11 @@ class TestIssue006(unittest.TestCase):
         where = os.path.abspath(os.path.join(os.path.dirname(__file__),
                                              'support', 'issue006'))
         l = TestLoader()
-        testmod = iter(l.loadTestsFromName(where)).next()
-        print testmod
+        testmod = next(iter(l.loadTestsFromName(where)))
+        print(testmod)
         testmod.setUp()
 
-        testcase = iter(testmod).next()
+        testcase = next(iter(testmod))
         expect = [
             ['tests.Test1.test_nested_generator'],
             ['tests.Test1.test_nested_generator_mult(1,)',
@@ -23,8 +23,8 @@ class TestIssue006(unittest.TestCase):
              'tests.Test1.test_normal_generator(2,)']
             ]
         for test in testcase:
-            tests = map(str, test)
-            print tests
+            tests = list(map(str, test))
+            print(tests)
             self.assertEqual(tests, expect.pop(0))
 
 if __name__ == '__main__':
diff --git a/unit_tests/test_issue_227.py b/unit_tests/test_issue_227.py
index 140862e..276fe04 100644
--- a/unit_tests/test_issue_227.py
+++ b/unit_tests/test_issue_227.py
@@ -9,4 +9,4 @@ def setup():
 
 
 def test_unicode():
-    print u'b\u00f6y'
+    print('b\u00f6y')
diff --git a/unit_tests/test_issue_230.py b/unit_tests/test_issue_230.py
index 41a717b..4f8e844 100644
--- a/unit_tests/test_issue_230.py
+++ b/unit_tests/test_issue_230.py
@@ -13,7 +13,7 @@ class TestIssue230(unittest.TestCase):
 
         loader = TestLoader()
         suite = loader.loadTestsFromGenerator(gen, module=None)
-        testcase = iter(suite).next()
+        testcase = next(iter(suite))
         self.assertEqual(testcase.test.test, test)
 
 
diff --git a/unit_tests/test_loader.py b/unit_tests/test_loader.py
index aee7681..b2fd2dd 100644
--- a/unit_tests/test_loader.py
+++ b/unit_tests/test_loader.py
@@ -51,8 +51,7 @@ def mods():
     class TCType(type):
         def __new__(cls, name, bases, dct):
             return type.__new__(cls, name, bases, dct)
-    class TestMetaclassed(object):
-        __metaclass__ = TCType
+    class TestMetaclassed(object, metaclass=TCType):
         def test_one(self):
             pass
         def test_two(self):
@@ -182,13 +181,13 @@ def mock_listdir(path):
 
 
 def mock_isdir(path):
-    print "is dir '%s'?" % path
-    paths = map(safepath, [
+    print("is dir '%s'?" % path)
+    paths = list(map(safepath, [
         '/a/dir/path', '/package',
         '/package/subpackage', '/sort/lib',
         '/sort/src', '/sort/a_test',
-        '/sort/test', '/sort'])
-    paths = paths + map(os.path.abspath, paths)
+        '/sort/test', '/sort']))
+    paths = paths + list(map(os.path.abspath, paths))
     if path in paths:
         return True
     return False
@@ -201,12 +200,12 @@ def mock_isfile(path):
 
 
 def mock_exists(path):
-    print "exists '%s'?" % path
-    paths = map(safepath, [
+    print("exists '%s'?" % path)
+    paths = list(map(safepath, [
         '/package', '/package/__init__.py', '/package/subpackage',
         '/package/subpackage/__init__.py'
-        ])
-    paths = paths + map(os.path.abspath, paths)
+        ]))
+    paths = paths + list(map(os.path.abspath, paths))
     return path in paths
 
 
@@ -270,35 +269,35 @@ class TestTestLoader(unittest.TestCase):
         l.loadTestsFromNames
 
     def test_load_from_name_dir_abs(self):
-        print "load from name dir"
+        print("load from name dir")
         l = self.l
         suite = l.loadTestsFromName(safepath('/a/dir/path'))
         tests = [t for t in suite]
         self.assertEqual(len(tests), 1)
 
     def test_load_from_name_module_filename(self):
-        print "load from name module filename"
+        print("load from name module filename")
         l = self.l
         suite = l.loadTestsFromName('test_module.py')
         tests = [t for t in suite]
         assert tests
 
     def test_load_from_name_module(self):
-        print "load from name module"
+        print("load from name module")
         l = self.l
         suite = l.loadTestsFromName('test_module')
         tests = [t for t in suite]
         assert tests            
 
     def test_load_from_name_nontest_module(self):
-        print "load from name nontest module"
+        print("load from name nontest module")
         l = self.l
         suite = l.loadTestsFromName('module')
         tests = [t for t in suite]
         assert tests
 
     def test_load_from_name_method(self):
-        print "load from name method"
+        print("load from name method")
         res = unittest.TestResult()
         l = self.l
         suite = l.loadTestsFromName(':TC.runTest')
@@ -310,11 +309,11 @@ class TestTestLoader(unittest.TestCase):
                "Expected a ValueError for unresolvable test name, got none"
 
     def test_load_from_name_module_class(self):
-        print "load from name module class"
+        print("load from name module class")
         l = self.l
         suite = l.loadTestsFromName('test_module:TC')
         tests = [t for t in suite]
-        print tests
+        print(tests)
         assert tests
         assert len(tests) == 1, \
                "Should have loaded 1 test, but got %s" % tests
@@ -322,10 +321,10 @@ class TestTestLoader(unittest.TestCase):
         # the item in tests is a suite, we want to check that all of
         # the members of the suite are wrapped -- though this is really
         # a suite test and doesn't belong here..
-        assert filter(lambda t: isinstance(t, nose.case.Test), tests[0])
+        assert [t for t in tests[0] if isinstance(t, nose.case.Test)]
 
     def test_load_from_name_module_func(self):
-        print "load from name module func"
+        print("load from name module func")
         l = self.l
         suite = l.loadTestsFromName('test_module:test_func')
         tests = [t for t in suite]
@@ -336,7 +335,7 @@ class TestTestLoader(unittest.TestCase):
                "Expected FunctionTestCase not %s" % tests[0].test
 
     def test_load_from_name_module_method(self):
-        print "load from name module method"
+        print("load from name module method")
         l = self.l
         suite = l.loadTestsFromName('test_module:TC.runTest')
         tests = [t for t in suite]
@@ -345,7 +344,7 @@ class TestTestLoader(unittest.TestCase):
                "Should have loaded 1 test, but got %s" % tests
 
     def test_load_from_name_module_missing_class(self):
-        print "load from name module missing class"
+        print("load from name module missing class")
         res = unittest.TestResult()
         l = self.l
         suite = l.loadTestsFromName('test_module:TC2')
@@ -356,7 +355,7 @@ class TestTestLoader(unittest.TestCase):
         assert res.errors, "Expected missing class test to raise exception"
 
     def test_load_from_name_module_missing_func(self):
-        print "load from name module missing func"
+        print("load from name module missing func")
         res = unittest.TestResult()
         l = self.l
         suite = l.loadTestsFromName('test_module:test_func2')
@@ -367,7 +366,7 @@ class TestTestLoader(unittest.TestCase):
         assert res.errors, "Expected missing func test to raise exception"
 
     def test_load_from_name_module_missing_method(self):
-        print "load from name module missing method"
+        print("load from name module missing method")
         res = unittest.TestResult()
         l = self.l
         suite = l.loadTestsFromName('test_module:TC.testThat')
@@ -378,7 +377,7 @@ class TestTestLoader(unittest.TestCase):
         assert res.errors, "Expected missing method test to raise exception"
 
     def test_load_from_name_module_transplanted_class_missing_method(self):
-        print "load from name module transplanted class missing method"
+        print("load from name module transplanted class missing method")
         res = unittest.TestResult()
         l = self.l
         suite = l.loadTestsFromName('test_transplant:Transplant.testThat')
@@ -389,7 +388,7 @@ class TestTestLoader(unittest.TestCase):
         assert res.errors, "Expected missing method test to raise exception"
 
     def test_load_from_name_missing_module(self):
-        print "load from name missing module"
+        print("load from name missing module")
         res = unittest.TestResult()
         l = self.l
         suite = l.loadTestsFromName('other_test_module')
@@ -400,27 +399,27 @@ class TestTestLoader(unittest.TestCase):
         assert res.errors, "Expected missing module test to raise exception"
 
     def test_cases_from_testcase_are_wrapped(self):
-        print "cases from testcase are wrapped"
+        print("cases from testcase are wrapped")
         test_module = M['test_module']
         l = self.l
         suite = l.loadTestsFromTestCase(test_module.TC)
-        print suite
+        print(suite)
         tests = [t for t in suite]
         for test in tests:
             assert isinstance(test, nose.case.Test), \
                    "Test %r is not a test wrapper" % test
 
     def test_load_test_func(self):
-        print "load test func"
+        print("load test func")
         l = self.l
         suite = l.loadTestsFromName('test_module')
         tests = [t for t in suite]
         self.assertEqual(len(tests), 2, "Wanted 2 tests, got %s" % tests)
-        assert filter(lambda t: isinstance(t, nose.case.Test), tests)
-        print tests
+        assert [t for t in tests if isinstance(t, nose.case.Test)]
+        print(tests)
         class_tests = tests[0]
         for t in class_tests:
-            print "class test: ", t
+            print("class test: ", t)
         func_tests = tests[1:]
         assert class_tests, \
                "Expected class suite got %s" % class_tests
@@ -434,25 +433,25 @@ class TestTestLoader(unittest.TestCase):
                    "Expected FunctionTestCase not %s" % tests[1].test
 
     def test_load_from_name_package_root_path(self):
-        print "load from name package root path"
+        print("load from name package root path")
         l = self.l
         suite = l.loadTestsFromName(safepath('/package'))
-        print suite
+        print(suite)
         tests = [t for t in suite]
         assert len(tests) == 1, "Expected one test, got %s" % tests
         tests = list(tests[0])
         assert not tests, "The full test list %s was not empty" % tests
 
     def test_load_from_name_subpackage_safepath(self):
-        print "load from name subpackage path"
+        print("load from name subpackage path")
         l = self.l
         suite = l.loadTestsFromName(safepath('/package/subpackage'))
-        print suite
+        print(suite)
         tests = [t for t in suite]
         assert len(tests) == 0, "Expected no tests, got %s" % tests
     
     def test_load_metaclass_customized_classes(self):
-        print "load metaclass-customized classes"
+        print("load metaclass-customized classes")
         test_module_with_generators = M['test_module_with_metaclass_tests']
         l = self.l
         suite = l.loadTestsFromModule(test_module_with_generators)
@@ -461,21 +460,21 @@ class TestTestLoader(unittest.TestCase):
         self.assertEqual(len(tc_methods), 2)
 
     def test_load_generators(self):
-        print "load generators"
+        print("load generators")
         test_module_with_generators = M['test_module_with_generators']
         l = self.l
         suite = l.loadTestsFromModule(test_module_with_generators)
         tests = [t for t in suite]
 
         for t in tests:
-            print "test", t
+            print("test", t)
             assert isinstance(t, unittest.TestSuite), \
                    "Test %s is not a suite" % t
 
         # the first item is a class, with both normal and generator methods
         count = 0
         cl_tests = [t for t in tests[0]]
-        print "class tests", cl_tests
+        print("class tests", cl_tests)
         normal, gens = cl_tests[0], cl_tests[1:]
         assert isinstance(normal, nose.case.Test), \
                "Expected a test case but got %s" % normal
@@ -484,8 +483,8 @@ class TestTestLoader(unittest.TestCase):
                    "Expected a generator test suite, but got %s" % gen
             count = 0
             for t in gen:
-                print "generated test %s" % t
-                print t.shortDescription()
+                print("generated test %s" % t)
+                print(t.shortDescription())
                 assert isinstance(t, nose.case.Test), \
                        "Test %s is not a test?" % t
                 count += 1
@@ -495,8 +494,8 @@ class TestTestLoader(unittest.TestCase):
         # 2nd item is generated from test_func_generator
         count = 0
         for t in tests[1]:
-            print "generated test %s" % t
-            print t.shortDescription()
+            print("generated test %s" % t)
+            print(t.shortDescription())
             assert isinstance(t, nose.case.Test), \
                    "Test %s is not a Test?" % t
             assert isinstance(t.test, nose.case.FunctionTestCase), \
@@ -513,8 +512,8 @@ class TestTestLoader(unittest.TestCase):
 
         count = 0
         for t in tests[2]:
-            print "generated test %s" % t
-            print t.shortDescription()
+            print("generated test %s" % t)
+            print(t.shortDescription())
             assert isinstance(t, nose.case.Test), \
                    "Test %s is not a Test?" % t
             assert isinstance(t.test, nose.case.FunctionTestCase), \
@@ -530,21 +529,21 @@ class TestTestLoader(unittest.TestCase):
                "Expected to generate 4 tests, but got %s" % count
 
     def test_load_transplanted_generator(self):
-        print "load transplanted generator (issue 501)"
+        print("load transplanted generator (issue 501)")
         test_module_transplant_generator = M['test_module_transplant_generator']
         l = self.l
         suite = l.loadTestsFromModule(test_module_transplant_generator)
         tests = [t for t in suite]
 
         assert len(tests) == 1
-        print "test", tests[0]
+        print("test", tests[0])
         assert isinstance(tests[0], unittest.TestSuite), \
             "Test is not a suite - probably did not look like a generator"
 
         count = 0
         for t in tests[0]:
-            print "generated test %s" % t
-            print t.shortDescription()
+            print("generated test %s" % t)
+            print(t.shortDescription())
             assert isinstance(t, nose.case.Test), \
                    "Test %s is not a Test?" % t
             assert isinstance(t.test, nose.case.FunctionTestCase), \
diff --git a/unit_tests/test_logcapture_plugin.py b/unit_tests/test_logcapture_plugin.py
index 63aa651..7b0f3c6 100644
--- a/unit_tests/test_logcapture_plugin.py
+++ b/unit_tests/test_logcapture_plugin.py
@@ -181,7 +181,7 @@ class TestLogCapturePlugin(object):
         parser = OptionParser()
         c.addOptions(parser, env)
         options, args = parser.parse_args(['foo'])
-        print options, args
+        print(options, args)
         c.configure(options, Config())
         c.start()
         for name in ['foobar.something', 'foo', 'foo.x', 'abara', 'bar.quux']:
@@ -200,7 +200,7 @@ class TestLogCapturePlugin(object):
         parser = OptionParser()
         c.addOptions(parser, env)
         options, args = parser.parse_args(['foo'])
-        print options, args
+        print(options, args)
         c.configure(options, Config())
         c.start()
         for name in ['foobar.something', 'foo', 'foo.x', 'abara', 'bar.quux']:
@@ -218,7 +218,7 @@ class TestLogCapturePlugin(object):
         parser = OptionParser()
         c.addOptions(parser, env)
         options, args = parser.parse_args(['foo'])
-        print options, args
+        print(options, args)
         c.configure(options, Config())
         c.start()
         for name in ['foo.yes', 'foo.bar', 'foo.bar.no', 'blah']:
@@ -230,7 +230,7 @@ class TestLogCapturePlugin(object):
         assert records[0].startswith('foo.yes:'), records[0]
 
     def test_unicode_messages_handled(self):
-        msg = u'Ivan Krsti\u0107'
+        msg = 'Ivan Krsti\u0107'
         c = LogCapture()
         parser = OptionParser()
         c.addOptions(parser, {})
@@ -250,7 +250,7 @@ class TestLogCapturePlugin(object):
         except:
             err = sys.exc_info()
         (ec, ev, tb) = c.formatError(test, err)
-        print ev
+        print(ev)
         if UNICODE_STRINGS:
             assert msg in ev
         else:
diff --git a/unit_tests/test_ls_tree.rst b/unit_tests/test_ls_tree.rst
index 260c641..29b9b05 100644
--- a/unit_tests/test_ls_tree.rst
+++ b/unit_tests/test_ls_tree.rst
@@ -7,7 +7,7 @@
     >>> dir_path = tempfile.mkdtemp()
 
     >>> def create_file(filename):
-    ...     fd = os.open(filename, os.O_WRONLY|os.O_CREAT, 0666)
+    ...     fd = os.open(filename, os.O_WRONLY|os.O_CREAT, 0o666)
     ...     os.close(fd)
 
     >>> os.mkdir(os.path.join(dir_path, "top"))
@@ -32,7 +32,7 @@
     Note that files matching skip_pattern (by default SVN files,
     backup files and compiled Python files) are ignored
 
-    >>> print ls_tree(os.path.join(dir_path, "top"))
+    >>> print(ls_tree(os.path.join(dir_path, "top")))
     |-- file
     |-- file2
     |-- .notsvn
@@ -48,3 +48,4 @@
     `-- dir3
 
     >>> shutil.rmtree(dir_path)
+
diff --git a/unit_tests/test_multiprocess_runner.py b/unit_tests/test_multiprocess_runner.py
index 2e22c8e..a9fd2a9 100644
--- a/unit_tests/test_multiprocess_runner.py
+++ b/unit_tests/test_multiprocess_runner.py
@@ -30,7 +30,7 @@ class TestMultiProcessTestRunner(unittest.TestCase):
         l = TestLoader()
         tests = list(r.nextBatch(ContextSuite(
                     tests=[l.makeTest(T_fixt), l.makeTest(T)])))
-        print tests
+        print(tests)
         self.assertEqual(len(tests), 3)
 
     def test_next_batch_with_module_fixt(self):
@@ -50,7 +50,7 @@ class TestMultiProcessTestRunner(unittest.TestCase):
         r = multiprocess.MultiProcessTestRunner()
         l = TestLoader()
         tests = list(r.nextBatch(l.loadTestsFromModule(mod_with_fixt)))
-        print tests
+        print(tests)
         self.assertEqual(len(tests), 1)
 
     def test_next_batch_with_module(self):
@@ -71,7 +71,7 @@ class TestMultiProcessTestRunner(unittest.TestCase):
         r = multiprocess.MultiProcessTestRunner()
         l = TestLoader()
         tests = list(r.nextBatch(l.loadTestsFromModule(mod_no_fixt)))
-        print tests
+        print(tests)
         self.assertEqual(len(tests), 3)
 
     def test_next_batch_with_generator_method(self):
@@ -84,8 +84,8 @@ class TestMultiProcessTestRunner(unittest.TestCase):
         r = multiprocess.MultiProcessTestRunner()
         l = TestLoader()
         tests = list(r.nextBatch(l.makeTest(Tg)))
-        print tests
-        print [r.address(t) for t in tests]
+        print(tests)
+        print([r.address(t) for t in tests])
         self.assertEqual(len(tests), 1)
 
     def test_next_batch_can_split_set(self):
@@ -112,7 +112,7 @@ class TestMultiProcessTestRunner(unittest.TestCase):
         r = multiprocess.MultiProcessTestRunner()
         l = TestLoader()
         tests = list(r.nextBatch(l.loadTestsFromModule(mod_with_fixt2)))
-        print tests
+        print(tests)
         self.assertEqual(len(tests), 3)
         
             
diff --git a/unit_tests/test_pdb_plugin.py b/unit_tests/test_pdb_plugin.py
index cdd43f2..aac3b2e 100644
--- a/unit_tests/test_pdb_plugin.py
+++ b/unit_tests/test_pdb_plugin.py
@@ -3,7 +3,7 @@ import unittest
 from nose.config import Config
 from nose.plugins import debug
 from optparse import OptionParser
-from StringIO import StringIO
+from io import StringIO
 
 class StubPdb:
     called = False
diff --git a/unit_tests/test_plugin_manager.py b/unit_tests/test_plugin_manager.py
index 578ce03..32b6a9f 100644
--- a/unit_tests/test_plugin_manager.py
+++ b/unit_tests/test_plugin_manager.py
@@ -44,7 +44,7 @@ class TestPluginManager(unittest.TestCase):
         # multiple proxy: all plugins that return values get to run
         all = []
         for res in man.loadTestsFromFile('foo'):
-            print res
+            print(res)
             all.append(res)
         self.assertEqual(len(all), 2)
 
diff --git a/unit_tests/test_plugins.py b/unit_tests/test_plugins.py
index b4f91c8..a4c3143 100644
--- a/unit_tests/test_plugins.py
+++ b/unit_tests/test_plugins.py
@@ -99,16 +99,16 @@ class TestDoctestPlugin(unittest.TestCase):
         dtp.add_options(parser, env)
         options, args = parser.parse_args(argv)
         
-        print options
-        print args
+        print(options)
+        print(args)
         self.assertEqual(options.doctestExtension, ['ext', 'txt'])
 
         env = {}
         parser = OptionParser()
         dtp.add_options(parser, env)
         options, args = parser.parse_args(argv)
-        print options
-        print args
+        print(options)
+        print(args)
         self.assertEqual(options.doctestExtension, ['txt'])
             
     def test_want_file(self):
@@ -171,12 +171,12 @@ class TestDoctestPlugin(unittest.TestCase):
         plug.configure(opt, conf)
         suite = plug.loadTestsFromModule(foo.bar.buz)
         for test in suite:
-            print test.address()
+            print(test.address())
             file, mod, call = test.address()
             self.assertEqual(mod, 'foo.bar.buz')
             self.assertEqual(call, None)
             for case in test:
-                print case.address()
+                print(case.address())
                 file, mod, call = case.address()
                 self.assertEqual(mod, 'foo.bar.buz')
                 self.assertEqual(call, 'afunc')
@@ -334,7 +334,7 @@ class TestAttribPlugin(unittest.TestCase):
         # OR
         opt, args = parser.parse_args(['test', '-a', 'tags=a',
                                        '-a', 'tags=b'])
-        print opt
+        print(opt)
         plug.configure(opt, cnf)
 
         assert plug.wantFunction(f1) is None
@@ -344,7 +344,7 @@ class TestAttribPlugin(unittest.TestCase):
 
         # AND
         opt, args = parser.parse_args(['test', '-a', 'tags=a,tags=b'])
-        print opt
+        print(opt)
         plug.configure(opt, cnf)
 
         assert plug.wantFunction(f1) is None
diff --git a/unit_tests/test_result_proxy.py b/unit_tests/test_result_proxy.py
index 3d6e2ac..73146f2 100644
--- a/unit_tests/test_result_proxy.py
+++ b/unit_tests/test_result_proxy.py
@@ -76,8 +76,8 @@ class TestResultProxy(unittest.TestCase):
         class TC(unittest.TestCase):
             def run(self, result):
                 unittest.TestCase.run(self, result)
-                print "errors", result.errors
-                print "failures", result.failures
+                print("errors", result.errors)
+                print("failures", result.failures)
             def runTest(self):
                 pass
         test = TC()
@@ -103,10 +103,10 @@ class TestResultProxy(unittest.TestCase):
         res = unittest.TestResult()
         class TC(unittest.TestCase):
             def test_error(self):
-                print "So long"
+                print("So long")
                 raise TypeError("oops")
             def test_fail(self):
-                print "Hello"
+                print("Hello")
                 self.fail()
             def test(self):
                 pass
diff --git a/unit_tests/test_selector.py b/unit_tests/test_selector.py
index 73e1593..8401c3f 100644
--- a/unit_tests/test_selector.py
+++ b/unit_tests/test_selector.py
@@ -74,8 +74,8 @@ class TestSelector(unittest.TestCase):
         class TestType(type):
             def __new__(cls, name, bases, dct):
                 return type.__new__(cls, name, bases, dct)
-        class TestClass(object):
-            __metaclass__ = TestType
+        class TestClass(object, metaclass=TestType):
+            pass
         
         s = Selector(Config())
         assert not s.wantClass(Foo)
diff --git a/unit_tests/test_skip_plugin.py b/unit_tests/test_skip_plugin.py
index c1dccee..7aa97ce 100644
--- a/unit_tests/test_skip_plugin.py
+++ b/unit_tests/test_skip_plugin.py
@@ -2,7 +2,7 @@ import unittest
 from nose.config import Config
 from nose.plugins.skip import Skip, SkipTest
 from nose.result import TextTestResult
-from StringIO import StringIO
+from io import StringIO
 from nose.result import _TextTestResult
 from optparse import OptionParser
 try:
@@ -85,7 +85,7 @@ class TestSkipPlugin(unittest.TestCase):
 
         res.printErrors()
         out = stream.getvalue()
-        print out
+        print(out)
         assert out
         assert out.strip() == "S"
         assert res.wasSuccessful()
@@ -107,7 +107,7 @@ class TestSkipPlugin(unittest.TestCase):
 
         res.printErrors()
         out = stream.getvalue()
-        print out
+        print(out)
         assert out
 
         assert ' ... SKIP' in out
diff --git a/unit_tests/test_suite.py b/unit_tests/test_suite.py
index cdd391d..00feac6 100644
--- a/unit_tests/test_suite.py
+++ b/unit_tests/test_suite.py
@@ -43,13 +43,13 @@ class TestLazySuite(unittest.TestCase):
         lazytests = []
         nonlazytests = []
         for t in lazy:
-            print "lazy %s" % t
+            print("lazy %s" % t)
             lazytests.append(t)
         for t in nonlazy:
-            print "nonlazy %s" % t
+            print("nonlazy %s" % t)
             nonlazytests.append(t)
-        slazy = map(str, lazytests)
-        snonlazy = map(str, nonlazytests)
+        slazy = list(map(str, lazytests))
+        snonlazy = list(map(str, nonlazytests))
         assert slazy == snonlazy, \
                "Lazy and Nonlazy produced different test lists (%s vs %s)" \
                % (slazy, snonlazy)
@@ -70,7 +70,7 @@ class TestLazySuite(unittest.TestCase):
 
         count = 0
         for test in lazy:
-            print test
+            print(test)
             assert test
             count += 1
         self.assertEqual(count, 2, "Expected 2 tests, got %s" % count)
@@ -117,7 +117,7 @@ class TestContextSuite(unittest.TestCase):
         assert isinstance(tests[0], ContextSuite)
         # suite is full of wrapped tests
         tests = [t for t in tests[0]]
-        cases = filter(lambda t: isinstance(t, case.Test), tests)
+        cases = [t for t in tests if isinstance(t, case.Test)]
         assert cases
         assert len(cases) == len(tests)
 
diff --git a/unit_tests/test_tools.py b/unit_tests/test_tools.py
index 2a6451c..f5a6ad5 100644
--- a/unit_tests/test_tools.py
+++ b/unit_tests/test_tools.py
@@ -11,7 +11,7 @@ class TestTools(unittest.TestCase):
         ok_(True)
         try:
             ok_(False, "message")
-        except AssertionError, e:
+        except AssertionError as e:
             assert str(e) == "message"
         else:
             self.fail("ok_(False) did not raise assertion error")
@@ -20,13 +20,13 @@ class TestTools(unittest.TestCase):
         eq_(1, 1)
         try:
             eq_(1, 0, "message")
-        except AssertionError, e:
+        except AssertionError as e:
             assert str(e) == "message"
         else:
             self.fail("eq_(1, 0) did not raise assertion error")
         try:
             eq_(1, 0)
-        except AssertionError, e:
+        except AssertionError as e:
             assert str(e) == "1 != 0"
         else:
             self.fail("eq_(1, 0) did not raise assertion error")
@@ -37,7 +37,7 @@ class TestTools(unittest.TestCase):
         This lets tracebacks refrain from descending into the eq_ frame.
 
         """
-        assert '__unittest' in eq_.func_globals
+        assert '__unittest' in eq_.__globals__
 
     def test_istest_unittest_flag(self):
         """Make sure istest() is not in a namespace that has __unittest = 1.
@@ -45,7 +45,7 @@ class TestTools(unittest.TestCase):
         That is, make sure our __unittest labeling didn't get overzealous.
 
         """
-        assert '__unittest' not in istest.func_globals
+        assert '__unittest' not in istest.__globals__
 
     def test_raises(self):
         from nose.case import FunctionTestCase
@@ -66,14 +66,14 @@ class TestTools(unittest.TestCase):
         raise_good()
         try:
             raise_other()
-        except TypeError, e:
+        except TypeError as e:
             pass
         else:
             self.fail("raises did pass through unwanted exception")
 
         try:
             no_raise()
-        except AssertionError, e:
+        except AssertionError as e:
             pass
         else:
             self.fail("raises did not raise assertion error on no exception")
@@ -163,7 +163,7 @@ class TestTools(unittest.TestCase):
         import nose.tools
         tc_asserts = [ at for at in dir(nose.tools)
                        if at.startswith('assert_') ]
-        print tc_asserts
+        print(tc_asserts)
 
         # FIXME: not sure which of these are in all supported
         # versions of python
diff --git a/unit_tests/test_twisted.py b/unit_tests/test_twisted.py
index 562e547..1b7e6bf 100644
--- a/unit_tests/test_twisted.py
+++ b/unit_tests/test_twisted.py
@@ -29,7 +29,7 @@ test_resolve = deferred()(test_resolve)
 #@raises(TypeError)
 #@deferred()
 def test_raises_bad_return():
-    print reactor
+    print(reactor)
     reactor.resolve("www.python.org")
 test_raises_bad_return = raises(TypeError)(deferred()(test_raises_bad_return))
 
diff --git a/unit_tests/test_utils.py b/unit_tests/test_utils.py
index f329cbb..4544343 100644
--- a/unit_tests/test_utils.py
+++ b/unit_tests/test_utils.py
@@ -78,8 +78,7 @@ class TestUtils(unittest.TestCase):
 
         class CustomTestType(type):
             pass
-        class CustomTC(unittest.TestCase):
-            __metaclass__ = CustomTestType
+        class CustomTC(unittest.TestCase, metaclass=CustomTestType):
             def test_one(self):
                 pass
             def test_two(self):
@@ -128,10 +127,10 @@ class TestUtils(unittest.TestCase):
         # issue153 -- was not detecting custom typed classes...
         class TCType(type):
             pass
-        class TC_custom_type(object):
-            __metaclass__ = TCType
-        class TC_unittest_custom_type(unittest.TestCase):
-            __metaclass__ = TCType
+        class TC_custom_type(object, metaclass=TCType):
+            pass
+        class TC_unittest_custom_type(unittest.TestCase, metaclass=TCType):
+            pass
         
         assert util.isclass(TC), "failed to detect %s as class" % TC
         assert util.isclass(TC_Classic), "failed to detect %s as class" % TC_Classic
diff --git a/unit_tests/test_xunit.py b/unit_tests/test_xunit.py
index 560b9c2..ccd06fb 100644
--- a/unit_tests/test_xunit.py
+++ b/unit_tests/test_xunit.py
@@ -113,7 +113,7 @@ class TestXMLOutputWithXML(unittest.TestCase):
         self.x.addFailure(test, some_err)
 
         result = self.get_xml_report()
-        print result
+        print(result)
 
         if self.ET:
             tree = self.ET.fromstring(result)
@@ -157,7 +157,7 @@ class TestXMLOutputWithXML(unittest.TestCase):
         self.x.addFailure(test, some_err)
 
         result = self.get_xml_report()
-        print result
+        print(result)
 
         if self.ET:
             tree = self.ET.fromstring(result)
@@ -181,7 +181,7 @@ class TestXMLOutputWithXML(unittest.TestCase):
         self.x.addError(test, some_err)
 
         result = self.get_xml_report()
-        print result
+        print(result)
 
         if self.ET:
             tree = self.ET.fromstring(result)
@@ -223,7 +223,7 @@ class TestXMLOutputWithXML(unittest.TestCase):
             some_err = sys.exc_info()
         self.x.addError(test, some_err)
         result = self.get_xml_report()
-        print repr(result)
+        print(repr(result))
         if self.ET:
             tree = self.ET.fromstring(result)
             tc = tree.find("testcase")
@@ -233,7 +233,7 @@ class TestXMLOutputWithXML(unittest.TestCase):
                     '\x80')
             else:
                 eq_(err.attrib['message'],
-                    u'\ufffd')
+                    '\ufffd')
         else:
             # this is a dumb test for 2.4-
             assert 'RuntimeError: \xef\xbf\xbd' in result
@@ -252,7 +252,7 @@ class TestXMLOutputWithXML(unittest.TestCase):
         self.x.addError(test, some_err)
 
         result = self.get_xml_report()
-        print result
+        print(result)
 
         if self.ET:
             tree = self.ET.fromstring(result)
@@ -271,7 +271,7 @@ class TestXMLOutputWithXML(unittest.TestCase):
         self.x.addSuccess(test, (None,None,None))
 
         result = self.get_xml_report()
-        print result
+        print(result)
 
         if self.ET:
             tree = self.ET.fromstring(result)
@@ -300,7 +300,7 @@ class TestXMLOutputWithXML(unittest.TestCase):
         self.x.addSuccess(test, (None,None,None))
 
         result = self.get_xml_report()
-        print result
+        print(result)
 
         if self.ET:
             tree = self.ET.fromstring(result)
-- 
2.41.0

