Merged revisions 56492-56752 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/p3yk

........
  r56497 | kurt.kaiser | 2007-07-22 14:55:16 -0700 (Sun, 22 Jul 2007) | 4 lines

  In the case of syntax errors, in py3k format_exception_only()
  was including line number and position in the final line of the
  exception notification, duplicating info in previous lines.
........
  r56501 | kurt.kaiser | 2007-07-22 19:35:50 -0700 (Sun, 22 Jul 2007) | 2 lines

  Hum, needed a newline in the last change.
........
  r56536 | kurt.kaiser | 2007-07-24 19:06:48 -0700 (Tue, 24 Jul 2007) | 5 lines

  Not all instantiations of SyntaxError set the args attribute.
  e.g. symtable.c
  Modify format_exception_only() to get SyntaxError attributes directly
  instead of unpacking 'args'.
........
  r56537 | kurt.kaiser | 2007-07-24 19:13:03 -0700 (Tue, 24 Jul 2007) | 3 lines

  Update doctest strings: traceback.py no longer prints redundant location
  information in the last line of the exception display.
........
  r56627 | kurt.kaiser | 2007-07-29 21:06:57 -0700 (Sun, 29 Jul 2007) | 2 lines

  Interactive interpreter emulator (code.py) failing to print exceptions.
........
  r56628 | kurt.kaiser | 2007-07-29 21:41:02 -0700 (Sun, 29 Jul 2007) | 2 lines

  Eliminate extra lines before and after tracebacks.
........
  r56638 | kurt.kaiser | 2007-07-31 19:36:45 -0700 (Tue, 31 Jul 2007) | 3 lines

  Refactor syntax error display in shell and edit windows; move
  colorize_syntax_error() to EditorWindow; update to py3k.
........
  r56685 | neal.norwitz | 2007-08-02 22:20:23 -0700 (Thu, 02 Aug 2007) | 10 lines

  Remove several h/w and o/s specific modules that are undocumented, obsolete,
  and/or not widely used:
   linuxaudiodev.c, sunaudiodev.c Lib/plat-sunos5/SUNAUDIODEV.py
   Lib/audiodev.py Tools/audiopy/audiopy

  Move Lib/toaiff.py to Demo.

  See PEP 3108 for most of the details.
........
  r56686 | neal.norwitz | 2007-08-02 22:21:48 -0700 (Thu, 02 Aug 2007) | 4 lines

  Missed one module that should have been removed since it relied
  on audiodev which was removed.
........
  r56748 | neal.norwitz | 2007-08-04 19:19:04 -0700 (Sat, 04 Aug 2007) | 1 line

  Make from X import * outside module scope an error.
........
  r56750 | neal.norwitz | 2007-08-04 19:35:01 -0700 (Sat, 04 Aug 2007) | 1 line

  Use READONLY consistently instead of RO
