]> granicus.if.org Git - python/commitdiff
Change WindowsError to carry the Win32 error code in winerror,
authorMartin v. Löwis <martin@v.loewis.de>
Thu, 11 May 2006 13:28:43 +0000 (13:28 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Thu, 11 May 2006 13:28:43 +0000 (13:28 +0000)
and the DOS error code in errno. Revert changes where
WindowsError catch blocks unnecessarily special-case OSError.

Doc/lib/libexcs.tex
Lib/mailbox.py
Lib/tempfile.py
Misc/NEWS
PC/errmap.h [new file with mode: 0644]
PC/errmap.mak [new file with mode: 0644]
PC/generrmap.c [new file with mode: 0644]
Python/exceptions.c

index f52ff0a952b7f2e03836816476b92901c4530b57..b51b7fc89b5fdb44fd8e980d6cbb22807beed772 100644 (file)
@@ -399,11 +399,15 @@ Raised when an \keyword{assert} statement fails.
 \begin{excdesc}{WindowsError}
   Raised when a Windows-specific error occurs or when the error number
   does not correspond to an \cdata{errno} value.  The
-  \member{errno} and \member{strerror} values are created from the
+  \member{winerror} and \member{strerror} values are created from the
   return values of the \cfunction{GetLastError()} and
   \cfunction{FormatMessage()} functions from the Windows Platform API.
+  The \member{errno} value maps the \member{winerror} value to 
+  corresponding \code{errno.h} values.
   This is a subclass of \exception{OSError}.
 \versionadded{2.0}
+\versionchanged[Previous versions put the \cfunction{GetLastError()}
+codes into \member{errno}]{2.5}
 \end{excdesc}
 
 \begin{excdesc}{ZeroDivisionError}
index 2d3553ab4bde93ae713563878dbb1d245074fc95..bb115e180fbd92e42b5e003c6a9e1ceef6abf169 100755 (executable)
@@ -24,12 +24,6 @@ __all__ = [ 'Mailbox', 'Maildir', 'mbox', 'MH', 'Babyl', 'MMDF',
             'BabylMessage', 'MMDFMessage', 'UnixMailbox',
             'PortableUnixMailbox', 'MmdfMailbox', 'MHMailbox', 'BabylMailbox' ]
 
-if sys.platform != 'win32':
-    # Define WindowsError so that we can use it in an except statement
-    # even on non-Windows systems
-    class WindowsError:
-        pass
-
 class Mailbox:
     """A group of messages in a particular place."""
 
@@ -268,9 +262,6 @@ class Maildir(Mailbox):
             self.remove(key)
         except KeyError:
             pass
-        except WindowsError, e:
-            if e.errno != 2: # ERROR_FILE_NOT_FOUND
-                raise
         except OSError, e:
             if e.errno != errno.ENOENT:
                 raise
@@ -426,12 +417,6 @@ class Maildir(Mailbox):
         path = os.path.join(self._path, 'tmp', uniq)
         try:
             os.stat(path)
-        except WindowsError, e:
-            if e.errno == 2: # ERROR_FILE_NOT_FOUND
-                Maildir._count += 1
-                return open(path, 'wb+')
-            else:
-                raise
         except OSError, e:
             if e.errno == errno.ENOENT:
                 Maildir._count += 1
@@ -579,12 +564,6 @@ class _singlefileMailbox(Mailbox):
         self._file.close()
         try:
             os.rename(new_file.name, self._path)
-        except WindowsError, e:
-            if e.errno == 183: # ERROR_ALREADY_EXISTS
-                os.remove(self._path)
-                os.rename(new_file.name, self._path)
-            else:
-                raise
         except OSError, e:
             if e.errno == errno.EEXIST:
                 os.remove(self._path)
@@ -1856,13 +1835,6 @@ def _lock_file(f, dotlock=True):
                 else:
                     os.rename(pre_lock.name, f.name + '.lock')
                     dotlock_done = True
-            except WindowsError, e:
-                if e.errno == 183:  # ERROR_ALREADY_EXISTS
-                    os.remove(pre_lock.name)
-                    raise ExternalClashError('dot lock unavailable: %s' %
-                                             f.name)
-                else:
-                    raise
             except OSError, e:
                 if e.errno == errno.EEXIST:
                     os.remove(pre_lock.name)
index 83dfa171dbf3f36ca1081f9839984de8dea5363f..dd7e8643e694d938e09a7ef628c7459c0a49ddd7 100644 (file)
@@ -327,10 +327,6 @@ def mkdtemp(suffix="", prefix=template, dir=None):
         try:
             _os.mkdir(file, 0700)
             return file
-        except WindowsError, e:
-            if e.errno == 183: # ERROR_ALREADY_EXISTS
-                continue # try again
-            raise
         except OSError, e:
             if e.errno == _errno.EEXIST:
                 continue # try again
index 4e1aa9e351f1fb32cfed439c792519094e7be016..0a769b7944a5a5afd8b31d6149619051a68b425c 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,11 @@ What's New in Python 2.5 alpha 2?
 Core and builtins
 -----------------
 
+- WindowsError now has two error code attributes: errno, which carries
+  the error values from errno.h, and winerror, which carries the error
+  values from winerror.h. Previous versions put the winerror.h values
+  (from GetLastError()) into the errno attribute.
+
 - Patch #1475845: Raise IndentationError for unexpected indent.
 
 - Patch #1479181: split open() and file() from being aliases for each other.
diff --git a/PC/errmap.h b/PC/errmap.h
new file mode 100644 (file)
index 0000000..59aeea1
--- /dev/null
@@ -0,0 +1,78 @@
+/* Generated file. Do not edit. */
+int winerror_to_errno(int winerror)
+{
+       switch(winerror) {
+               case 2: return 2;
+               case 3: return 2;
+               case 4: return 24;
+               case 5: return 13;
+               case 6: return 9;
+               case 7: return 12;
+               case 8: return 12;
+               case 9: return 12;
+               case 10: return 7;
+               case 11: return 8;
+               case 15: return 2;
+               case 16: return 13;
+               case 17: return 18;
+               case 18: return 2;
+               case 19: return 13;
+               case 20: return 13;
+               case 21: return 13;
+               case 22: return 13;
+               case 23: return 13;
+               case 24: return 13;
+               case 25: return 13;
+               case 26: return 13;
+               case 27: return 13;
+               case 28: return 13;
+               case 29: return 13;
+               case 30: return 13;
+               case 31: return 13;
+               case 32: return 13;
+               case 33: return 13;
+               case 34: return 13;
+               case 35: return 13;
+               case 36: return 13;
+               case 53: return 2;
+               case 65: return 13;
+               case 67: return 2;
+               case 80: return 17;
+               case 82: return 13;
+               case 83: return 13;
+               case 89: return 11;
+               case 108: return 13;
+               case 109: return 32;
+               case 112: return 28;
+               case 114: return 9;
+               case 128: return 10;
+               case 129: return 10;
+               case 130: return 9;
+               case 132: return 13;
+               case 145: return 41;
+               case 158: return 13;
+               case 161: return 2;
+               case 164: return 11;
+               case 167: return 13;
+               case 183: return 17;
+               case 188: return 8;
+               case 189: return 8;
+               case 190: return 8;
+               case 191: return 8;
+               case 192: return 8;
+               case 193: return 8;
+               case 194: return 8;
+               case 195: return 8;
+               case 196: return 8;
+               case 197: return 8;
+               case 198: return 8;
+               case 199: return 8;
+               case 200: return 8;
+               case 201: return 8;
+               case 202: return 8;
+               case 206: return 2;
+               case 215: return 11;
+               case 1816: return 12;
+               default: return EINVAL;
+       }
+}
diff --git a/PC/errmap.mak b/PC/errmap.mak
new file mode 100644 (file)
index 0000000..646bcd0
--- /dev/null
@@ -0,0 +1,5 @@
+errmap.h:      generrmap.exe
+       .\generrmap.exe > errmap.h
+
+genermap.exe:  generrmap.c
+       cl generrmap.c
diff --git a/PC/generrmap.c b/PC/generrmap.c
new file mode 100644 (file)
index 0000000..2b25063
--- /dev/null
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <errno.h>
+
+/* Extract the mapping of Win32 error codes to errno */
+
+int main()
+{
+       int i;
+       printf("/* Generated file. Do not edit. */\n");
+       printf("int winerror_to_errno(int winerror)\n");
+       printf("{\n\tswitch(winerror) {\n");
+       for(i=1; i < 65000; i++) {
+               _dosmaperr(i);
+               if (errno == EINVAL)
+                       continue;
+               printf("\t\tcase %d: return %d;\n", i, errno);
+       }
+       printf("\t\tdefault: return EINVAL;\n");
+       printf("\t}\n}\n");
+}
index 31fb53e6b3b942b3e4826b53572fed175aea70ac..3f949edfab05235f9654c8b613eb50f6a1e767b7 100644 (file)
@@ -704,15 +704,132 @@ PyMethodDef EnvironmentError_methods[] = {
     {NULL, NULL}
 };
 
-
-
-\f
 PyDoc_STRVAR(IOError__doc__, "I/O operation failed.");
 
 PyDoc_STRVAR(OSError__doc__, "OS system call failed.");
 
 #ifdef MS_WINDOWS
+#include "errmap.h"
+
 PyDoc_STRVAR(WindowsError__doc__, "MS-Windows OS system call failed.");
+
+static PyObject *
+WindowsError__init__(PyObject *self, PyObject *args)
+{
+       PyObject *o_errcode, *result;
+       long errcode, posix_errno;
+       result = EnvironmentError__init__(self, args);
+       if (!result)
+               return NULL;
+       self = get_self(args);
+       if (!self)
+               goto failed;
+       /* Set errno to the POSIX errno, and winerror to the Win32
+          error code. */
+       o_errcode = PyObject_GetAttrString(self, "errno");
+       if (!o_errcode)
+               goto failed;
+       errcode = PyInt_AsLong(o_errcode);
+       if (!errcode == -1 && PyErr_Occurred())
+               goto failed;
+       posix_errno = winerror_to_errno(errcode);
+       if (PyObject_SetAttrString(self, "winerror", o_errcode) < 0)
+               goto failed;
+       Py_DECREF(o_errcode);
+       o_errcode = PyInt_FromLong(posix_errno);
+       if (!o_errcode)
+               goto failed;
+       if (PyObject_SetAttrString(self, "errno", o_errcode) < 0)
+               goto failed;
+       Py_DECREF(o_errcode);
+       return result;
+failed:
+       /* Could not set errno. */
+       Py_XDECREF(o_errcode);
+       Py_DECREF(self);
+       Py_DECREF(result);
+       return NULL;
+}
+
+static PyObject *
+WindowsError__str__(PyObject *self, PyObject *args)
+{
+    PyObject *originalself = self;
+    PyObject *filename;
+    PyObject *serrno;
+    PyObject *strerror;
+    PyObject *rtnval = NULL;
+
+    if (!PyArg_ParseTuple(args, "O:__str__", &self))
+       return NULL;
+
+    filename = PyObject_GetAttrString(self, "filename");
+    serrno = PyObject_GetAttrString(self, "winerror");
+    strerror = PyObject_GetAttrString(self, "strerror");
+    if (!filename || !serrno || !strerror)
+       goto finally;
+
+    if (filename != Py_None) {
+       PyObject *fmt = PyString_FromString("[Error %s] %s: %s");
+       PyObject *repr = PyObject_Repr(filename);
+       PyObject *tuple = PyTuple_New(3);
+
+       if (!fmt || !repr || !tuple) {
+           Py_XDECREF(fmt);
+           Py_XDECREF(repr);
+           Py_XDECREF(tuple);
+           goto finally;
+       }
+
+       PyTuple_SET_ITEM(tuple, 0, serrno);
+       PyTuple_SET_ITEM(tuple, 1, strerror);
+       PyTuple_SET_ITEM(tuple, 2, repr);
+
+       rtnval = PyString_Format(fmt, tuple);
+
+       Py_DECREF(fmt);
+       Py_DECREF(tuple);
+       /* already freed because tuple owned only reference */
+       serrno = NULL;
+       strerror = NULL;
+    }
+    else if (PyObject_IsTrue(serrno) && PyObject_IsTrue(strerror)) {
+       PyObject *fmt = PyString_FromString("[Error %s] %s");
+       PyObject *tuple = PyTuple_New(2);
+
+       if (!fmt || !tuple) {
+           Py_XDECREF(fmt);
+           Py_XDECREF(tuple);
+           goto finally;
+       }
+
+       PyTuple_SET_ITEM(tuple, 0, serrno);
+       PyTuple_SET_ITEM(tuple, 1, strerror);
+
+       rtnval = PyString_Format(fmt, tuple);
+
+       Py_DECREF(fmt);
+       Py_DECREF(tuple);
+       /* already freed because tuple owned only reference */
+       serrno = NULL;
+       strerror = NULL;
+    }
+    else
+       rtnval = EnvironmentError__str__(originalself, args);
+
+  finally:
+    Py_XDECREF(filename);
+    Py_XDECREF(serrno);
+    Py_XDECREF(strerror);
+    return rtnval;
+}
+
+static
+PyMethodDef WindowsError_methods[] = {
+    {"__init__", WindowsError__init__, METH_VARARGS},
+    {"__str__", WindowsError__str__, METH_VARARGS},
+    {NULL, NULL}
+};
 #endif /* MS_WINDOWS */
 
 #ifdef __VMS
@@ -1760,7 +1877,7 @@ static struct {
  {"OSError", &PyExc_OSError, &PyExc_EnvironmentError, OSError__doc__},
 #ifdef MS_WINDOWS
  {"WindowsError", &PyExc_WindowsError, &PyExc_OSError,
-  WindowsError__doc__},
+WindowsError__doc__, WindowsError_methods},
 #endif /* MS_WINDOWS */
 #ifdef __VMS
  {"VMSError", &PyExc_VMSError, &PyExc_OSError,