--- a/nose/core.py	2015-04-04 10:52:52.000000000 +0200
+++ b/nose/core.py	2024-10-22 22:19:15.783743717 +0200
@@ -150,7 +150,7 @@
         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 @@
         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
--- a/nose/config.py	2015-04-04 10:52:52.000000000 +0200
+++ b/nose/config.py	2024-10-22 22:40:33.377710694 +0200
@@ -65,7 +65,7 @@
             cfg = ConfigParser.RawConfigParser()
             try:
                 cfg.read(filename)
-            except ConfigParser.Error, exc:
+            except( ConfigParser.Error, exc ) :
                 raise ConfigError("Error reading config file %r: %s" %
                                   (filename, str(exc)))
             config.extend(self._configTuples(cfg, filename))
@@ -79,7 +79,7 @@
             filename = '<???>'
         try:
             cfg.readfp(fh)
-        except ConfigParser.Error, exc:
+        except( ConfigParser.Error, exc ):
             raise ConfigError("Error reading config file %r: %s" %
                               (filename, str(exc)))
         return self._configTuples(cfg, filename)
@@ -113,12 +113,12 @@
                 continue
             try:
                 self._processConfigValue(name, value, values, parser)
-            except NoSuchOptionError, exc:
+            except( NoSuchOptionError, exc ):
                 self._file_error(
                     "Error reading config file %r: "
                     "no such option %r" % (filename, exc.name),
                     name=name, filename=filename)
-            except optparse.OptionValueError, exc:
+            except( optparse.OptionValueError, exc ):
                 msg = str(exc).replace('--' + name, repr(name), 1)
                 self._file_error("Error reading config file %r: "
                                  "%s" % (filename, msg),
@@ -128,12 +128,12 @@
         values = self._parser.get_default_values()
         try:
             config = self._readConfiguration(config_files)
-        except ConfigError, exc:
+        except( ConfigError, exc ):
             self._error(str(exc))
         else:
             try:
                 self._applyConfigurationToValues(self._parser, config, values)
-            except ConfigError, exc:
+            except( ConfigError, exc ):
                 self._error(str(exc))
         return self._parser.parse_args(args, values)
 
--- a/nose/ext/dtcompat.py	2024-10-23 07:43:46.184868230 +0200
+++ b/nose/ext/dtcompat.py	2024-10-23 07:52:47.698854233 +0200
@@ -341,9 +341,9 @@
 # [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__'):
@@ -683,7 +683,7 @@
 
     # This regular expression finds the indentation of every non-blank
     # line in a string.
-    _INDENT_RE = re.compile('^([ ]*)(?=\S)', re.MULTILINE)
+    _INDENT_RE = re.compile("^([ ]*)(?=\\S)", re.MULTILINE)
 
     def _min_indent(self, s):
         "Return the minimum indentation of any non-blank line in `s`"
@@ -875,7 +875,7 @@
         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:
@@ -1179,8 +1179,8 @@
             # 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) in test.globs )
                 self.debugger.set_continue() # ==== Example Finished ====
                 exception = None
             except KeyboardInterrupt:
@@ -1354,28 +1354,28 @@
                 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
 
     #/////////////////////////////////////////////////////////////////
@@ -1385,8 +1385,8 @@
         d = self._name2ft
         for name, (f, t) in 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 @@
     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):