........
diff --git a/Lib/audiodev.py b/Lib/audiodev.py
deleted file mode 100644
index 0585bcf..0000000
--- a/Lib/audiodev.py
+++ /dev/null
@@ -1,257 +0,0 @@
-"""Classes for manipulating audio devices (currently only for Sun and SGI)"""
-
-__all__ = ["error","AudioDev"]
-
-class error(Exception):
-    pass
-
-class Play_Audio_sgi:
-    # Private instance variables
-##      if 0: access frameratelist, nchannelslist, sampwidthlist, oldparams, \
-##                params, config, inited_outrate, inited_width, \
-##                inited_nchannels, port, converter, classinited: private
-
-    classinited = 0
-    frameratelist = nchannelslist = sampwidthlist = None
-
-    def initclass(self):
-        import AL
-        self.frameratelist = [
-                  (48000, AL.RATE_48000),
-                  (44100, AL.RATE_44100),
-                  (32000, AL.RATE_32000),
-                  (22050, AL.RATE_22050),
-                  (16000, AL.RATE_16000),
-                  (11025, AL.RATE_11025),
-                  ( 8000,  AL.RATE_8000),
-                  ]
-        self.nchannelslist = [
-                  (1, AL.MONO),
-                  (2, AL.STEREO),
-                  (4, AL.QUADRO),
-                  ]
-        self.sampwidthlist = [
-                  (1, AL.SAMPLE_8),
-                  (2, AL.SAMPLE_16),
-                  (3, AL.SAMPLE_24),
-                  ]
-        self.classinited = 1
-
-    def __init__(self):
-        import al, AL
-        if not self.classinited:
-            self.initclass()
-        self.oldparams = []
-        self.params = [AL.OUTPUT_RATE, 0]
-        self.config = al.newconfig()
-        self.inited_outrate = 0
-        self.inited_width = 0
-        self.inited_nchannels = 0
-        self.converter = None
-        self.port = None
-        return
-
-    def __del__(self):
-        if self.port:
-            self.stop()
-        if self.oldparams:
-            import al, AL
-            al.setparams(AL.DEFAULT_DEVICE, self.oldparams)
-            self.oldparams = []
-
-    def wait(self):
-        if not self.port:
-            return
-        import time
-        while self.port.getfilled() > 0:
-            time.sleep(0.1)
-        self.stop()
-
-    def stop(self):
-        if self.port:
-            self.port.closeport()
-            self.port = None
-        if self.oldparams:
-            import al, AL
-            al.setparams(AL.DEFAULT_DEVICE, self.oldparams)
-            self.oldparams = []
-
-    def setoutrate(self, rate):
-        for (raw, cooked) in self.frameratelist:
-            if rate == raw:
-                self.params[1] = cooked
-                self.inited_outrate = 1
-                break
-        else:
-            raise error, 'bad output rate'
-
-    def setsampwidth(self, width):
-        for (raw, cooked) in self.sampwidthlist:
-            if width == raw:
-                self.config.setwidth(cooked)
-                self.inited_width = 1
-                break
-        else:
-            if width == 0:
-                import AL
-                self.inited_width = 0
-                self.config.setwidth(AL.SAMPLE_16)
-                self.converter = self.ulaw2lin
-            else:
-                raise error, 'bad sample width'
-
-    def setnchannels(self, nchannels):
-        for (raw, cooked) in self.nchannelslist:
-            if nchannels == raw:
-                self.config.setchannels(cooked)
-                self.inited_nchannels = 1
-                break
-        else:
-            raise error, 'bad # of channels'
-
-    def writeframes(self, data):
-        if not (self.inited_outrate and self.inited_nchannels):
-            raise error, 'params not specified'
-        if not self.port:
-            import al, AL
-            self.port = al.openport('Python', 'w', self.config)
-            self.oldparams = self.params[:]
-            al.getparams(AL.DEFAULT_DEVICE, self.oldparams)
-            al.setparams(AL.DEFAULT_DEVICE, self.params)
-        if self.converter:
-            data = self.converter(data)
-        self.port.writesamps(data)
-
-    def getfilled(self):
-        if self.port:
-            return self.port.getfilled()
-        else:
-            return 0
-
-    def getfillable(self):
-        if self.port:
-            return self.port.getfillable()
-        else:
-            return self.config.getqueuesize()
-
-    # private methods
-##      if 0: access *: private
-
-    def ulaw2lin(self, data):
-        import audioop
-        return audioop.ulaw2lin(data, 2)
-
-class Play_Audio_sun:
-##      if 0: access outrate, sampwidth, nchannels, inited_outrate, inited_width, \
-##                inited_nchannels, converter: private
-
-    def __init__(self):
-        self.outrate = 0
-        self.sampwidth = 0
-        self.nchannels = 0
-        self.inited_outrate = 0
-        self.inited_width = 0
-        self.inited_nchannels = 0
-        self.converter = None
-        self.port = None
-        return
-
-    def __del__(self):
-        self.stop()
-
-    def setoutrate(self, rate):
-        self.outrate = rate
-        self.inited_outrate = 1
-
-    def setsampwidth(self, width):
-        self.sampwidth = width
-        self.inited_width = 1
-
-    def setnchannels(self, nchannels):
-        self.nchannels = nchannels
-        self.inited_nchannels = 1
-
-    def writeframes(self, data):
-        if not (self.inited_outrate and self.inited_width and self.inited_nchannels):
-            raise error, 'params not specified'
-        if not self.port:
-            import sunaudiodev, SUNAUDIODEV
-            self.port = sunaudiodev.open('w')
-            info = self.port.getinfo()
-            info.o_sample_rate = self.outrate
-            info.o_channels = self.nchannels
-            if self.sampwidth == 0:
-                info.o_precision = 8
-                self.o_encoding = SUNAUDIODEV.ENCODING_ULAW
-                # XXX Hack, hack -- leave defaults
-            else:
-                info.o_precision = 8 * self.sampwidth
-                info.o_encoding = SUNAUDIODEV.ENCODING_LINEAR
-                self.port.setinfo(info)
-        if self.converter:
-            data = self.converter(data)
-        self.port.write(data)
-
-    def wait(self):
-        if not self.port:
-            return
-        self.port.drain()
-        self.stop()
-
-    def stop(self):
-        if self.port:
-            self.port.flush()
-            self.port.close()
-            self.port = None
-
-    def getfilled(self):
-        if self.port:
-            return self.port.obufcount()
-        else:
-            return 0
-
-##    # Nobody remembers what this method does, and it's broken. :-(
-##    def getfillable(self):
-##        return BUFFERSIZE - self.getfilled()
-
-def AudioDev():
-    # Dynamically try to import and use a platform specific module.
-    try:
-        import al
-    except ImportError:
-        try:
-            import sunaudiodev
-            return Play_Audio_sun()
-        except ImportError:
-            try:
-                import Audio_mac
-            except ImportError:
-                raise error, 'no audio device'
-            else:
-                return Audio_mac.Play_Audio_mac()
-    else:
-        return Play_Audio_sgi()
-
-def test(fn = None):
-    import sys
-    if sys.argv[1:]:
-        fn = sys.argv[1]
-    else:
-        fn = 'f:just samples:just.aif'
-    import aifc
-    af = aifc.open(fn, 'r')
-    print(fn, af.getparams())
-    p = AudioDev()
-    p.setoutrate(af.getframerate())
-    p.setsampwidth(af.getsampwidth())
-    p.setnchannels(af.getnchannels())
-    BUFSIZ = af.getframerate()/af.getsampwidth()/af.getnchannels()
-    while 1:
-        data = af.readframes(BUFSIZ)
-        if not data: break
-        print(len(data))
-        p.writeframes(data)
-    p.wait()
-
-if __name__ == '__main__':
-    test()
diff --git a/Lib/code.py b/Lib/code.py
index 7182777..58af883 100644
--- a/Lib/code.py
+++ b/Lib/code.py
@@ -111,16 +111,16 @@
         if filename and type is SyntaxError:
             # Work hard to stuff the correct filename in the exception
             try:
-                msg, (dummy_filename, lineno, offset, line) = value
-            except:
+                msg, (dummy_filename, lineno, offset, line) = value.args
+            except ValueError:
                 # Not the format we expect; leave it alone
                 pass
             else:
                 # Stuff in the right filename
                 value = SyntaxError(msg, (filename, lineno, offset, line))
                 sys.last_value = value
-        list = traceback.format_exception_only(type, value)
-        map(self.write, list)
+        lines = traceback.format_exception_only(type, value)
+        self.write(''.join(lines))
 
     def showtraceback(self):
         """Display the exception that just occurred.
@@ -137,13 +137,13 @@
             sys.last_traceback = tb
             tblist = traceback.extract_tb(tb)
             del tblist[:1]
-            list = traceback.format_list(tblist)
-            if list:
-                list.insert(0, "Traceback (most recent call last):\n")
-            list[len(list):] = traceback.format_exception_only(type, value)
+            lines = traceback.format_list(tblist)
+            if lines:
+                lines.insert(0, "Traceback (most recent call last):\n")
+            lines.extend(traceback.format_exception_only(type, value))
         finally:
             tblist = tb = None
-        map(self.write, list)
+        self.write(''.join(lines))
 
     def write(self, data):
         """Write a string.
