[Python-checkins] r86408 - in python/branches/pep-3151: Include/pyerrors.h Lib/test/exception_hierarchy.txt Lib/test/test_exceptions.py Lib/test/test_mmap.py Lib/test/test_pep3151.py Modules/_io/_iomodule.h Modules/mmapmodule.c Modules/selectmodule.c Modules/socketmodule.c Objects/exceptions.c Python/errors.c

antoine.pitrou python-checkins at python.org
Thu Nov 11 00:20:54 CET 2010


Author: antoine.pitrou
Date: Thu Nov 11 00:20:53 2010
New Revision: 86408

Log:
socket.error -> IOError
select.error -> IOError
mmap.error -> IOError
WindowsError -> IOError
VMSError -> IOError
OSError -> IOError
EnvironmentError -> IOError



Added:
   python/branches/pep-3151/Lib/test/test_pep3151.py
Modified:
   python/branches/pep-3151/Include/pyerrors.h
   python/branches/pep-3151/Lib/test/exception_hierarchy.txt
   python/branches/pep-3151/Lib/test/test_exceptions.py
   python/branches/pep-3151/Lib/test/test_mmap.py
   python/branches/pep-3151/Modules/_io/_iomodule.h
   python/branches/pep-3151/Modules/mmapmodule.c
   python/branches/pep-3151/Modules/selectmodule.c
   python/branches/pep-3151/Modules/socketmodule.c
   python/branches/pep-3151/Objects/exceptions.c
   python/branches/pep-3151/Python/errors.c

Modified: python/branches/pep-3151/Include/pyerrors.h
==============================================================================
--- python/branches/pep-3151/Include/pyerrors.h	(original)
+++ python/branches/pep-3151/Include/pyerrors.h	Thu Nov 11 00:20:53 2010
@@ -44,16 +44,15 @@
     PyObject *myerrno;
     PyObject *strerror;
     PyObject *filename;
-} PyEnvironmentErrorObject;
-
 #ifdef MS_WINDOWS
-typedef struct {
-    PyException_HEAD
-    PyObject *myerrno;
-    PyObject *strerror;
-    PyObject *filename;
     PyObject *winerror;
-} PyWindowsErrorObject;
+#endif
+} PyIOErrorObject;
+
+/* Compatibility typedefs */
+typedef PyIOErrorObject PyEnvironmentErrorObject;
+#ifdef MS_WINDOWS
+typedef PyIOErrorObject PyWindowsErrorObject;
 #endif
 
 /* Error handling definitions */
@@ -119,11 +118,10 @@
 
 PyAPI_DATA(PyObject *) PyExc_AssertionError;
 PyAPI_DATA(PyObject *) PyExc_AttributeError;
+PyAPI_DATA(PyObject *) PyExc_BufferError;
 PyAPI_DATA(PyObject *) PyExc_EOFError;
 PyAPI_DATA(PyObject *) PyExc_FloatingPointError;
-PyAPI_DATA(PyObject *) PyExc_EnvironmentError;
 PyAPI_DATA(PyObject *) PyExc_IOError;
-PyAPI_DATA(PyObject *) PyExc_OSError;
 PyAPI_DATA(PyObject *) PyExc_ImportError;
 PyAPI_DATA(PyObject *) PyExc_IndexError;
 PyAPI_DATA(PyObject *) PyExc_KeyError;
@@ -147,6 +145,10 @@
 PyAPI_DATA(PyObject *) PyExc_UnicodeTranslateError;
 PyAPI_DATA(PyObject *) PyExc_ValueError;
 PyAPI_DATA(PyObject *) PyExc_ZeroDivisionError;
+
+/* Compatibility aliases */
+PyAPI_DATA(PyObject *) PyExc_EnvironmentError;
+PyAPI_DATA(PyObject *) PyExc_OSError;
 #ifdef MS_WINDOWS
 PyAPI_DATA(PyObject *) PyExc_WindowsError;
 #endif
@@ -154,8 +156,6 @@
 PyAPI_DATA(PyObject *) PyExc_VMSError;
 #endif
 
-PyAPI_DATA(PyObject *) PyExc_BufferError;
-
 PyAPI_DATA(PyObject *) PyExc_RecursionErrorInst;
 
 /* Predefined warning categories */

Modified: python/branches/pep-3151/Lib/test/exception_hierarchy.txt
==============================================================================
--- python/branches/pep-3151/Lib/test/exception_hierarchy.txt	(original)
+++ python/branches/pep-3151/Lib/test/exception_hierarchy.txt	Thu Nov 11 00:20:53 2010
@@ -11,13 +11,9 @@
       +-- AssertionError
       +-- AttributeError
       +-- BufferError
-      +-- EnvironmentError
-      |    +-- IOError
-      |    +-- OSError
-      |         +-- WindowsError (Windows)
-      |         +-- VMSError (VMS)
       +-- EOFError
       +-- ImportError
+      +-- IOError
       +-- LookupError
       |    +-- IndexError
       |    +-- KeyError

Modified: python/branches/pep-3151/Lib/test/test_exceptions.py
==============================================================================
--- python/branches/pep-3151/Lib/test/test_exceptions.py	(original)
+++ python/branches/pep-3151/Lib/test/test_exceptions.py	Thu Nov 11 00:20:53 2010
@@ -191,12 +191,34 @@
         except NameError:
             pass
         else:
