Added support for including the filename in IOErrors and OSErrors that
involve a filesystem path.  To that end:

- Changed IOError to EnvironmentError and added a hack which checks
  for arg of len 3.  When constructed with a 3-tuple, the third item
  is the filename and this is squirreled away in the `filename'
  attribute.   However, for in-place unpacking backwards
  compatibility, self.args still only gets the first two items.  Added
  a __str__() which prints the filename if it is given.

- IOError now inherits from EnvironmentError

- New class OSError which also inherits from EnvironmentError and is
  used by the posix module.
diff --git a/Lib/exceptions.py b/Lib/exceptions.py
index ba63be6..9eba588 100644
--- a/Lib/exceptions.py
+++ b/Lib/exceptions.py
@@ -80,15 +80,44 @@
     def __str__(self):
         return str(self.msg)
 
-class IOError(StandardError):
+class EnvironmentError(StandardError):
+    """Base class for exceptions that occur outside the Python system.
+    Primarily used as a base class for OSError and IOError."""
     def __init__(self, *args):
         self.args = args
         self.errno = None
         self.strerror = None
+        self.filename = None
+        if len(args) == 3:
+            # open() errors give third argument which is the filename.  BUT,
+            # so common in-place unpacking doesn't break, e.g.:
+            #
+            # except IOError, (errno, strerror):
+            #
+            # we hack args so that it only contains two items.  This also
+            # means we need our own __str__() which prints out the filename
+            # when it was supplied.
+            self.errno, self.strerror, self.filename = args
+            self.args = args[0:2]
         if len(args) == 2:
             # common case: PyErr_SetFromErrno()
-            self.errno = args[0]
-            self.strerror = args[1]
+            self.errno, self.strerror = args
+
+    def __str__(self):
+        if self.filename:
+            return '[Errno %d] %s: %s' % (self.errno, self.strerror,
+                                        self.filename)
+        elif self.errno and self.strerror:
+            return '[Errno %d] %s' % (self.errno, self.strerror)
+        else:
+            return StandardError.__str__(self)
+
+class IOError(EnvironmentError):
+    pass
+
+class OSError(EnvironmentError):
+    """Used by the posix module."""
+    pass
 
 class RuntimeError(StandardError):
     pass