@@ -184,7 +184,7 @@
     def interact(self, banner=None):
         """Closely emulate the interactive Python console.
 
-        The optional banner argument specify the banner to print
+        The optional banner argument specifies the banner to print
         before the first interaction; by default it prints a banner
         similar to the one printed by the real Python interpreter,
         followed by the current class name in parentheses (so as not
diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py
index 501ae0f..a43929d 100644
--- a/Lib/idlelib/EditorWindow.py
+++ b/Lib/idlelib/EditorWindow.py
@@ -1,6 +1,7 @@
 import sys
 import os
 import re
+import string
 import imp
 from itertools import count
 from Tkinter import *
@@ -602,6 +603,19 @@
         theme = idleConf.GetOption('main','Theme','name')
         self.text.config(idleConf.GetHighlight(theme, "normal"))
 
+    IDENTCHARS = string.ascii_letters + string.digits + "_"
+
+    def colorize_syntax_error(self, text, pos):
+        text.tag_add("ERROR", pos)
+        char = text.get(pos)
+        if char and char in self.IDENTCHARS:
+            text.tag_add("ERROR", pos + " wordstart", pos)
+        if '\n' == text.get(pos):   # error at line end
+            text.mark_set("insert", pos)
+        else:
+            text.mark_set("insert", pos + "+1c")
+        text.see(pos)
+
     def ResetFont(self):
         "Update the text widgets' font if it is changed"
         # Called from configDialog.py
@@ -1004,6 +1018,8 @@
                                   "n" * newtabwidth)
             text.configure(tabs=pixels)
 
+### begin autoindent code ###  (configuration was moved to beginning of class)
+
     # If ispythonsource and guess are true, guess a good value for
     # indentwidth based on file content (if possible), and if
     # indentwidth != tabwidth set usetabs false.
diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py
index 567994e..70c36fc 100644
--- a/Lib/idlelib/PyShell.py
+++ b/Lib/idlelib/PyShell.py
@@ -3,7 +3,6 @@
 import os
 import os.path
 import sys
-import string
 import getopt
 import re
 import socket
@@ -35,7 +34,6 @@
 from . import RemoteDebugger
 from . import macosxSupport
 
-IDENTCHARS = string.ascii_letters + string.digits + "_"
 LOCALHOST = '127.0.0.1'
 
 try:
@@ -624,47 +622,30 @@
             \n""" % (filename,))
 
     def showsyntaxerror(self, filename=None):
-        """Extend base class method: Add Colorizing
+        """Override Interactive Interpreter method: Use Colorizing
 
         Color the offending position instead of printing it and pointing at it
         with a caret.
 
         """
-        text = self.tkconsole.text
-        stuff = self.unpackerror()
-        if stuff:
-            msg, lineno, offset, line = stuff
-            if lineno == 1:
-                pos = "iomark + %d chars" % (offset-1)
-            else:
-                pos = "iomark linestart + %d lines + %d chars" % \
-                      (lineno-1, offset-1)
-            text.tag_add("ERROR", pos)
-            text.see(pos)
-            char = text.get(pos)
-            if char and char in IDENTCHARS:
-                text.tag_add("ERROR", pos + " wordstart", pos)
-            self.tkconsole.resetoutput()
-            self.write("SyntaxError: %s\n" % str(msg))
-        else:
-            self.tkconsole.resetoutput()
-            InteractiveInterpreter.showsyntaxerror(self, filename)
-        self.tkconsole.showprompt()
-
-    def unpackerror(self):
+        tkconsole = self.tkconsole
+        text = tkconsole.text
+        text.tag_remove("ERROR", "1.0", "end")
         type, value, tb = sys.exc_info()
-        ok = type is SyntaxError
-        if ok:
-            try:
-                msg, (dummy_filename, lineno, offset, line) = value
-                if not offset:
-                    offset = 0
-            except:
-                ok = 0
-        if ok:
-            return msg, lineno, offset, line
+        msg = value.msg or "<no detail available>"
+        lineno = value.lineno or 1
+        offset = value.offset or 0
+        if offset == 0:
+            lineno += 1 #mark end of offending line
+        if lineno == 1:
+            pos = "iomark + %d chars" % (offset-1)
         else:
-            return None
+            pos = "iomark linestart + %d lines + %d chars" % \
+                  (lineno-1, offset-1)
+        tkconsole.colorize_syntax_error(text, pos)
+        tkconsole.resetoutput()
+        self.write("SyntaxError: %s\n" % msg)
+        tkconsole.showprompt()
 
     def showtraceback(self):
         "Extend base class method to reset output properly"
diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py
index 485de34..47eadb2 100644
--- a/Lib/idlelib/ScriptBinding.py
+++ b/Lib/idlelib/ScriptBinding.py
@@ -23,12 +23,11 @@
 import tabnanny
 import tokenize
 import tkMessageBox
+from .EditorWindow import EditorWindow
 from . import PyShell
 
 from .configHandler import idleConf
 
-IDENTCHARS = string.ascii_letters + string.digits + "_"
-
 indent_message = """Error: Inconsistent indentation detected!
 
 1) Your indentation is outright incorrect (easy to fix), OR
@@ -83,7 +82,7 @@
         self.shell = shell = self.flist.open_shell()
         saved_stream = shell.get_warning_stream()
         shell.set_warning_stream(shell.stderr)
-        f = open(filename, 'r')
+        f = file(filename, 'r')
         source = f.read()
         f.close()
         if '\r' in source:
@@ -91,40 +90,25 @@
             source = re.sub(r"\r", "\n", source)
         if source and source[-1] != '\n':
             source = source + '\n'
-        text = self.editwin.text
+        editwin = self.editwin
+        text = editwin.text
         text.tag_remove("ERROR", "1.0", "end")
         try:
-            try:
-                # If successful, return the compiled code
-                return compile(source, filename, "exec")
-            except (SyntaxError, OverflowError) as err:
-                try:
-                    msg, (errorfilename, lineno, offset, line) = err.args
-                    if not errorfilename:
-                        err.args = msg, (filename, lineno, offset, line)
-                        err.filename = filename
-                    self.colorize_syntax_error(msg, lineno, offset)
-                except:
-                    msg = str(err)
-                self.errorbox("Syntax error",
-                              "There's an error in your program:\n" + msg)
-                return False
+            # If successful, return the compiled code
+            return compile(source, filename, "exec")
+        except (SyntaxError, OverflowError) as value:
+            msg = value.msg or "<no detail available>"
+            lineno = value.lineno or 1
+            offset = value.offset or 0
+            if offset == 0:
+                lineno += 1  #mark end of offending line
+            pos = "0.0 + %d lines + %d chars" % (lineno-1, offset-1)
+            editwin.colorize_syntax_error(text, pos)
+            self.errorbox("SyntaxError", "%-20s" % msg)
+            return False
         finally:
             shell.set_warning_stream(saved_stream)
 