-            self.assertEqual(str(WindowsError(1001)),
-                                 "1001")
-            self.assertEqual(str(WindowsError(1001, "message")),
-                                 "[Error 1001] message")
-            self.assertEqual(WindowsError(1001, "message").errno, 22)
-            self.assertEqual(WindowsError(1001, "message").winerror, 1001)
+            self.assertIs(WindowsError, IOError)
+            self.assertEqual(str(IOError(1001)), "1001")
+            self.assertEqual(str(IOError(1001, "message")),
+                                         "[Errno 1001] message")
+            # POSIX errno (9 aka EBADF) is untranslated
+            w = IOError(9, 'foo', 'bar')
+            self.assertEqual(w.errno, 9)
+            self.assertEqual(w.winerror, None)
+            self.assertEqual("[Errno 9] foo: 'bar'", str(w))
+            # ERROR_PATH_NOT_FOUND (win error 3) becomes ENOENT (2)
+            w = IOError(0, 'foo', 'bar', 3)
+            self.assertEqual(w.errno, 2)
+            self.assertEqual(w.winerror, 3)
+            self.assertEqual(w.strerror, 'foo')
+            self.assertEqual(w.filename, 'bar')
+            # Unknown win error becomes EINVAL (22)
+            w = IOError(0, 'foo', None, 1001)
+            self.assertEqual(w.errno, 22)
+            self.assertEqual(w.winerror, 1001)
+            self.assertEqual(w.strerror, 'foo')
+            self.assertEqual(w.filename, None)
+            self.assertEqual("[Error 1001] foo", str(w))
+            # Non-numeric "errno"
+            w = IOError('bar', 'foo')
+            self.assertEqual(w.errno, 'bar')
+            self.assertEqual(w.winerror, None)
+            self.assertEqual(w.strerror, 'foo')
+            self.assertEqual(w.filename, None)
 
     def testAttributes(self):
         # test that exception attributes are happy
@@ -274,11 +296,12 @@
                  'start' : 0, 'end' : 1}),
         ]
         try:
+            # More tests are in test_WindowsError
             exceptionList.append(
                 (WindowsError, (1, 'strErrorStr', 'filenameStr'),
                     {'args' : (1, 'strErrorStr'),
-                     'strerror' : 'strErrorStr', 'winerror' : 1,
-                     'errno' : 22, 'filename' : 'filenameStr'})
+                     'strerror' : 'strErrorStr', 'winerror' : None,
+                     'errno' : 1, 'filename' : 'filenameStr'})
             )
         except NameError:
             pass

Modified: python/branches/pep-3151/Lib/test/test_mmap.py
==============================================================================
--- python/branches/pep-3151/Lib/test/test_mmap.py	(original)
+++ python/branches/pep-3151/Lib/test/test_mmap.py	Thu Nov 11 00:20:53 2010
@@ -498,8 +498,7 @@
         f.close()
 
     def test_error(self):
-        self.assertTrue(issubclass(mmap.error, EnvironmentError))
-        self.assertIn("mmap.error", str(mmap.error))
+        self.assertIs(mmap.error, IOError)
 
     def test_io_methods(self):
         data = b"0123456789"

Added: python/branches/pep-3151/Lib/test/test_pep3151.py
==============================================================================
--- (empty file)
+++ python/branches/pep-3151/Lib/test/test_pep3151.py	Thu Nov 11 00:20:53 2010
@@ -0,0 +1,41 @@
+import errno
+import os
+import select
+import socket
+import sys
+import unittest
+
+from test import support
+
+class HierarchyTest(unittest.TestCase):
+
+    def test_builtin_errors(self):
+        self.assertEqual(IOError.__name__, 'IOError')
+        self.assertIs(OSError, IOError)
+        self.assertIs(EnvironmentError, IOError)
+
+    def test_socket_errors(self):
+        self.assertIs(socket.error, IOError)
+        self.assertIs(socket.gaierror.__base__, IOError)
+        self.assertIs(socket.herror.__base__, IOError)
+        self.assertIs(socket.timeout.__base__, IOError)
+
+    def test_select_error(self):
+        self.assertIs(select.error, IOError)
+
+    # mmap.error is tested in test_mmap
+
+    def test_windows_error(self):
+        if os.name == "nt":
+            self.assertIn('winerror', dir(IOError))
+        else:
+            self.assertNotIn('winerror', dir(IOError))
+
+    # XXX VMSError not tested
+
+
+def test_main():
+    support.run_unittest(__name__)
+
+if __name__=="__main__":
+    test_main()

Modified: python/branches/pep-3151/Modules/_io/_iomodule.h
==============================================================================
--- python/branches/pep-3151/Modules/_io/_iomodule.h	(original)
+++ python/branches/pep-3151/Modules/_io/_iomodule.h	Thu Nov 11 00:20:53 2010
@@ -65,6 +65,7 @@
     PyObject *myerrno;
     PyObject *strerror;
     PyObject *filename; /* Not used, but part of the IOError object */
+    PyObject *winerror; /* Same, only under Windows */
     Py_ssize_t written;
 } PyBlockingIOErrorObject;
 PyAPI_DATA(PyObject *) PyExc_BlockingIOError;

Modified: python/branches/pep-3151/Modules/mmapmodule.c
==============================================================================
--- python/branches/pep-3151/Modules/mmapmodule.c	(original)
+++ python/branches/pep-3151/Modules/mmapmodule.c	Thu Nov 11 00:20:53 2010
@@ -75,8 +75,6 @@
 #  define MAP_ANONYMOUS MAP_ANON
 #endif
 
