From 879768dd97f98626c919a460a90dd0d54855de9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Thu, 11 May 2006 13:28:43 +0000 Subject: Change WindowsError to carry the Win32 error code in winerror, and the DOS error code in errno. Revert changes where WindowsError catch blocks unnecessarily special-case OSError. --- Doc/lib/libexcs.tex | 6 ++- Lib/mailbox.py | 28 ------------ Lib/tempfile.py | 4 -- Misc/NEWS | 5 +++ PC/errmap.h | 78 ++++++++++++++++++++++++++++++++ PC/errmap.mak | 5 +++ PC/generrmap.c | 20 +++++++++ Python/exceptions.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 8 files changed, 234 insertions(+), 37 deletions(-) create mode 100644 PC/errmap.h create mode 100644 PC/errmap.mak create mode 100644 PC/generrmap.c diff --git a/Doc/lib/libexcs.tex b/Doc/lib/libexcs.tex index f52ff0a..b51b7fc 100644 --- a/Doc/lib/libexcs.tex +++ b/Doc/lib/libexcs.tex @@ -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} diff --git a/Lib/mailbox.py b/Lib/mailbox.py index 2d3553a..bb115e1 100755 --- a/Lib/mailbox.py +++ b/Lib/mailbox.py @@ -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) diff --git a/Lib/tempfile.py b/Lib/tempfile.py index 83dfa17..dd7e864 100644 --- a/Lib/tempfile.py +++ b/Lib/tempfile.py @@ -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 diff --git a/Misc/NEWS b/Misc/NEWS index 4e1aa9e..0a769b7 100644 --- 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 index 0000000..59aeea1 --- /dev/null +++ b/PC/errmap.h @@ -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 index 0000000..646bcd0 --- /dev/null +++ b/PC/errmap.mak @@ -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 index 0000000..2b25063 --- /dev/null +++ b/PC/generrmap.c @@ -0,0 +1,20 @@ +#include +#include + +/* 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"); +} diff --git a/Python/exceptions.c b/Python/exceptions.c index 31fb53e..3f949ed 100644 --- a/Python/exceptions.c +++ b/Python/exceptions.c @@ -704,15 +704,132 @@ PyMethodDef EnvironmentError_methods[] = { {NULL, NULL} }; - - - 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, -- cgit v0.12