-    def colorize_syntax_error(self, msg, lineno, offset):
-        text = self.editwin.text
-        pos = "0.0 + %d lines + %d chars" % (lineno-1, offset-1)
-        text.tag_add("ERROR", pos)
-        char = text.get(pos)
-        if char and char in IDENTCHARS:
-            text.tag_add("ERROR", pos + " wordstart", pos)
-        if '\n' == text.get(pos):   # error at line end
-            text.mark_set("insert", pos)
-        else:
-            text.mark_set("insert", pos + "+1c")
-        text.see(pos)
-
     def run_module_event(self, event):
         """Run the module after setting up the environment.
 
@@ -199,10 +183,10 @@
                                   icon=tkMessageBox.QUESTION,
                                   type=tkMessageBox.OKCANCEL,
                                   default=tkMessageBox.OK,
-                                  master=self.editwin.text)
+                                  parent=self.editwin.text)
         return mb.show()
 
     def errorbox(self, title, message):
         # XXX This should really be a function of EditorWindow...
-        tkMessageBox.showerror(title, message, master=self.editwin.text)
+        tkMessageBox.showerror(title, message, parent=self.editwin.text)
         self.editwin.text.focus_set()
diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py
index 614875a..c1bc8eb 100644
--- a/Lib/idlelib/run.py
+++ b/Lib/idlelib/run.py
@@ -149,14 +149,14 @@
     typ, val, tb = excinfo = sys.exc_info()
     sys.last_type, sys.last_value, sys.last_traceback = excinfo
     tbe = traceback.extract_tb(tb)
-    print('\nTraceback (most recent call last):', file=efile)
+    print('Traceback (most recent call last):', file=efile)
     exclude = ("run.py", "rpc.py", "threading.py", "Queue.py",
                "RemoteDebugger.py", "bdb.py")
     cleanup_traceback(tbe, exclude)
     traceback.print_list(tbe, file=efile)
     lines = traceback.format_exception_only(typ, val)
     for line in lines:
-        print(line, end=' ', file=efile)
+        print(line, end='', file=efile)
 
 def cleanup_traceback(tb, exclude):
     "Remove excluded traces from beginning/end of tb; get cached lines"
diff --git a/Lib/plat-sunos5/SUNAUDIODEV.py b/Lib/plat-sunos5/SUNAUDIODEV.py
deleted file mode 100755
index 632139f..0000000
--- a/Lib/plat-sunos5/SUNAUDIODEV.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Symbolic constants for use with sunaudiodev module
-# The names are the same as in audioio.h with the leading AUDIO_
-# removed.
-
-# Not all values are supported on all releases of SunOS.
-
-# Encoding types, for fields i_encoding and o_encoding
-
-ENCODING_NONE = 0                       # no encoding assigned
-ENCODING_ULAW = 1                       # u-law encoding
-ENCODING_ALAW = 2                       # A-law encoding
-ENCODING_LINEAR = 3                     # Linear PCM encoding
-
-# Gain ranges for i_gain, o_gain and monitor_gain
-
-MIN_GAIN = 0                            # minimum gain value
-MAX_GAIN = 255                          # maximum gain value
-
-# Balance values for i_balance and o_balance
-
-LEFT_BALANCE = 0                        # left channel only
-MID_BALANCE = 32                        # equal left/right channel
-RIGHT_BALANCE = 64                      # right channel only
-BALANCE_SHIFT = 3
-
-# Port names for i_port and o_port
-
-PORT_A = 1
-PORT_B = 2
-PORT_C = 3
-PORT_D = 4
-
-SPEAKER = 0x01                          # output to built-in speaker
-HEADPHONE = 0x02                        # output to headphone jack
-LINE_OUT = 0x04                         # output to line out
-
-MICROPHONE = 0x01                       # input from microphone
-LINE_IN = 0x02                          # input from line in
-CD = 0x04                               # input from on-board CD inputs
-INTERNAL_CD_IN = CD                     # input from internal CDROM
diff --git a/Lib/test/README b/Lib/test/README
index 747d842..8aab357 100644
--- a/Lib/test/README
+++ b/Lib/test/README
@@ -372,7 +372,7 @@
 
     * ``findfile(file)`` - you can call this function to locate a file
       somewhere along sys.path or in the Lib/test tree - see
-      test_linuxaudiodev.py for an example of its use.
+      test_ossaudiodev.py for an example of its use.
 
     * ``fcmp(x,y)`` - you can call this function to compare two floating
       point numbers when you expect them to only be approximately equal
diff --git a/Lib/test/output/test_linuxaudiodev b/Lib/test/output/test_linuxaudiodev
deleted file mode 100644
index 3e8c691..0000000
--- a/Lib/test/output/test_linuxaudiodev
+++ /dev/null
@@ -1,7 +0,0 @@
-test_linuxaudiodev
-expected rate >= 0, not -1
-expected sample size >= 0, not -2
-nchannels must be 1 or 2, not 3
-unknown audio encoding: 177
-for linear unsigned 16-bit little-endian audio, expected sample size 16, not 8
-for linear unsigned 8-bit audio, expected sample size 8, not 16
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
index de7807c..28b82ad 100755
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -1106,8 +1106,6 @@
             self.expected = set(s.split())
 
             # expected to be skipped on every platform, even Linux
-            self.expected.add('test_linuxaudiodev')
-
             if not os.path.supports_unicode_filenames:
                 self.expected.add('test_pep277')
 
@@ -1134,7 +1132,6 @@
                     self.expected.add(skip)
 
             if sys.platform != 'sunos5':
-                self.expected.add('test_sunaudiodev')
                 self.expected.add('test_nis')
 
             self.valid = True
diff --git a/Lib/test/test___all__.py b/Lib/test/test___all__.py
index f5dd431..4cf2e25 100644
--- a/Lib/test/test___all__.py
+++ b/Lib/test/test___all__.py
@@ -39,7 +39,6 @@
         self.check_all("StringIO")
         self.check_all("UserString")
         self.check_all("aifc")
-        self.check_all("audiodev")
         self.check_all("base64")
         self.check_all("bdb")
         self.check_all("binhex")
@@ -135,7 +134,6 @@
         self.check_all("textwrap")
         self.check_all("threading")
         self.check_all("timeit")
-        self.check_all("toaiff")
         self.check_all("tokenize")
         self.check_all("traceback")
         self.check_all("tty")
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py
index a3b7870..a1ab0f1 100644
--- a/Lib/test/test_generators.py
+++ b/Lib/test/test_generators.py
@@ -733,14 +733,14 @@
 ...     yield 1
 Traceback (most recent call last):
   ..
-SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[0]>, line 3)
+SyntaxError: 'return' with argument inside generator
 
 >>> def f():
 ...     yield 1
 ...     return 22
 Traceback (most recent call last):
   ..
-SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[1]>, line 3)
+SyntaxError: 'return' with argument inside generator
 
 "return None" is not the same as "return" in a generator:
 
@@ -749,7 +749,7 @@
 ...     return None
 Traceback (most recent call last):
   ..
-SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[2]>, line 3)
+SyntaxError: 'return' with argument inside generator
 
 These are fine:
 
@@ -878,7 +878,7 @@
 ...     if 0:
 ...         yield 2             # because it's a generator (line 10)
 Traceback (most recent call last):
-SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.syntax[24]>, line 10)
+SyntaxError: 'return' with argument inside generator
 
 This one caused a crash (see SF bug 567538):
 
@@ -1525,27 +1525,27 @@
 >>> f=lambda: (yield 1),(yield 2)
 Traceback (most recent call last):
   ...
-SyntaxError: 'yield' outside function (<doctest test.test_generators.__test__.coroutine[21]>, line 1)
+SyntaxError: 'yield' outside function
 
 >>> def f(): return lambda x=(yield): 1
 Traceback (most recent call last):
   ...
-SyntaxError: 'return' with argument inside generator (<doctest test.test_generators.__test__.coroutine[22]>, line 1)
+SyntaxError: 'return' with argument inside generator
 
 >>> def f(): x = yield = y
 Traceback (most recent call last):
   ...
-SyntaxError: assignment to yield expression not possible (<doctest test.test_generators.__test__.coroutine[23]>, line 1)
+SyntaxError: assignment to yield expression not possible
 
 >>> def f(): (yield bar) = y
 Traceback (most recent call last):
   ...
-SyntaxError: can't assign to yield expression (<doctest test.test_generators.__test__.coroutine[24]>, line 1)
+SyntaxError: can't assign to yield expression
 
 >>> def f(): (yield bar) += y
 Traceback (most recent call last):
   ...
-SyntaxError: augmented assignment to yield expression not possible (<doctest test.test_generators.__test__.coroutine[25]>, line 1)
+SyntaxError: augmented assignment to yield expression not possible
 
 
 Now check some throw() conditions:
diff --git a/Lib/test/test_genexps.py b/Lib/test/test_genexps.py
index ee582e3..6c60d02 100644
--- a/Lib/test/test_genexps.py
+++ b/Lib/test/test_genexps.py
@@ -137,12 +137,12 @@
     >>> (y for y in (1,2)) = 10
     Traceback (most recent call last):
        ...
-    SyntaxError: can't assign to generator expression (<doctest test.test_genexps.__test__.doctests[40]>, line 1)
+    SyntaxError: can't assign to generator expression
 
     >>> (y for y in (1,2)) += 10
     Traceback (most recent call last):
        ...
-    SyntaxError: augmented assignment to generator expression not possible (<doctest test.test_genexps.__test__.doctests[41]>, line 1)
+    SyntaxError: augmented assignment to generator expression not possible
 
 
 ########### Tests borrowed from or inspired by test_generators.py ############
diff --git a/Lib/test/test_linuxaudiodev.py b/Lib/test/test_linuxaudiodev.py
deleted file mode 100644
index 340dc2d..0000000
--- a/Lib/test/test_linuxaudiodev.py
+++ /dev/null
@@ -1,92 +0,0 @@
-from test import test_support
-test_support.requires('audio')
-
-from test.test_support import verbose, findfile, TestFailed, TestSkipped
-
-import errno
-import fcntl
-import linuxaudiodev
-import os
-import sys
-import select
-import sunaudio
-import time
-import audioop
-
-SND_FORMAT_MULAW_8 = 1
-
-def play_sound_file(path):
-    fp = open(path, 'r')
-    size, enc, rate, nchannels, extra = sunaudio.gethdr(fp)
-    data = fp.read()
-    fp.close()
-
-    if enc != SND_FORMAT_MULAW_8:
-        print("Expect .au file with 8-bit mu-law samples")
-        return
-
-    try:
-        a = linuxaudiodev.open('w')
-    except linuxaudiodev.error as msg:
-        if msg.args[0] in (errno.EACCES, errno.ENOENT, errno.ENODEV, errno.EBUSY):
-            raise TestSkipped, msg
-        raise TestFailed, msg
-
-    # convert the data to 16-bit signed
-    data = audioop.ulaw2lin(data, 2)
-
-    # set the data format
-    if sys.byteorder == 'little':
-        fmt = linuxaudiodev.AFMT_S16_LE
-    else:
-        fmt = linuxaudiodev.AFMT_S16_BE
-
-    # at least check that these methods can be invoked
-    a.bufsize()
-    a.obufcount()
-    a.obuffree()
-    a.getptr()
-    a.fileno()
-
-    # set parameters based on .au file headers
-    a.setparameters(rate, 16, nchannels, fmt)
-    a.write(data)
-    a.flush()
-    a.close()
-
-def test_errors():
-    a = linuxaudiodev.open("w")
-    size = 8
-    fmt = linuxaudiodev.AFMT_U8
-    rate = 8000
-    nchannels = 1
-    try:
-        a.setparameters(-1, size, nchannels, fmt)
-    except ValueError as msg:
-        print(msg)
-    try:
-        a.setparameters(rate, -2, nchannels, fmt)
-    except ValueError as msg:
-        print(msg)
-    try:
-        a.setparameters(rate, size, 3, fmt)
-    except ValueError as msg:
-        print(msg)
-    try:
-        a.setparameters(rate, size, nchannels, 177)
-    except ValueError as msg:
-        print(msg)
-    try:
-        a.setparameters(rate, size, nchannels, linuxaudiodev.AFMT_U16_LE)
-    except ValueError as msg:
-        print(msg)
-    try:
-        a.setparameters(rate, 16, nchannels, fmt)
-    except ValueError as msg:
-        print(msg)
-
-def test():
-    play_sound_file(findfile('audiotest.au'))
-    test_errors()
-
-test()
diff --git a/Lib/test/test_scope.py b/Lib/test/test_scope.py
index 259d1d9..567053b 100644
--- a/Lib/test/test_scope.py
+++ b/Lib/test/test_scope.py
@@ -223,25 +223,6 @@
         return getrefcount # global or local?
 """)
 