-static PyObject *mmap_module_error;
-
 typedef enum
 {
     ACCESS_DEFAULT,
@@ -430,7 +428,7 @@
     {
         struct stat buf;
         if (-1 == fstat(self->fd, &buf)) {
-            PyErr_SetFromErrno(mmap_module_error);
+            PyErr_SetFromErrno(PyExc_IOError);
             return NULL;
         }
         return PyLong_FromSsize_t(buf.st_size);
@@ -523,7 +521,7 @@
         void *newmap;
 
         if (ftruncate(self->fd, self->offset + new_size) == -1) {
-            PyErr_SetFromErrno(mmap_module_error);
+            PyErr_SetFromErrno(PyExc_IOError);
             return NULL;
         }
 
@@ -538,7 +536,7 @@
 #endif
         if (newmap == (void *)-1)
         {
-            PyErr_SetFromErrno(mmap_module_error);
+            PyErr_SetFromErrno(PyExc_IOError);
             return NULL;
         }
         self->data = newmap;
@@ -579,7 +577,7 @@
     /* XXX semantics of return value? */
     /* XXX flags for msync? */
     if (-1 == msync(self->data + offset, size, MS_SYNC)) {
-        PyErr_SetFromErrno(mmap_module_error);
+        PyErr_SetFromErrno(PyExc_IOError);
         return NULL;
     }
     return PyLong_FromLong(0);
@@ -1145,7 +1143,7 @@
         fd = devzero = open("/dev/zero", O_RDWR);
         if (devzero == -1) {
             Py_DECREF(m_obj);
-            PyErr_SetFromErrno(mmap_module_error);
+            PyErr_SetFromErrno(PyExc_IOError);
             return NULL;
         }
 #endif
@@ -1153,7 +1151,7 @@
         m_obj->fd = dup(fd);
         if (m_obj->fd == -1) {
             Py_DECREF(m_obj);
-            PyErr_SetFromErrno(mmap_module_error);
+            PyErr_SetFromErrno(PyExc_IOError);
             return NULL;
         }
     }
@@ -1169,7 +1167,7 @@
     if (m_obj->data == (char *)-1) {
         m_obj->data = NULL;
         Py_DECREF(m_obj);
-        PyErr_SetFromErrno(mmap_module_error);
+        PyErr_SetFromErrno(PyExc_IOError);
         return NULL;
     }
     m_obj->access = (access_mode)access;
@@ -1241,12 +1239,12 @@
     if (fileno != -1 && fileno != 0) {
         /* Ensure that fileno is within the CRT's valid range */
         if (_PyVerify_fd(fileno) == 0) {
-            PyErr_SetFromErrno(mmap_module_error);
+            PyErr_SetFromErrno(PyExc_IOError);
             return NULL;
         }
         fh = (HANDLE)_get_osfhandle(fileno);
         if (fh==(HANDLE)-1) {
-            PyErr_SetFromErrno(mmap_module_error);
+            PyErr_SetFromErrno(PyExc_IOError);
             return NULL;
         }
         /* Win9x appears to need us seeked to zero */
@@ -1407,11 +1405,7 @@
     dict = PyModule_GetDict(module);
     if (!dict)
         return NULL;
-    mmap_module_error = PyErr_NewException("mmap.error",
-        PyExc_EnvironmentError , NULL);
-    if (mmap_module_error == NULL)
-        return NULL;
-    PyDict_SetItemString(dict, "error", mmap_module_error);
+    PyDict_SetItemString(dict, "error", PyExc_IOError);
     PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type);
 #ifdef PROT_EXEC
     setint(dict, "PROT_EXEC", PROT_EXEC);

Modified: python/branches/pep-3151/Modules/selectmodule.c
==============================================================================
--- python/branches/pep-3151/Modules/selectmodule.c	(original)
+++ python/branches/pep-3151/Modules/selectmodule.c	Thu Nov 11 00:20:53 2010
@@ -54,8 +54,6 @@
 #  endif
 #endif
 
-static PyObject *SelectError;
-
 /* list of Python objects and their file descriptor */
 typedef struct {
     PyObject *obj;                           /* owned reference */
@@ -277,11 +275,11 @@
 
 #ifdef MS_WINDOWS
     if (n == SOCKET_ERROR) {
-        PyErr_SetExcFromWindowsErr(SelectError, WSAGetLastError());
+        PyErr_SetExcFromWindowsErr(PyExc_IOError, WSAGetLastError());
     }
 #else
     if (n < 0) {
-        PyErr_SetFromErrno(SelectError);
+        PyErr_SetFromErrno(PyExc_IOError);
     }
 #endif
     else {
@@ -527,7 +525,7 @@
     Py_END_ALLOW_THREADS
 
     if (poll_result < 0) {
-        PyErr_SetFromErrno(SelectError);
+        PyErr_SetFromErrno(PyExc_IOError);
         return NULL;
     }
 
@@ -1781,9 +1779,8 @@
     if (m == NULL)
         return NULL;
 
-    SelectError = PyErr_NewException("select.error", NULL, NULL);
-    Py_INCREF(SelectError);
-    PyModule_AddObject(m, "error", SelectError);
+    Py_INCREF(PyExc_IOError);
+    PyModule_AddObject(m, "error", PyExc_IOError);
 
 #ifdef PIPE_BUF
 #ifdef HAVE_BROKEN_PIPE_BUF

Modified: python/branches/pep-3151/Modules/socketmodule.c
==============================================================================
--- python/branches/pep-3151/Modules/socketmodule.c	(original)
+++ python/branches/pep-3151/Modules/socketmodule.c	Thu Nov 11 00:20:53 2010
@@ -438,7 +438,6 @@
 
 /* Global variable holding the exception type for errors detected
    by this module (but not argument type or memory errors, etc.). */
-static PyObject *socket_error;
 static PyObject *socket_herror;
 static PyObject *socket_gaierror;
 static PyObject *socket_timeout;
@@ -472,7 +471,7 @@
 static PyObject*
 select_error(void)
 {
-    PyErr_SetString(socket_error, "unable to select on socket");
+    PyErr_SetString(PyExc_IOError, "unable to select on socket");
     return NULL;
 }
 
@@ -499,7 +498,7 @@
        recognizes the error codes used by both GetLastError() and
        WSAGetLastError */
     if (err_no)
-        return PyErr_SetExcFromWindowsErr(socket_error, err_no);
+        return PyErr_SetExcFromWindowsErr(PyExc_IOError, err_no);
 #endif
 
 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
@@ -530,7 +529,7 @@
             }
             v = Py_BuildValue("(is)", myerrorcode, outbuf);
             if (v != NULL) {
-                PyErr_SetObject(socket_error, v);
+                PyErr_SetObject(PyExc_IOError, v);
                 Py_DECREF(v);
             }
             return NULL;
@@ -538,7 +537,7 @@
     }
 #endif
 
-    return PyErr_SetFromErrno(socket_error);
+    return PyErr_SetFromErrno(PyExc_IOError);
 }
 
 
