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.
This commit is contained in:
Martin v. Löwis 2006-05-11 13:28:43 +00:00
parent 38e3b7d2d3
commit 879768dd97
8 changed files with 234 additions and 37 deletions

View file

@ -399,11 +399,15 @@ Raised when an \keyword{assert} statement fails.
\begin{excdesc}{WindowsError} \begin{excdesc}{WindowsError}
Raised when a Windows-specific error occurs or when the error number Raised when a Windows-specific error occurs or when the error number
does not correspond to an \cdata{errno} value. The 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 return values of the \cfunction{GetLastError()} and
\cfunction{FormatMessage()} functions from the Windows Platform API. \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}. This is a subclass of \exception{OSError}.
\versionadded{2.0} \versionadded{2.0}
\versionchanged[Previous versions put the \cfunction{GetLastError()}
codes into \member{errno}]{2.5}
\end{excdesc} \end{excdesc}
\begin{excdesc}{ZeroDivisionError} \begin{excdesc}{ZeroDivisionError}

View file

@ -24,12 +24,6 @@ __all__ = [ 'Mailbox', 'Maildir', 'mbox', 'MH', 'Babyl', 'MMDF',
'BabylMessage', 'MMDFMessage', 'UnixMailbox', 'BabylMessage', 'MMDFMessage', 'UnixMailbox',
'PortableUnixMailbox', 'MmdfMailbox', 'MHMailbox', 'BabylMailbox' ] '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: class Mailbox:
"""A group of messages in a particular place.""" """A group of messages in a particular place."""
@ -268,9 +262,6 @@ class Maildir(Mailbox):
self.remove(key) self.remove(key)
except KeyError: except KeyError:
pass pass
except WindowsError, e:
if e.errno != 2: # ERROR_FILE_NOT_FOUND
raise
except OSError, e: except OSError, e:
if e.errno != errno.ENOENT: if e.errno != errno.ENOENT:
raise raise
@ -426,12 +417,6 @@ class Maildir(Mailbox):
path = os.path.join(self._path, 'tmp', uniq) path = os.path.join(self._path, 'tmp', uniq)
try: try:
os.stat(path) 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: except OSError, e:
if e.errno == errno.ENOENT: if e.errno == errno.ENOENT:
Maildir._count += 1 Maildir._count += 1
@ -579,12 +564,6 @@ class _singlefileMailbox(Mailbox):
self._file.close() self._file.close()
try: try:
os.rename(new_file.name, self._path) 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: except OSError, e:
if e.errno == errno.EEXIST: if e.errno == errno.EEXIST:
os.remove(self._path) os.remove(self._path)
@ -1856,13 +1835,6 @@ def _lock_file(f, dotlock=True):
else: else:
os.rename(pre_lock.name, f.name + '.lock') os.rename(pre_lock.name, f.name + '.lock')
dotlock_done = True 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: except OSError, e:
if e.errno == errno.EEXIST: if e.errno == errno.EEXIST:
os.remove(pre_lock.name) os.remove(pre_lock.name)

View file

@ -327,10 +327,6 @@ def mkdtemp(suffix="", prefix=template, dir=None):
try: try:
_os.mkdir(file, 0700) _os.mkdir(file, 0700)
return file return file
except WindowsError, e:
if e.errno == 183: # ERROR_ALREADY_EXISTS
continue # try again
raise
except OSError, e: except OSError, e:
if e.errno == _errno.EEXIST: if e.errno == _errno.EEXIST:
continue # try again continue # try again

View file

@ -12,6 +12,11 @@ What's New in Python 2.5 alpha 2?
Core and builtins 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 #1475845: Raise IndentationError for unexpected indent.
- Patch #1479181: split open() and file() from being aliases for each other. - Patch #1479181: split open() and file() from being aliases for each other.

78
PC/errmap.h Normal file
View file

@ -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;
}
}

5
PC/errmap.mak Normal file
View file

@ -0,0 +1,5 @@
errmap.h: generrmap.exe
.\generrmap.exe > errmap.h
genermap.exe: generrmap.c
cl generrmap.c

20
PC/generrmap.c Normal file
View file

@ -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");
}

View file

@ -704,15 +704,132 @@ PyMethodDef EnvironmentError_methods[] = {
{NULL, NULL} {NULL, NULL}
}; };
PyDoc_STRVAR(IOError__doc__, "I/O operation failed."); PyDoc_STRVAR(IOError__doc__, "I/O operation failed.");
PyDoc_STRVAR(OSError__doc__, "OS system call failed."); PyDoc_STRVAR(OSError__doc__, "OS system call failed.");
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
#include "errmap.h"
PyDoc_STRVAR(WindowsError__doc__, "MS-Windows OS system call failed."); 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 */ #endif /* MS_WINDOWS */
#ifdef __VMS #ifdef __VMS
@ -1760,7 +1877,7 @@ static struct {
{"OSError", &PyExc_OSError, &PyExc_EnvironmentError, OSError__doc__}, {"OSError", &PyExc_OSError, &PyExc_EnvironmentError, OSError__doc__},
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
{"WindowsError", &PyExc_WindowsError, &PyExc_OSError, {"WindowsError", &PyExc_WindowsError, &PyExc_OSError,
WindowsError__doc__}, WindowsError__doc__, WindowsError_methods},
#endif /* MS_WINDOWS */ #endif /* MS_WINDOWS */
#ifdef __VMS #ifdef __VMS
{"VMSError", &PyExc_VMSError, &PyExc_OSError, {"VMSError", &PyExc_VMSError, &PyExc_OSError,