-        # and verify a few cases that should work
-
-        exec("""
-def noproblem1():
-    from sys import *
-    f = lambda x:x
-
-def noproblem2():
-    from sys import *
-    def f(x):
-        return x + 1
-
-def noproblem3():
-    from sys import *
-    def f(x):
-        global y
-        y = x
-""")
-
     def testLambdas(self):
 
         f1 = lambda x: lambda y: x + y
diff --git a/Lib/test/test_sunaudiodev.py b/Lib/test/test_sunaudiodev.py
deleted file mode 100644
index 0427db5..0000000
--- a/Lib/test/test_sunaudiodev.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from test.test_support import verbose, findfile, TestFailed, TestSkipped
-import sunaudiodev
-import os
-
-try:
-    audiodev = os.environ["AUDIODEV"]
-except KeyError:
-    audiodev = "/dev/audio"
-
-if not os.path.exists(audiodev):
-    raise TestSkipped("no audio device found!")
-
-def play_sound_file(path):
-    fp = open(path, 'r')
-    data = fp.read()
-    fp.close()
-    try:
-        a = sunaudiodev.open('w')
-    except sunaudiodev.error as msg:
-        raise TestFailed, msg
-    else:
-        a.write(data)
-        a.close()
-
-def test():
-    play_sound_file(findfile('audiotest.au'))
-
-test()
diff --git a/Lib/test/test_sundry.py b/Lib/test/test_sundry.py
index 28a08c5..6afc63b 100644
--- a/Lib/test/test_sundry.py
+++ b/Lib/test/test_sundry.py
@@ -13,7 +13,6 @@
     import SimpleHTTPServer
     import SimpleXMLRPCServer
     import aifc