@@ -857,13 +856,13 @@
 #endif
         default:
             freeaddrinfo(res);
-            PyErr_SetString(socket_error,
+            PyErr_SetString(PyExc_IOError,
                 "unsupported address family");
             return -1;
         }
         if (res->ai_next) {
             freeaddrinfo(res);
-            PyErr_SetString(socket_error,
+            PyErr_SetString(PyExc_IOError,
                 "wildcard resolved to multiple address");
             return -1;
         }
@@ -876,7 +875,7 @@
     if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
         struct sockaddr_in *sin;
         if (af != AF_INET && af != AF_UNSPEC) {
-            PyErr_SetString(socket_error,
+            PyErr_SetString(PyExc_IOError,
                 "address family mismatched");
             return -1;
         }
@@ -934,7 +933,7 @@
         return 16;
 #endif
     default:
-        PyErr_SetString(socket_error, "unknown address family");
+        PyErr_SetString(PyExc_IOError, "unknown address family");
         return -1;
     }
 }
@@ -983,7 +982,7 @@
         bdaddr->b[5] = b5;
         return 6;
     } else {
-        PyErr_SetString(socket_error, "bad bluetooth address");
+        PyErr_SetString(PyExc_IOError, "bad bluetooth address");
         return -1;
     }
 }
@@ -1233,7 +1232,7 @@
         if (len > 0 && path[0] == 0) {
             /* Linux abstract namespace extension */
             if (len > sizeof addr->sun_path) {
-                PyErr_SetString(socket_error,
+                PyErr_SetString(PyExc_IOError,
                                 "AF_UNIX path too long");
                 return 0;
             }
@@ -1243,7 +1242,7 @@
         {
             /* regular NULL-terminated string */
             if (len >= sizeof addr->sun_path) {
-                PyErr_SetString(socket_error,
+                PyErr_SetString(PyExc_IOError,
                                 "AF_UNIX path too long");
                 return 0;
             }
@@ -1373,7 +1372,7 @@
             _BT_L2_MEMB(addr, family) = AF_BLUETOOTH;
             if (!PyArg_ParseTuple(args, "si", &straddr,
                                   &_BT_L2_MEMB(addr, psm))) {
-                PyErr_SetString(socket_error, "getsockaddrarg: "
+                PyErr_SetString(PyExc_IOError, "getsockaddrarg: "
                                 "wrong format");
                 return 0;
             }
@@ -1392,7 +1391,7 @@
             _BT_RC_MEMB(addr, family) = AF_BLUETOOTH;
             if (!PyArg_ParseTuple(args, "si", &straddr,
                                   &_BT_RC_MEMB(addr, channel))) {
-                PyErr_SetString(socket_error, "getsockaddrarg: "
+                PyErr_SetString(PyExc_IOError, "getsockaddrarg: "
                                 "wrong format");
                 return 0;
             }
@@ -1410,7 +1409,7 @@
 
 			_BT_HCI_MEMB(addr, family) = AF_BLUETOOTH;
             if (straddr == NULL) {
-                PyErr_SetString(socket_error, "getsockaddrarg: "
+                PyErr_SetString(PyExc_IOError, "getsockaddrarg: "
                     "wrong format");
                 return 0;
             }
@@ -1419,7 +1418,7 @@
 #else
             _BT_HCI_MEMB(addr, family) = AF_BLUETOOTH;
             if (!PyArg_ParseTuple(args, "i", &_BT_HCI_MEMB(addr, dev))) {
-                PyErr_SetString(socket_error, "getsockaddrarg: "
+                PyErr_SetString(PyExc_IOError, "getsockaddrarg: "
                                 "wrong format");
                 return 0;
             }
@@ -1436,7 +1435,7 @@
             addr = (struct sockaddr_sco *)addr_ret;
             _BT_SCO_MEMB(addr, family) = AF_BLUETOOTH;
             if (!PyBytes_Check(args)) {
-                PyErr_SetString(socket_error, "getsockaddrarg: "
+                PyErr_SetString(PyExc_IOError, "getsockaddrarg: "
                                 "wrong format");
                 return 0;
             }
@@ -1449,7 +1448,7 @@
         }
 #endif
         default:
-            PyErr_SetString(socket_error, "getsockaddrarg: unknown Bluetooth protocol");
+            PyErr_SetString(PyExc_IOError, "getsockaddrarg: unknown Bluetooth protocol");
             return 0;
         }
     }
@@ -1564,7 +1563,7 @@
     /* More cases here... */
 
     default:
-        PyErr_SetString(socket_error, "getsockaddrarg: bad family");
+        PyErr_SetString(PyExc_IOError, "getsockaddrarg: bad family");
         return 0;
 
     }
@@ -1630,7 +1629,7 @@
             return 1;
 #endif
         default:
-            PyErr_SetString(socket_error, "getsockaddrlen: "
+            PyErr_SetString(PyExc_IOError, "getsockaddrlen: "
                             "unknown BT protocol");
             return 0;
 
@@ -1657,7 +1656,7 @@
     /* More cases here... */
 
     default:
-        PyErr_SetString(socket_error, "getsockaddrlen: bad family");
+        PyErr_SetString(PyExc_IOError, "getsockaddrlen: bad family");
         return 0;
 
     }
@@ -1886,7 +1885,7 @@
 #else
     if (buflen <= 0 || buflen > 1024) {
 #endif
-        PyErr_SetString(socket_error,
+        PyErr_SetString(PyExc_IOError,
                         "getsockopt buflen out of range");
         return NULL;
     }
@@ -3181,7 +3180,7 @@
 
     if (h->h_addrtype != af) {
         /* Let's get real error message to return */
-        PyErr_SetString(socket_error,
+        PyErr_SetString(PyExc_IOError,
                         (char *)strerror(EAFNOSUPPORT));
 
         return NULL;
@@ -3266,7 +3265,7 @@
 #endif
 
         default:                /* can't happen */
-            PyErr_SetString(socket_error,
+            PyErr_SetString(PyExc_IOError,
                             "unsupported address family");
             return NULL;
         }
@@ -3420,7 +3419,7 @@
         break;
 #endif
     default:
-        PyErr_SetString(socket_error, "unsupported address family");
+        PyErr_SetString(PyExc_IOError, "unsupported address family");
         goto finally;
     }
     Py_BEGIN_ALLOW_THREADS
@@ -3476,7 +3475,7 @@
     sp = getservbyname(name, proto);
     Py_END_ALLOW_THREADS
     if (sp == NULL) {
-        PyErr_SetString(socket_error, "service/proto not found");
+        PyErr_SetString(PyExc_IOError, "service/proto not found");
         return NULL;
     }
     return PyLong_FromLong((long) ntohs(sp->s_port));
@@ -3513,7 +3512,7 @@
     sp = getservbyport(htons((short)port), proto);
     Py_END_ALLOW_THREADS
     if (sp == NULL) {
-        PyErr_SetString(socket_error, "port/proto not found");
+        PyErr_SetString(PyExc_IOError, "port/proto not found");
         return NULL;
     }
     return PyUnicode_FromString(sp->s_name);
@@ -3542,7 +3541,7 @@
     sp = getprotobyname(name);
     Py_END_ALLOW_THREADS
     if (sp == NULL) {
-        PyErr_SetString(socket_error, "protocol not found");
+        PyErr_SetString(PyExc_IOError, "protocol not found");
         return NULL;
     }
     return PyLong_FromLong((long) sp->p_proto);
@@ -3797,7 +3796,7 @@
         return PyBytes_FromStringAndSize((char *)(&buf),
                                           sizeof(buf));
 
-    PyErr_SetString(socket_error,
+    PyErr_SetString(PyExc_IOError,
                     "illegal IP address string passed to inet_aton");
     return NULL;
 
@@ -3818,7 +3817,7 @@
         packed_addr = inet_addr(ip_addr);
 
         if (packed_addr == INADDR_NONE) {               /* invalid address */
-            PyErr_SetString(socket_error,
+            PyErr_SetString(PyExc_IOError,
                 "illegal IP address string passed to inet_aton");
             return NULL;
         }
@@ -3850,7 +3849,7 @@
     }
 
     if (addr_len != sizeof(packed_addr)) {
-        PyErr_SetString(socket_error,
+        PyErr_SetString(PyExc_IOError,
             "packed IP wrong length for inet_ntoa");
         return NULL;
     }
@@ -3885,7 +3884,7 @@
 
 #if !defined(ENABLE_IPV6) && defined(AF_INET6)
     if(af == AF_INET6) {
-        PyErr_SetString(socket_error,
+        PyErr_SetString(PyExc_IOError,
                         "can't use AF_INET6, IPv6 is disabled");
         return NULL;
     }
@@ -3893,10 +3892,10 @@
 
     retval = inet_pton(af, ip, packed);
     if (retval < 0) {
-        PyErr_SetFromErrno(socket_error);
+        PyErr_SetFromErrno(PyExc_IOError);
         return NULL;
     } else if (retval == 0) {
-        PyErr_SetString(socket_error,
+        PyErr_SetString(PyExc_IOError,
             "illegal IP address string passed to inet_pton");
         return NULL;
     } else if (af == AF_INET) {
@@ -3908,7 +3907,7 @@
                                           sizeof(struct in6_addr));
 #endif
     } else {
-        PyErr_SetString(socket_error, "unknown address family");
+        PyErr_SetString(PyExc_IOError, "unknown address family");
         return NULL;
     }
 }
@@ -3960,7 +3959,7 @@
 
     retval = inet_ntop(af, packed, ip, sizeof(ip));
     if (!retval) {
-        PyErr_SetFromErrno(socket_error);
+        PyErr_SetFromErrno(PyExc_IOError);
         return NULL;
     } else {
         return PyUnicode_FromString(retval);
@@ -4027,7 +4026,7 @@
     } else if (pobj == Py_None) {
         pptr = (char *)NULL;
     } else {
-        PyErr_SetString(socket_error, "Int or String expected");
+        PyErr_SetString(PyExc_IOError, "Int or String expected");
         goto err;
     }
     memset(&hints, 0, sizeof(hints));
@@ -4124,7 +4123,7 @@
         goto fail;
     }
     if (res->ai_next) {
-        PyErr_SetString(socket_error,
+        PyErr_SetString(PyExc_IOError,
             "sockaddr resolved to multiple addresses");
         goto fail;
     }
@@ -4132,7 +4131,7 @@
     case AF_INET:
         {
         if (PyTuple_GET_SIZE(sa) != 2) {
-            PyErr_SetString(socket_error,
+            PyErr_SetString(PyExc_IOError,
                 "IPv4 sockaddr must be 2 tuple");
             goto fail;
         }
@@ -4402,27 +4401,24 @@
     if (m == NULL)
         return NULL;
 
-    socket_error = PyErr_NewException("socket.error",
-                                      PyExc_IOError, NULL);
-    if (socket_error == NULL)
-        return NULL;
-    PySocketModuleAPI.error = socket_error;
-    Py_INCREF(socket_error);
-    PyModule_AddObject(m, "error", socket_error);
+    Py_INCREF(PyExc_IOError);
+    PySocketModuleAPI.error = PyExc_IOError;
+    Py_INCREF(PyExc_IOError);
+    PyModule_AddObject(m, "error", PyExc_IOError);
     socket_herror = PyErr_NewException("socket.herror",
-                                       socket_error, NULL);
+                                       PyExc_IOError, NULL);
     if (socket_herror == NULL)
         return NULL;
     Py_INCREF(socket_herror);
     PyModule_AddObject(m, "herror", socket_herror);
-    socket_gaierror = PyErr_NewException("socket.gaierror", socket_error,
+    socket_gaierror = PyErr_NewException("socket.gaierror", PyExc_IOError,
         NULL);
     if (socket_gaierror == NULL)
         return NULL;
     Py_INCREF(socket_gaierror);
     PyModule_AddObject(m, "gaierror", socket_gaierror);
     socket_timeout = PyErr_NewException("socket.timeout",
-                                        socket_error, NULL);
+                                        PyExc_IOError, NULL);
     if (socket_timeout == NULL)
         return NULL;
     Py_INCREF(socket_timeout);

Modified: python/branches/pep-3151/Objects/exceptions.c
==============================================================================
--- python/branches/pep-3151/Objects/exceptions.c	(original)
+++ python/branches/pep-3151/Objects/exceptions.c	Thu Nov 11 00:20:53 2010
@@ -10,6 +10,16 @@
 #include "osdefs.h"
 
 
+/* Compatibility aliases */
+PyObject *PyExc_EnvironmentError = NULL;
+PyObject *PyExc_OSError = NULL;
+#ifdef MS_WINDOWS
+PyObject *PyExc_WindowsError = NULL;
+#endif
+#ifdef __VMS
+PyObject *PyExc_VMSError = NULL;
+#endif
+
 /* NOTE: If the exception class hierarchy changes, don't forget to update
  * Lib/test/exception_hierarchy.txt
  */
@@ -552,9 +562,13 @@
 
 
 /*
- *    EnvironmentError extends Exception
+ *    IOError extends Exception
  */
 
+#ifdef MS_WINDOWS
+#include "errmap.h"
+#endif
+
 /* Where a function has a single filename, such as open() or some
  * of the os module functions, PyErr_SetFromErrnoWithFilename() is
  * called, giving a third argument which is the filename.  But, so
@@ -567,23 +581,38 @@
  * when it was supplied.
  */
 static int
-EnvironmentError_init(PyEnvironmentErrorObject *self, PyObject *args,
+IOError_init(PyIOErrorObject *self, PyObject *args,
     PyObject *kwds)
 {
     PyObject *myerrno = NULL, *strerror = NULL, *filename = NULL;
     PyObject *subslice = NULL;
+#ifdef MS_WINDOWS
+    PyObject *winerror = NULL;
+#endif
 
     if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
         return -1;
 
+#ifdef MS_WINDOWS
+    if (PyTuple_GET_SIZE(args) <= 1 || PyTuple_GET_SIZE(args) > 4) {
+        return 0;
+    }
+    if (!PyArg_UnpackTuple(args, "IOError", 2, 4,
+                           &myerrno, &strerror, &filename, &winerror)) {
+        return -1;
+    }
+    /* 4-args form with non-int 4th arg; just store the args tuple */
+    if (winerror && !PyLong_Check(winerror))
+        return 0;
+#else
     if (PyTuple_GET_SIZE(args) <= 1 || PyTuple_GET_SIZE(args) > 3) {
         return 0;
     }
-
-    if (!PyArg_UnpackTuple(args, "EnvironmentError", 2, 3,
+    if (!PyArg_UnpackTuple(args, "IOError", 2, 3,
                            &myerrno, &strerror, &filename)) {
         return -1;
     }
+#endif
     Py_CLEAR(self->myerrno);       /* replacing */
     self->myerrno = myerrno;
     Py_INCREF(self->myerrno);
@@ -592,8 +621,41 @@
     self->strerror = strerror;
     Py_INCREF(self->strerror);
 
+#ifdef MS_WINDOWS
+    /* NOTE: when calling the WindowsError constructor explicitly, behaviour
+       is changed compared to previous versions:
+       - previous signature:
+           WindowsError(winerror[, strerror[, filename]])
+       - new signature:
+           WindowsError(posix_errno[, strerror[, filename, [winerror]]])
+    */
+    Py_XINCREF(winerror);
+    Py_CLEAR(self->winerror);
+    self->winerror = winerror;
+    /* If the optional "winerror" is passed, set errno to the corresponding
+       POSIX errno. */
+    if (self->winerror != NULL) {
+        PyObject *o_errcode = NULL;
+        long errcode;
+        long posix_errno;
+
+        errcode = PyLong_AsLong(self->winerror);
+        if (errcode == -1 && PyErr_Occurred())
+            PyErr_Clear();
+        else {
+            posix_errno = winerror_to_errno(errcode);
+
+            o_errcode = PyLong_FromLong(posix_errno);
+            if (!o_errcode)
+                return -1;
+            Py_CLEAR(self->myerrno);
+            self->myerrno = o_errcode;
+        }
+    }
+#endif
+
     /* self->filename will remain Py_None otherwise */
-    if (filename != NULL) {
+    if (filename != NULL && filename != Py_None) {
         Py_CLEAR(self->filename);      /* replacing */
         self->filename = filename;
         Py_INCREF(self->filename);
@@ -609,67 +671,87 @@
 }
 
 static int
-EnvironmentError_clear(PyEnvironmentErrorObject *self)
+IOError_clear(PyIOErrorObject *self)
 {
     Py_CLEAR(self->myerrno);
     Py_CLEAR(self->strerror);
     Py_CLEAR(self->filename);
+#ifdef MS_WINDOWS
+    Py_CLEAR(self->winerror);
+#endif
     return BaseException_clear((PyBaseExceptionObject *)self);
 }
 
 static void
-EnvironmentError_dealloc(PyEnvironmentErrorObject *self)
+IOError_dealloc(PyIOErrorObject *self)
 {
     _PyObject_GC_UNTRACK(self);
-    EnvironmentError_clear(self);
+    IOError_clear(self);
     Py_TYPE(self)->tp_free((PyObject *)self);
 }
 
 static int
-EnvironmentError_traverse(PyEnvironmentErrorObject *self, visitproc visit,
+IOError_traverse(PyIOErrorObject *self, visitproc visit,
         void *arg)
 {
     Py_VISIT(self->myerrno);
     Py_VISIT(self->strerror);
     Py_VISIT(self->filename);
+#ifdef MS_WINDOWS
+    Py_VISIT(self->winerror);
+#endif
     return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
 }
 
 static PyObject *
-EnvironmentError_str(PyEnvironmentErrorObject *self)
+IOError_str(PyIOErrorObject *self)
 {
+#ifdef MS_WINDOWS
+    /* If available, winerror has the priority over myerrno */
+    if (self->winerror && self->filename)
+        return PyUnicode_FromFormat("[Error %S] %S: %R",
+                                    self->winerror ? self->winerror: Py_None,
+                                    self->strerror ? self->strerror: Py_None,
+                                    self->filename);
+    if (self->winerror && self->strerror)
+        return PyUnicode_FromFormat("[Error %S] %S",
+                                    self->winerror ? self->winerror: Py_None,
+                                    self->strerror ? self->strerror: Py_None);
+#endif
     if (self->filename)
         return PyUnicode_FromFormat("[Errno %S] %S: %R",
                                     self->myerrno ? self->myerrno: Py_None,
                                     self->strerror ? self->strerror: Py_None,
                                     self->filename);
-    else if (self->myerrno && self->strerror)
+    if (self->myerrno && self->strerror)
         return PyUnicode_FromFormat("[Errno %S] %S",
                                     self->myerrno ? self->myerrno: Py_None,
                                     self->strerror ? self->strerror: Py_None);
-    else
-        return BaseException_str((PyBaseExceptionObject *)self);
+    return BaseException_str((PyBaseExceptionObject *)self);
 }
 
-static PyMemberDef EnvironmentError_members[] = {
-    {"errno", T_OBJECT, offsetof(PyEnvironmentErrorObject, myerrno), 0,
-        PyDoc_STR("exception errno")},
-    {"strerror", T_OBJECT, offsetof(PyEnvironmentErrorObject, strerror), 0,
+static PyMemberDef IOError_members[] = {
+    {"errno", T_OBJECT, offsetof(PyIOErrorObject, myerrno), 0,
+        PyDoc_STR("POSIX exception code")},
+    {"strerror", T_OBJECT, offsetof(PyIOErrorObject, strerror), 0,
         PyDoc_STR("exception strerror")},
-    {"filename", T_OBJECT, offsetof(PyEnvironmentErrorObject, filename), 0,
+    {"filename", T_OBJECT, offsetof(PyIOErrorObject, filename), 0,
         PyDoc_STR("exception filename")},
+#ifdef MS_WINDOWS
+    {"winerror", T_OBJECT, offsetof(PyIOErrorObject, winerror), 0,
+        PyDoc_STR("Win32 exception code")},
+#endif
     {NULL}  /* Sentinel */
 };
 
-
 static PyObject *
-EnvironmentError_reduce(PyEnvironmentErrorObject *self)
+IOError_reduce(PyIOErrorObject *self)
 {
     PyObject *args = self->args;
     PyObject *res = NULL, *tmp;
 
     /* self->args is only the first two real arguments if there was a
-     * file name given to EnvironmentError. */
+     * file name given to IOError. */
     if (PyTuple_GET_SIZE(args) == 2 && self->filename) {
         args = PyTuple_New(3);
         if (!args) return NULL;
@@ -696,145 +778,19 @@
 }
 
 
-static PyMethodDef EnvironmentError_methods[] = {
-    {"__reduce__", (PyCFunction)EnvironmentError_reduce, METH_NOARGS},
+static PyMethodDef IOError_methods[] = {
+    {"__reduce__", (PyCFunction)IOError_reduce, METH_NOARGS},
     {NULL}
 };
 
-ComplexExtendsException(PyExc_Exception, EnvironmentError,
-                        EnvironmentError, EnvironmentError_dealloc,
-                        EnvironmentError_methods, EnvironmentError_members,
-                        EnvironmentError_str,
+ComplexExtendsException(PyExc_Exception, IOError,
+                        IOError, IOError_dealloc,
+                        IOError_methods, IOError_members,
+                        IOError_str,
                         "Base class for I/O related errors.");
 
 
 /*
- *    IOError extends EnvironmentError
- */
-MiddlingExtendsException(PyExc_EnvironmentError, IOError,
-                         EnvironmentError, "I/O operation failed.");
-
-
-/*
- *    OSError extends EnvironmentError
- */
-MiddlingExtendsException(PyExc_EnvironmentError, OSError,
-                         EnvironmentError, "OS system call failed.");
-
-
-/*
- *    WindowsError extends OSError
- */
-#ifdef MS_WINDOWS
-#include "errmap.h"
-
-static int
-WindowsError_clear(PyWindowsErrorObject *self)
-{
-    Py_CLEAR(self->myerrno);
-    Py_CLEAR(self->strerror);
-    Py_CLEAR(self->filename);
-    Py_CLEAR(self->winerror);
-    return BaseException_clear((PyBaseExceptionObject *)self);
-}
-
-static void
-WindowsError_dealloc(PyWindowsErrorObject *self)
-{
-    _PyObject_GC_UNTRACK(self);
-    WindowsError_clear(self);
-    Py_TYPE(self)->tp_free((PyObject *)self);
-}
-
-static int
-WindowsError_traverse(PyWindowsErrorObject *self, visitproc visit, void *arg)
-{
-    Py_VISIT(self->myerrno);
-    Py_VISIT(self->strerror);
-    Py_VISIT(self->filename);
-    Py_VISIT(self->winerror);
-    return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
-}
-
-static int
-WindowsError_init(PyWindowsErrorObject *self, PyObject *args, PyObject *kwds)
-{
-    PyObject *o_errcode = NULL;
-    long errcode;
-    long posix_errno;
-
-    if (EnvironmentError_init((PyEnvironmentErrorObject *)self, args, kwds)
-            == -1)
-        return -1;
-
-    if (self->myerrno == NULL)
-        return 0;
-
-    /* Set errno to the POSIX errno, and winerror to the Win32
-       error code. */
-    errcode = PyLong_AsLong(self->myerrno);
-    if (errcode == -1 && PyErr_Occurred())
-        return -1;
-    posix_errno = winerror_to_errno(errcode);
-
-    Py_CLEAR(self->winerror);
-    self->winerror = self->myerrno;
-
-    o_errcode = PyLong_FromLong(posix_errno);
-    if (!o_errcode)
-        return -1;
-
-    self->myerrno = o_errcode;
-
-    return 0;
-}
-
-
-static PyObject *
-WindowsError_str(PyWindowsErrorObject *self)
-{
-    if (self->filename)
-        return PyUnicode_FromFormat("[Error %S] %S: %R",
-                                    self->winerror ? self->winerror: Py_None,
-                                    self->strerror ? self->strerror: Py_None,
-                                    self->filename);
-    else if (self->winerror && self->strerror)
-        return PyUnicode_FromFormat("[Error %S] %S",
-                                    self->winerror ? self->winerror: Py_None,
-                                    self->strerror ? self->strerror: Py_None);
-    else
-        return EnvironmentError_str((PyEnvironmentErrorObject *)self);
-}
-
-static PyMemberDef WindowsError_members[] = {
-    {"errno", T_OBJECT, offsetof(PyWindowsErrorObject, myerrno), 0,
-        PyDoc_STR("POSIX exception code")},
-    {"strerror", T_OBJECT, offsetof(PyWindowsErrorObject, strerror), 0,
-        PyDoc_STR("exception strerror")},
-    {"filename", T_OBJECT, offsetof(PyWindowsErrorObject, filename), 0,
-        PyDoc_STR("exception filename")},
-    {"winerror", T_OBJECT, offsetof(PyWindowsErrorObject, winerror), 0,
-        PyDoc_STR("Win32 exception code")},
-    {NULL}  /* Sentinel */
-};
-
-ComplexExtendsException(PyExc_OSError, WindowsError, WindowsError,
-                        WindowsError_dealloc, 0, WindowsError_members,
-                        WindowsError_str, "MS-Windows OS system call failed.");
-
-#endif /* MS_WINDOWS */
-
-
-/*
- *    VMSError extends OSError (I think)
- */
-#ifdef __VMS
-MiddlingExtendsException(PyExc_OSError, VMSError, EnvironmentError,
-                         "OpenVMS OS system call failed.");
-#endif
-
-
-/*
  *    EOFError extends Exception
  */
 SimpleExtendsException(PyExc_Exception, EOFError,
@@ -1966,6 +1922,11 @@
     if (PyDict_SetItemString(bdict, # TYPE, PyExc_ ## TYPE)) \
         Py_FatalError("Module dictionary insertion problem.");
 
+#define INIT_ALIAS(NAME, TYPE) Py_INCREF(PyExc_ ## TYPE); \
+    PyExc_ ## NAME = PyExc_ ## TYPE; \
+    if (PyDict_SetItemString(bdict, # NAME, PyExc_ ## NAME)) \
+        Py_FatalError("Module dictionary insertion problem.");
+
 
 void
 _PyExc_Init(void)
@@ -1980,15 +1941,7 @@
     PRE_INIT(SystemExit)
     PRE_INIT(KeyboardInterrupt)
     PRE_INIT(ImportError)
-    PRE_INIT(EnvironmentError)
     PRE_INIT(IOError)
-    PRE_INIT(OSError)
-#ifdef MS_WINDOWS
-    PRE_INIT(WindowsError)
-#endif
-#ifdef __VMS
-    PRE_INIT(VMSError)
-#endif
     PRE_INIT(EOFError)
     PRE_INIT(RuntimeError)
     PRE_INIT(NotImplementedError)
@@ -2043,14 +1996,14 @@
     POST_INIT(SystemExit)
     POST_INIT(KeyboardInterrupt)
     POST_INIT(ImportError)
-    POST_INIT(EnvironmentError)
     POST_INIT(IOError)
-    POST_INIT(OSError)
+    INIT_ALIAS(EnvironmentError, IOError)
+    INIT_ALIAS(OSError, IOError)
 #ifdef MS_WINDOWS
-    POST_INIT(WindowsError)
+    INIT_ALIAS(WindowsError, IOError)
 #endif
 #ifdef __VMS
-    POST_INIT(VMSError)
+    INIT_ALIAS(VMSError, IOError)
 #endif
     POST_INIT(EOFError)
     POST_INIT(RuntimeError)

Modified: python/branches/pep-3151/Python/errors.c
==============================================================================
--- python/branches/pep-3151/Python/errors.c	(original)
+++ python/branches/pep-3151/Python/errors.c	Thu Nov 11 00:20:53 2010
@@ -496,10 +496,15 @@
         return NULL;
     }
 
-    if (filenameObject != NULL)
-        v = Py_BuildValue("(iOO)", err, message, filenameObject);
+    if (filenameObject == NULL)
+        filenameObject = Py_None;
+    /* errcodes >= 10000 correspond to socket error codes; no need to convert
+       them to a POSIX errno since they are natively recognized by Python
+       (also, trying to convert would end up with EINVAL) */
+    if (err < 10000)
+        v = Py_BuildValue("(iOOi)", err, message, filenameObject, err);
     else
-        v = Py_BuildValue("(iO)", err, message);
+        v = Py_BuildValue("(iOO)", err, message, filenameObject);
     Py_DECREF(message);
 
     if (v != NULL) {


More information about the Python-checkins mailing list