@@ -2247,7 +2247,7 @@
             try:
                 execfile(srcfilename, 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
--- a/nose/failure.py	2024-10-23 07:43:46.183868230 +0200
+++ b/nose/failure.py	2024-10-23 07:58:46.423844961 +0200
@@ -36,7 +36,7 @@
     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( None, self.tb )
+            raise self.exc_class( self.exc_val, self.tb )
         else:
             raise self.exc_class(self.exc_val)
--- a/nose/inspector.py	2024-10-23 07:43:46.183868230 +0200
+++ b/nose/inspector.py	2024-10-23 07:58:15.625845757 +0200
@@ -38,7 +38,7 @@
         try:
             for tok in tokenize.generate_tokens(src.readline):
                 exp(*tok)
-        except tokenize.TokenError, e:
+        except( tokenize.TokenError, 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
--- a/nose/plugins/base.py	2024-10-23 07:43:46.184868230 +0200
+++ b/nose/plugins/base.py	2024-10-23 07:50:19.928858052 +0200
@@ -67,7 +67,7 @@
         try:
             self.options(parser, env)
             self.can_configure = True
-        except OptionConflictError, e:
+        except( OptionConflictError, e ):
             warn("Plugin %s has conflicting option string: %s and will "
                  "be disabled" % (self, e), RuntimeWarning)
             self.enabled = False
--- a/nose/plugins/cover.py	2024-10-23 07:43:46.184868230 +0200
+++ b/nose/plugins/cover.py	2024-10-23 07:49:47.027858903 +0200
@@ -194,14 +194,14 @@
             log.debug("Generating HTML coverage report")
             try:
                 self.coverInstance.html_report(modules, self.coverHtmlDir)
-            except coverage.misc.CoverageException, e:
+            except( coverage.misc.CoverageException, 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, e ):
                 log.warning("Failed to generate XML report: %s" % str(e))
 
         # make sure we have minimum required coverage
--- a/nose/plugins/doctests.py	2024-10-23 07:43:46.184868230 +0200
+++ b/nose/plugins/doctests.py	2024-10-23 07:48:31.409860858 +0200
@@ -275,7 +275,7 @@
                 try:
                     fixture_context = __import__(
                         fixt_mod, globals(), locals(), ["nop"])
-                except ImportError, e:
+                except( ImportError, e ):
                     log.debug(
                         "Could not import %s: %s (%s)", fixt_mod, e, sys.path)
                 log.debug("Fixture module %s resolved to %s",
@@ -413,7 +413,7 @@
         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()
@@ -446,7 +446,7 @@
         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()
--- a/nose/plugins/manager.py	2024-10-23 07:43:46.184868230 +0200
+++ b/nose/plugins/manager.py	2024-10-23 07:47:47.274861998 +0200
@@ -387,7 +387,7 @@
                     plugcls = ep.load()
                 except KeyboardInterrupt:
                     raise
-                except Exception, e:
+                except( Exception, e ):
                     # never want a plugin load to kill the test run
                     # but we can't log here because the logger is not yet
                     # configured
--- a/nose/plugins/multiprocess.py	2024-10-23 07:43:46.184868230 +0200
+++ b/nose/plugins/multiprocess.py	2024-10-23 07:47:05.561863077 +0200
@@ -478,7 +478,7 @@
                                 self.config.multiprocess_timeout-timeprocessing)
             log.debug("Completed %s tasks (%s remain)", len(completed), len(tasks))
 
-        except (KeyboardInterrupt, SystemExit), e:
+        except(KeyboardInterrupt, SystemExit, e):
             log.info('parent received ctrl-c when waiting for test results')
             thrownError = e
             #resultQueue.get(False)
@@ -715,7 +715,7 @@
             test(result)
             currentaddr.value = bytes_('')
             resultQueue.put((ix, test_addr, test.tasks, batch(result)))
-        except KeyboardInterrupt, e: #TimedOutException:
+        except( KeyboardInterrupt, e ): #TimedOutException:
             timeout = isinstance(e, TimedOutException)
             if timeout:
                 keyboardCaught.set()
@@ -810,7 +810,7 @@
                 #log.debug('running test %s in suite %s', test, self);
                 try:
                     test(orig)
-                except KeyboardInterrupt, e:
+                except( KeyboardInterrupt, e ):
                     timeout = isinstance(e, TimedOutException)
                     if timeout:
                         msg = 'Timeout when running test %s in suite %s'
--- a/nose/plugins/plugintest.py	2024-10-23 07:43:46.184868230 +0200
+++ b/nose/plugins/plugintest.py	2024-10-23 07:45:51.173864999 +0200
@@ -404,7 +404,7 @@
             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):
--- a/nose/plugins/testid.py	2024-10-23 07:43:46.184868230 +0200
+++ b/nose/plugins/testid.py	2024-10-23 07:45:02.792866250 +0200
@@ -198,7 +198,7 @@
                 self.ids, self.tests, self.failed, self.source_names,
                 self.idfile)
             fh.close()
-        except ValueError, e:
+        except( ValueError, 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.
--- a/nose/twistedtools.py	2024-10-23 07:43:46.183868230 +0200
+++ b/nose/twistedtools.py	2024-10-23 07:57:01.757847666 +0200
@@ -166,7 +166,7 @@
             # 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, tb )
         wrapper = make_decorator(func)(wrapper)
         return wrapper
     return decorate