-    import audiodev
     import bdb
     import cgitb
     import cmd
@@ -99,7 +98,6 @@
     import tabnanny
     import telnetlib
     import timeit
-    import toaiff
     import token
     try:
         import tty     # not available on Windows
diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py
index ab60a56..4297d22 100644
--- a/Lib/test/test_syntax.py
+++ b/Lib/test/test_syntax.py
@@ -33,7 +33,7 @@
 
 >>> None = 1
 Traceback (most recent call last):
-SyntaxError: assignment to keyword (<doctest test.test_syntax[2]>, line 1)
+SyntaxError: assignment to keyword
 
 It's a syntax error to assign to the empty tuple.  Why isn't it an
 error to assign to the empty list?  It will always raise some error at
@@ -41,31 +41,31 @@
 
 >>> () = 1
 Traceback (most recent call last):
-SyntaxError: can't assign to () (<doctest test.test_syntax[3]>, line 1)
+SyntaxError: can't assign to ()
 
 >>> f() = 1
 Traceback (most recent call last):
-SyntaxError: can't assign to function call (<doctest test.test_syntax[4]>, line 1)
+SyntaxError: can't assign to function call
 
 >>> del f()
 Traceback (most recent call last):
-SyntaxError: can't delete function call (<doctest test.test_syntax[5]>, line 1)
+SyntaxError: can't delete function call
 
 >>> a + 1 = 2
 Traceback (most recent call last):
-SyntaxError: can't assign to operator (<doctest test.test_syntax[6]>, line 1)
+SyntaxError: can't assign to operator
 
 >>> (x for x in x) = 1
 Traceback (most recent call last):
-SyntaxError: can't assign to generator expression (<doctest test.test_syntax[7]>, line 1)
+SyntaxError: can't assign to generator expression
 
 >>> 1 = 1
 Traceback (most recent call last):
-SyntaxError: can't assign to literal (<doctest test.test_syntax[8]>, line 1)
+SyntaxError: can't assign to literal
 
 >>> "abc" = 1
 Traceback (most recent call last):
-SyntaxError: can't assign to literal (<doctest test.test_syntax[9]>, line 1)
+SyntaxError: can't assign to literal
 
 >>> `1` = 1
 Traceback (most recent call last):
@@ -78,15 +78,15 @@
 
 >>> (a, "b", c) = (1, 2, 3)
 Traceback (most recent call last):
-SyntaxError: can't assign to literal (<doctest test.test_syntax[11]>, line 1)
+SyntaxError: can't assign to literal
 
 >>> [a, b, c + 1] = [1, 2, 3]
 Traceback (most recent call last):
-SyntaxError: can't assign to operator (<doctest test.test_syntax[12]>, line 1)
+SyntaxError: can't assign to operator
 
 >>> a if 1 else b = 1
 Traceback (most recent call last):
-SyntaxError: can't assign to conditional expression (<doctest test.test_syntax[13]>, line 1)
+SyntaxError: can't assign to conditional expression
 
 From compiler_complex_args():
 
@@ -101,7 +101,7 @@
 >>> def f(x, y=1, z):
 ...     pass
 Traceback (most recent call last):
-SyntaxError: non-default argument follows default argument (<doctest test.test_syntax[15]>, line 1)
+SyntaxError: non-default argument follows default argument
 
 >>> def f(x, None):
 ...     pass
@@ -136,7 +136,7 @@
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 >>> f(x for x in L, 1)
 Traceback (most recent call last):
-SyntaxError: Generator expression must be parenthesized if not sole argument (<doctest test.test_syntax[23]>, line 1)
+SyntaxError: Generator expression must be parenthesized if not sole argument
 >>> f((x for x in L), 1)
 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 
@@ -168,7 +168,7 @@
 ...   i244,  i245,  i246,  i247,  i248,  i249,  i250,  i251,  i252,
 ...   i253,  i254,  i255)
 Traceback (most recent call last):
-SyntaxError: more than 255 arguments (<doctest test.test_syntax[25]>, line 1)
+SyntaxError: more than 255 arguments
 
 The actual error cases counts positional arguments, keyword arguments,
 and generator expression arguments separately.  This test combines the
@@ -202,37 +202,37 @@
 ...   (x for x in i244),  i245,  i246,  i247,  i248,  i249,  i250,  i251,
 ...    i252=1, i253=1,  i254=1,  i255=1)
 Traceback (most recent call last):
-SyntaxError: more than 255 arguments (<doctest test.test_syntax[26]>, line 1)
+SyntaxError: more than 255 arguments
 
 >>> f(lambda x: x[0] = 3)
 Traceback (most recent call last):
-SyntaxError: lambda cannot contain assignment (<doctest test.test_syntax[27]>, line 1)
+SyntaxError: lambda cannot contain assignment
 
 The grammar accepts any test (basically, any expression) in the
 keyword slot of a call site.  Test a few different options.
 
 >>> f(x()=2)
 Traceback (most recent call last):
-SyntaxError: keyword can't be an expression (<doctest test.test_syntax[28]>, line 1)
+SyntaxError: keyword can't be an expression
 >>> f(a or b=1)
 Traceback (most recent call last):
-SyntaxError: keyword can't be an expression (<doctest test.test_syntax[29]>, line 1)
+SyntaxError: keyword can't be an expression
 >>> f(x.y=1)
 Traceback (most recent call last):
-SyntaxError: keyword can't be an expression (<doctest test.test_syntax[30]>, line 1)
+SyntaxError: keyword can't be an expression
 
 
 From ast_for_expr_stmt():
 
 >>> (x for x in x) += 1
 Traceback (most recent call last):
-SyntaxError: augmented assignment to generator expression not possible (<doctest test.test_syntax[31]>, line 1)
+SyntaxError: augmented assignment to generator expression not possible
 >>> None += 1
 Traceback (most recent call last):
-SyntaxError: assignment to keyword (<doctest test.test_syntax[32]>, line 1)
+SyntaxError: assignment to keyword
 >>> f() += 1
 Traceback (most recent call last):
-SyntaxError: illegal expression for augmented assignment (<doctest test.test_syntax[33]>, line 1)
+SyntaxError: illegal expression for augmented assignment
 
 
 Test continue in finally in weird combinations.
@@ -259,7 +259,7 @@
     ...            continue
     Traceback (most recent call last):
       ...
-    SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[36]>, line 6)
+    SyntaxError: 'continue' not supported inside 'finally' clause
 
 This is essentially a continue in a finally which should not be allowed.
 
@@ -274,7 +274,7 @@
     ...                pass
     Traceback (most recent call last):
       ...
-    SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[37]>, line 7)
+    SyntaxError: 'continue' not supported inside 'finally' clause
 
     >>> def foo():
     ...     try:
@@ -283,7 +283,7 @@
     ...         continue
     Traceback (most recent call last):
       ...
-    SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[38]>, line 5)
+    SyntaxError: 'continue' not supported inside 'finally' clause
 
     >>> def foo():
     ...     for a in ():
@@ -293,7 +293,7 @@
     ...           continue
     Traceback (most recent call last):
       ...
-    SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[39]>, line 6)
+    SyntaxError: 'continue' not supported inside 'finally' clause
 
     >>> def foo():
     ...     for a in ():
@@ -306,7 +306,7 @@
     ...                 pass
     Traceback (most recent call last):
       ...
-    SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[40]>, line 7)
+    SyntaxError: 'continue' not supported inside 'finally' clause
 
     >>> def foo():
     ...  for a in ():
@@ -318,7 +318,7 @@
     ...     continue
     Traceback (most recent call last):
       ...
-    SyntaxError: 'continue' not supported inside 'finally' clause (<doctest test.test_syntax[41]>, line 8)
+    SyntaxError: 'continue' not supported inside 'finally' clause
 
 There is one test for a break that is not in a loop.  The compiler
 uses a single data structure to keep track of try-finally and loops,
@@ -333,7 +333,7 @@
    ...     print(3)
    Traceback (most recent call last):
      ...
-   SyntaxError: 'break' outside loop (<doctest test.test_syntax[42]>, line 3)
+   SyntaxError: 'break' outside loop
 
 This should probably raise a better error than a SystemError (or none at all).
 In 2.5 there was a missing exception and an assert was triggered in a debug
@@ -420,7 +420,7 @@
    ...   pass
    Traceback (most recent call last):
      ...
-   SyntaxError: can't assign to function call (<doctest test.test_syntax[48]>, line 2)
+   SyntaxError: can't assign to function call
 
    >>> if 1:
    ...   pass
@@ -428,7 +428,7 @@
    ...   x() = 1
    Traceback (most recent call last):
      ...
-   SyntaxError: can't assign to function call (<doctest test.test_syntax[49]>, line 4)
+   SyntaxError: can't assign to function call
 
    >>> if 1:
    ...   x() = 1
@@ -438,7 +438,7 @@
    ...   pass
    Traceback (most recent call last):
      ...
-   SyntaxError: can't assign to function call (<doctest test.test_syntax[50]>, line 2)
+   SyntaxError: can't assign to function call
 
    >>> if 1:
    ...   pass
@@ -448,7 +448,7 @@
    ...   pass
    Traceback (most recent call last):
      ...
-   SyntaxError: can't assign to function call (<doctest test.test_syntax[51]>, line 4)
+   SyntaxError: can't assign to function call
 
    >>> if 1:
    ...   pass
@@ -458,7 +458,7 @@
    ...   x() = 1
    Traceback (most recent call last):
      ...
-   SyntaxError: can't assign to function call (<doctest test.test_syntax[52]>, line 6)
+   SyntaxError: can't assign to function call
 
 """
 
diff --git a/Lib/test/test_unpack_ex.py b/Lib/test/test_unpack_ex.py
index 557e449..7fe486b 100644
--- a/Lib/test/test_unpack_ex.py
+++ b/Lib/test/test_unpack_ex.py
@@ -116,32 +116,32 @@
     >>> a, *b, c, *d, e = range(10) # doctest:+ELLIPSIS
     Traceback (most recent call last):
       ...
-    SyntaxError: two starred expressions in assignment (...)
+    SyntaxError: two starred expressions in assignment
 
     >>> [*b, *c] = range(10) # doctest:+ELLIPSIS
     Traceback (most recent call last):
       ...
-    SyntaxError: two starred expressions in assignment (...)
+    SyntaxError: two starred expressions in assignment
 
     >>> *a = range(10) # doctest:+ELLIPSIS
     Traceback (most recent call last):
       ...
-    SyntaxError: starred assignment target must be in a list or tuple (...)
+    SyntaxError: starred assignment target must be in a list or tuple
 
     >>> *a # doctest:+ELLIPSIS
     Traceback (most recent call last):
       ...
-    SyntaxError: can use starred expression only as assignment target (...)
+    SyntaxError: can use starred expression only as assignment target
 
     >>> *1 # doctest:+ELLIPSIS
     Traceback (most recent call last):
       ...
-    SyntaxError: can use starred expression only as assignment target (...)
+    SyntaxError: can use starred expression only as assignment target
 
     >>> x = *a # doctest:+ELLIPSIS
     Traceback (most recent call last):
       ...
-    SyntaxError: can use starred expression only as assignment target (...)
+    SyntaxError: can use starred expression only as assignment target
 
 """
 
diff --git a/Lib/toaiff.py b/Lib/toaiff.py
deleted file mode 100644
index 438d225..0000000
--- a/Lib/toaiff.py
+++ /dev/null
@@ -1,107 +0,0 @@
-"""Convert "arbitrary" sound files to AIFF (Apple and SGI's audio format).
-
-Input may be compressed.
-Uncompressed file type may be AIFF, WAV, VOC, 8SVX, NeXT/Sun, and others.
-An exception is raised if the file is not of a recognized type.
-Returned filename is either the input filename or a temporary filename;
-in the latter case the caller must ensure that it is removed.
-Other temporary files used are removed by the function.
-"""
-
-import os
-import tempfile
-import pipes
-import sndhdr
-
-__all__ = ["error", "toaiff"]
-
-table = {}
-
-t = pipes.Template()
-t.append('sox -t au - -t aiff -r 8000 -', '--')
-table['au'] = t
-
-# XXX The following is actually sub-optimal.
-# XXX The HCOM sampling rate can be 22k, 22k/2, 22k/3 or 22k/4.
-# XXX We must force the output sampling rate else the SGI won't play
-# XXX files sampled at 5.5k or 7.333k; however this means that files
-# XXX sampled at 11k are unnecessarily expanded.
-# XXX Similar comments apply to some other file types.
-t = pipes.Template()
-t.append('sox -t hcom - -t aiff -r 22050 -', '--')
-table['hcom'] = t
-
-t = pipes.Template()
-t.append('sox -t voc - -t aiff -r 11025 -', '--')
-table['voc'] = t
-
-t = pipes.Template()
-t.append('sox -t wav - -t aiff -', '--')
-table['wav'] = t
-
-t = pipes.Template()
-t.append('sox -t 8svx - -t aiff -r 16000 -', '--')
-table['8svx'] = t
-
-t = pipes.Template()
-t.append('sox -t sndt - -t aiff -r 16000 -', '--')
-table['sndt'] = t
-
-t = pipes.Template()
-t.append('sox -t sndr - -t aiff -r 16000 -', '--')
-table['sndr'] = t
-
-uncompress = pipes.Template()
-uncompress.append('uncompress', '--')
-
-
-class error(Exception):
-    pass
-
-def toaiff(filename):
-    temps = []
-    ret = None
-    try:
-        ret = _toaiff(filename, temps)
-    finally:
-        for temp in temps[:]:
-            if temp != ret:
-                try:
-                    os.unlink(temp)
-                except os.error:
-                    pass
-                temps.remove(temp)
-    return ret
-
-def _toaiff(filename, temps):
-    if filename[-2:] == '.Z':
-        (fd, fname) = tempfile.mkstemp()
-        os.close(fd)
-        temps.append(fname)
-        sts = uncompress.copy(filename, fname)
-        if sts:
-            raise error, filename + ': uncompress failed'
-    else:
-        fname = filename
-    try:
-        ftype = sndhdr.whathdr(fname)
-        if ftype:
-            ftype = ftype[0] # All we're interested in
-    except IOError as msg:
-        if type(msg) == type(()) and len(msg) == 2 and \
-                type(msg[0]) == type(0) and type(msg[1]) == type(''):
-            msg = msg[1]
-        if type(msg) != type(''):
-            msg = repr(msg)
-        raise error, filename + ': ' + msg
-    if ftype == 'aiff':
-        return fname
-    if ftype is None or not ftype in table:
-        raise error, '%s: unsupported audio file type %r' % (filename, ftype)
-    (fd, temp) = tempfile.mkstemp()
-    os.close(fd)
-    temps.append(temp)
-    sts = table[ftype].copy(fname, temp)
-    if sts:
-        raise error, filename + ': conversion to aiff failed'
-    return temp
diff --git a/Lib/traceback.py b/Lib/traceback.py
index 437e29b..11ece25 100644
--- a/Lib/traceback.py
+++ b/Lib/traceback.py
@@ -161,7 +161,6 @@
     string in the list.
 
     """
-
     # Gracefully handle (the way Python 2.4 and earlier did) the case of
     # being called with (None, None).
     if etype is None:
@@ -177,28 +176,24 @@
 
     # It was a syntax error; show exactly where the problem was found.
     lines = []
-    try:
-        msg, (filename, lineno, offset, badline) = value.args
-    except Exception:
-        pass
-    else:
-        filename = filename or "<string>"
-        lines.append('  File "%s", line %d\n' % (filename, lineno))
-        if badline is not None:
-            lines.append('    %s\n' % badline.strip())
-            if offset is not None:
-                caretspace = badline[:offset].lstrip()
-                # non-space whitespace (likes tabs) must be kept for alignment
-                caretspace = ((c.isspace() and c or ' ') for c in caretspace)
-                # only three spaces to account for offset1 == pos 0
-                lines.append('   %s^\n' % ''.join(caretspace))
-            value = msg
-
-    lines.append(_format_final_exc_line(stype, value))
+    filename = value.filename or "<string>"
+    lineno = str(value.lineno) or '?'
+    lines.append('  File "%s", line %s\n' % (filename, lineno))
+    badline = value.text
+    offset = value.offset
+    if badline is not None:
+        lines.append('    %s\n' % badline.strip())
+        if offset is not None:
+            caretspace = badline[:offset].lstrip()
+            # non-space whitespace (likes tabs) must be kept for alignment
+            caretspace = ((c.isspace() and c or ' ') for c in caretspace)
+            # only three spaces to account for offset1 == pos 0
+            lines.append('   %s^\n' % ''.join(caretspace))
+    msg = value.msg or "<no detail available>"
+    lines.append("%s: %s\n" % (stype, msg))
     return lines
 
 def _format_final_exc_line(etype, value):
-    """Return a list of a single line -- normal case for format_exception_only"""
     valuestr = _some_str(value)
     if value is None or not valuestr:
         line = "%s\n" % etype