now register both filenames in the exception on failure.
This required adding new C API functions allowing OSError exceptions
to reference two filenames instead of one.
exception instance.
+.. c:function:: PyObject* PyErr_SetFromErrnoWithFilenameObjects(PyObject *type, PyObject *filenameObject, PyObject *filenameObject2)
+
+ Similar to :c:func:`PyErr_SetFromErrnoWithFilenameObject`, but takes a second
+ filename object, for raising errors when a function that takes two filenames
+ fails.
+
+.. versionadded:: 3.4
+
+
.. c:function:: PyObject* PyErr_SetFromErrnoWithFilename(PyObject *type, const char *filename)
Similar to :c:func:`PyErr_SetFromErrnoWithFilenameObject`, but the filename
(:func:`os.fsdecode`).
+.. c:function:: PyObject* PyErr_SetFromErrnoWithFilenames(PyObject *type, const char *filename, const char *filename2)
+
+ Similar to :c:func:`PyErr_SetFromErrnoWithFilename`, but accepts a
+ second filename.
+
+.. versionadded:: 3.4
+
+
.. c:function:: PyObject* PyErr_SetFromWindowsErr(int ierr)
This is a convenience function to raise :exc:`WindowsError`. If called with
specifying the exception type to be raised. Availability: Windows.
-.. c:function:: PyObject* PyErr_SetFromWindowsErrWithFilenameObject(int ierr, PyObject *filenameObject)
-
- Similar to :c:func:`PyErr_SetFromWindowsErr`, with the additional behavior
- that if *filenameObject* is not *NULL*, it is passed to the constructor of
- :exc:`WindowsError` as a third parameter. Availability: Windows.
-
-
.. c:function:: PyObject* PyErr_SetFromWindowsErrWithFilename(int ierr, const char *filename)
Similar to :c:func:`PyErr_SetFromWindowsErrWithFilenameObject`, but the
encoding (:func:`os.fsdecode`). Availability: Windows.
+.. c:function:: PyObject* PyErr_SetFromWindowsErrWithFilenames(int ierr, const char *filename, const char *filename2)
+
+ Similar to :c:func:`PyErr_SetFromWindowsErrWithFilename`, but accepts
+ a second filename. Availability: Windows.
+
+.. versionadded:: 3.4
+
+
.. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilenameObject(PyObject *type, int ierr, PyObject *filename)
Similar to :c:func:`PyErr_SetFromWindowsErrWithFilenameObject`, with an
Availability: Windows.
+.. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilenameObjects(PyObject *type, int ierr, PyObject *filename, PyObject *filename2)
+
+ Similar to :c:func:`PyErr_SetExcFromWindowsErrWithFilenameObject`,
+ but accepts a second filename object.
+ Availability: Windows.
+
+.. versionadded:: 3.4
+
+
.. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilename(PyObject *type, int ierr, const char *filename)
Similar to :c:func:`PyErr_SetFromWindowsErrWithFilename`, with an additional
parameter specifying the exception type to be raised. Availability: Windows.
+.. c:function:: PyObject* PyErr_SetExcFromWindowsErrWithFilenames(PyObject *type, int ierr, const char *filename, const char *filename2)
+
+ Similar to :c:func:`PyErr_SetExcFromWindowsErrWithFilename`,
+ but accepts a second filename object.
+ Availability: Windows.
+
+.. versionadded:: 3.4
+
+
.. c:function:: PyObject* PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path)
This is a convenience function to raise :exc:`ImportError`. *msg* will be
# reference to the item argument!
# The parameter names are as they appear in the API manual, not the source
-# code.
+# code.
PyBool_FromLong:PyObject*::+1:
PyBool_FromLong:long:v:0:
PyErr_SetExcFromWindowsErrWithFilename:int:ierr::
PyErr_SetExcFromWindowsErrWithFilename:const char*:filename::
+PyErr_SetExcFromWindowsErrWithFilenames:PyObject*::null:
+PyErr_SetExcFromWindowsErrWithFilenames:PyObject*:type:0:
+PyErr_SetExcFromWindowsErrWithFilenames:int:ierr::
+PyErr_SetExcFromWindowsErrWithFilenames:const char*:filename::
+PyErr_SetExcFromWindowsErrWithFilenames:const char*:filename2::
+
PyErr_SetFromErrno:PyObject*::null:
PyErr_SetFromErrno:PyObject*:type:0:
PyErr_SetFromErrnoWithFilename:PyObject*:type:0:
PyErr_SetFromErrnoWithFilename:const char*:filename::
+PyErr_SetFromErrnoWithFilenames:PyObject*::null:
+PyErr_SetFromErrnoWithFilenames:PyObject*:type:0:
+PyErr_SetFromErrnoWithFilenames:const char*:filename::
+PyErr_SetFromErrnoWithFilenames:const char*:filename2::
+
PyErr_SetFromWindowsErr:PyObject*::null:
PyErr_SetFromWindowsErr:int:ierr::
PyErr_SetFromWindowsErrWithFilename:int:ierr::
PyErr_SetFromWindowsErrWithFilename:const char*:filename::
+PyErr_SetFromWindowsErrWithFilenames:PyObject*::null:
+PyErr_SetFromWindowsErrWithFilenames:int:ierr::
+PyErr_SetFromWindowsErrWithFilenames:const char*:filename::
+PyErr_SetFromWindowsErrWithFilenames:const char*:filename2::
+
PyErr_SetInterrupt:void:::
PyErr_SetNone:void:::
PyNumber_Xor:PyObject*:o1:0:
PyNumber_Xor:PyObject*:o2:0:
-PyObject_AsFileDescriptor:int:::
+PyObject_AsFileDescriptor:int:::
PyObject_AsFileDescriptor:PyObject*:o:0:
PyObject_Call:PyObject*::+1:
For exceptions that involve a file system path (such as :func:`open` or
:func:`os.unlink`), the exception instance will contain an additional
attribute, :attr:`filename`, which is the file name passed to the function.
+ For functions that involve two file system paths (such as
+ :func:`os.rename`), the exception instance will contain a second
+ :attr:`filename2` attribute corresponding to the second file name passed
+ to the function.
+
.. versionchanged:: 3.3
:exc:`EnvironmentError`, :exc:`IOError`, :exc:`WindowsError`,
The :attr:`filename` attribute is now the original file name passed to
the function, instead of the name encoded to or decoded from the
- filesystem encoding.
+ filesystem encoding. Also, the :attr:`filename2` attribute was added.
.. exception:: OverflowError
PyObject *myerrno;
PyObject *strerror;
PyObject *filename;
+ PyObject *filename2;
#ifdef MS_WINDOWS
PyObject *winerror;
#endif
PyAPI_FUNC(PyObject *) PyErr_SetFromErrno(PyObject *);
PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenameObject(
PyObject *, PyObject *);
+PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenameObjects(
+ PyObject *, PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilename(
PyObject *exc,
const char *filename /* decoded from the filesystem encoding */
);
+PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithFilenames(
+ PyObject *exc,
+ /* decoded from the filesystem encoding */
+ const char *filename,
+ const char *filename2
+ );
#if defined(MS_WINDOWS) && !defined(Py_LIMITED_API)
PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithUnicodeFilename(
PyObject *, const Py_UNICODE *);
+PyAPI_FUNC(PyObject *) PyErr_SetFromErrnoWithUnicodeFilenames(
+ PyObject *, const Py_UNICODE *, const Py_UNICODE *);
#endif /* MS_WINDOWS */
PyAPI_FUNC(PyObject *) PyErr_Format(
int ierr,
const char *filename /* decoded from the filesystem encoding */
);
+PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithFilenames(
+ int ierr,
+ /* decoded from the filesystem encoding */
+ const char *filename,
+ const char *filename2
+ );
#ifndef Py_LIMITED_API
/* XXX redeclare to use WSTRING */
PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithUnicodeFilename(
int, const Py_UNICODE *);
+PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErrWithUnicodeFilenames(
+ int, const Py_UNICODE *, const Py_UNICODE *);
#endif
PyAPI_FUNC(PyObject *) PyErr_SetFromWindowsErr(int);
PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenameObject(
PyObject *,int, PyObject *);
+PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenameObjects(
+ PyObject *,int, PyObject *, PyObject *);
PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilename(
PyObject *exc,
int ierr,
const char *filename /* decoded from the filesystem encoding */
);
+PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithFilenames(
+ PyObject *exc,
+ int ierr,
+ /* decoded from the filesystem encoding */
+ const char *filename,
+ const char *filename2
+ );
#ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithUnicodeFilename(
PyObject *,int, const Py_UNICODE *);
+PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErrWithUnicodeFilenames(
+ PyObject *,int, const Py_UNICODE *, const Py_UNICODE *);
#endif
PyAPI_FUNC(PyObject *) PyErr_SetExcFromWindowsErr(PyObject *, int);
#endif /* MS_WINDOWS */
(OSError, ('foo', 'bar', 'baz'),
{'args' : ('foo', 'bar'), 'filename' : 'baz',
'errno' : 'foo', 'strerror' : 'bar'}),
- (OSError, ('foo', 'bar', 'baz', 'quux'),
- {'args' : ('foo', 'bar', 'baz', 'quux')}),
+ (OSError, ('foo', 'bar', 'baz', None, 'quux'),
+ {'args' : ('foo', 'bar'), 'filename' : 'baz', 'filename2': 'quux'}),
(OSError, ('errnoStr', 'strErrorStr', 'filenameStr'),
{'args' : ('errnoStr', 'strErrorStr'),
'strerror' : 'strErrorStr', 'errno' : 'errnoStr',
# http://lists.freebsd.org/pipermail/freebsd-amd64/2012-January/014332.html
raise unittest.SkipTest("OSError raised!")
+ def test_path_error2(self):
+ """
+ Test functions that call path_error2(), providing two filenames in their exceptions.
+ """
+ for name in ("rename", "replace", "link", "symlink"):
+ function = getattr(os, name, None)
+
+ if function:
+ for dst in ("noodly2", support.TESTFN):
+ try:
+ function('doesnotexistfilename', dst)
+ except OSError as e:
+ self.assertIn("'doesnotexistfilename' -> '{}'".format(dst), str(e))
+ break
+ else:
+ self.fail("No valid path_error2() test for os." + name)
+
class PosixGroupsTester(unittest.TestCase):
def setUp(self):
Library
-------
+- Issue #20517: Functions in the os module that accept two filenames
+ now register both filenames in the exception on failure.
+
- Issue #20563: The ipaddress module API is now considered stable.
- Issue #14983: email.generator now always adds a line end after each MIME
- Issue #20465: Update SQLite shipped with OS X installer to 3.8.3.
+C-API
+-----
+
+- Issue #20517: Added new functions allowing OSError exceptions to reference
+ two filenames instead of one: PyErr_SetFromErrnoWithFilenameObjects(),
+ PyErr_SetFromErrnoWithFilenames(), PyErr_SetFromWindowsErrWithFilenames(),
+ PyErr_SetExcFromWindowsErrWithFilenameObjects(), and
+ PyErr_SetExcFromWindowsErrWithFilenames().
+
Documentation
-------------
}
+static PyObject *
+path_error2(path_t *path, path_t *path2)
+{
+#ifdef MS_WINDOWS
+ return PyErr_SetExcFromWindowsErrWithFilenameObjects(PyExc_OSError,
+ 0, path->object, path2->object);
+#else
+ return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError,
+ path->object, path2->object);
+#endif
+}
+
+
/* POSIX generic methods */
static PyObject *
Py_END_ALLOW_THREADS
if (!result) {
- return_value = path_error(&src);
+ return_value = path_error2(&src, &dst);
goto exit;
}
#else
Py_END_ALLOW_THREADS
if (result) {
- return_value = path_error(&src);
+ return_value = path_error2(&src, &dst);
goto exit;
}
#endif
Py_END_ALLOW_THREADS
if (!result) {
- return_value = path_error(&src);
+ return_value = path_error2(&src, &dst);
goto exit;
}
Py_END_ALLOW_THREADS
if (result) {
- return_value = path_error(&src);
+ return_value = path_error2(&src, &dst);
goto exit;
}
#endif
Py_END_ALLOW_THREADS
if (!result) {
- return_value = path_error(&src);
+ return_value = path_error2(&src, &dst);
goto exit;
}
Py_END_ALLOW_THREADS
if (result) {
- return_value = path_error(&src);
+ return_value = path_error2(&src, &dst);
goto exit;
}
#endif
* 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.
+ *
+ * (If a function has two filenames, such as rename(), symlink(),
+ * or copy(), PyErr_SetFromErrnoWithFilenames() is called, which
+ * allows passing in a second filename.)
*/
/* This function doesn't cleanup on error, the caller should */
static int
oserror_parse_args(PyObject **p_args,
PyObject **myerrno, PyObject **strerror,
- PyObject **filename
+ PyObject **filename, PyObject **filename2
#ifdef MS_WINDOWS
, PyObject **winerror
#endif
{
Py_ssize_t nargs;
PyObject *args = *p_args;
+#ifndef MS_WINDOWS
+ /*
+ * ignored on non-Windows platforms,
+ * but parsed so OSError has a consistent signature
+ */
+ PyObject *_winerror = NULL;
+ PyObject **winerror = &_winerror;
+#endif /* MS_WINDOWS */
nargs = PyTuple_GET_SIZE(args);
-#ifdef MS_WINDOWS
- if (nargs >= 2 && nargs <= 4) {
- if (!PyArg_UnpackTuple(args, "OSError", 2, 4,
- myerrno, strerror, filename, winerror))
+ if (nargs >= 2 && nargs <= 5) {
+ if (!PyArg_UnpackTuple(args, "OSError", 2, 5,
+ myerrno, strerror,
+ filename, winerror, filename2))
return -1;
+#ifdef MS_WINDOWS
if (*winerror && PyLong_Check(*winerror)) {
long errcode, winerrcode;
PyObject *newargs;
Py_DECREF(args);
args = *p_args = newargs;
}
+#endif /* MS_WINDOWS */
}
-#else
- if (nargs >= 2 && nargs <= 3) {
- if (!PyArg_UnpackTuple(args, "OSError", 2, 3,
- myerrno, strerror, filename))
- return -1;
- }
-#endif
return 0;
}
static int
oserror_init(PyOSErrorObject *self, PyObject **p_args,
PyObject *myerrno, PyObject *strerror,
- PyObject *filename
+ PyObject *filename, PyObject *filename2
#ifdef MS_WINDOWS
, PyObject *winerror
#endif
Py_INCREF(filename);
self->filename = filename;
- if (nargs >= 2 && nargs <= 3) {
- /* filename is removed from the args tuple (for compatibility
- purposes, see test_exceptions.py) */
+ if (filename2 && filename2 != Py_None) {
+ Py_INCREF(filename2);
+ self->filename2 = filename2;
+ }
+
+ if (nargs >= 2 && nargs <= 5) {
+ /* filename, filename2, and winerror are removed from the args tuple
+ (for compatibility purposes, see test_exceptions.py) */
PyObject *subslice = PyTuple_GetSlice(args, 0, 2);
if (!subslice)
return -1;
OSError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyOSErrorObject *self = NULL;
- PyObject *myerrno = NULL, *strerror = NULL, *filename = NULL;
+ PyObject *myerrno = NULL, *strerror = NULL;
+ PyObject *filename = NULL, *filename2 = NULL;
#ifdef MS_WINDOWS
PyObject *winerror = NULL;
#endif
if (!_PyArg_NoKeywords(type->tp_name, kwds))
goto error;
- if (oserror_parse_args(&args, &myerrno, &strerror, &filename
+ if (oserror_parse_args(&args, &myerrno, &strerror,
+ &filename, &filename2
#ifdef MS_WINDOWS
, &winerror
#endif
self->written = -1;
if (!oserror_use_init(type)) {
- if (oserror_init(self, &args, myerrno, strerror, filename
+ if (oserror_init(self, &args, myerrno, strerror, filename, filename2
#ifdef MS_WINDOWS
, winerror
#endif
static int
OSError_init(PyOSErrorObject *self, PyObject *args, PyObject *kwds)
{
- PyObject *myerrno = NULL, *strerror = NULL, *filename = NULL;
+ PyObject *myerrno = NULL, *strerror = NULL;
+ PyObject *filename = NULL, *filename2 = NULL;
#ifdef MS_WINDOWS
PyObject *winerror = NULL;
#endif
return -1;
Py_INCREF(args);
- if (oserror_parse_args(&args, &myerrno, &strerror, &filename
+ if (oserror_parse_args(&args, &myerrno, &strerror, &filename, &filename2
#ifdef MS_WINDOWS
, &winerror
#endif
))
goto error;
- if (oserror_init(self, &args, myerrno, strerror, filename
+ if (oserror_init(self, &args, myerrno, strerror, filename, filename2
#ifdef MS_WINDOWS
, winerror
#endif
Py_CLEAR(self->myerrno);
Py_CLEAR(self->strerror);
Py_CLEAR(self->filename);
+ Py_CLEAR(self->filename2);
#ifdef MS_WINDOWS
Py_CLEAR(self->winerror);
#endif
Py_VISIT(self->myerrno);
Py_VISIT(self->strerror);
Py_VISIT(self->filename);
+ Py_VISIT(self->filename2);
#ifdef MS_WINDOWS
Py_VISIT(self->winerror);
#endif
static PyObject *
OSError_str(PyOSErrorObject *self)
{
+#define OR_NONE(x) ((x)?(x):Py_None)
#ifdef MS_WINDOWS
/* If available, winerror has the priority over myerrno */
- if (self->winerror && self->filename)
- return PyUnicode_FromFormat("[WinError %S] %S: %R",
- self->winerror ? self->winerror: Py_None,
- self->strerror ? self->strerror: Py_None,
- self->filename);
+ if (self->winerror && self->filename) {
+ if (self->filename2) {
+ return PyUnicode_FromFormat("[WinError %S] %S: %R -> %R",
+ OR_NONE(self->winerror),
+ OR_NONE(self->strerror),
+ self->filename,
+ self->filename2);
+ } else {
+ return PyUnicode_FromFormat("[WinError %S] %S: %R",
+ OR_NONE(self->winerror),
+ OR_NONE(self->strerror),
+ self->filename);
+ }
+ }
if (self->winerror && self->strerror)
return PyUnicode_FromFormat("[WinError %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);
+ if (self->filename) {
+ if (self->filename2) {
+ return PyUnicode_FromFormat("[Errno %S] %S: %R -> %R",
+ OR_NONE(self->myerrno),
+ OR_NONE(self->strerror),
+ self->filename,
+ self->filename2);
+ } else {
+ return PyUnicode_FromFormat("[Errno %S] %S: %R",
+ OR_NONE(self->myerrno),
+ OR_NONE(self->strerror),
+ self->filename);
+ }
+ }
if (self->myerrno && self->strerror)
return PyUnicode_FromFormat("[Errno %S] %S",
self->myerrno ? self->myerrno: Py_None,
/* self->args is only the first two real arguments if there was a
* file name given to OSError. */
if (PyTuple_GET_SIZE(args) == 2 && self->filename) {
- args = PyTuple_New(3);
+ Py_ssize_t size = self->filename2 ? 5 : 3;
+ args = PyTuple_New(size);
if (!args)
return NULL;
Py_INCREF(self->filename);
PyTuple_SET_ITEM(args, 2, self->filename);
+
+ if (self->filename2) {
+ /*
+ * This tuple is essentially used as OSError(*args).
+ * So, to recreate filename2, we need to pass in
+ * winerror as well.
+ */
+ Py_INCREF(Py_None);
+ PyTuple_SET_ITEM(args, 3, Py_None);
+
+ /* filename2 */
+ Py_INCREF(self->filename2);
+ PyTuple_SET_ITEM(args, 4, self->filename2);
+ }
} else
Py_INCREF(args);
PyDoc_STR("exception strerror")},
{"filename", T_OBJECT, offsetof(PyOSErrorObject, filename), 0,
PyDoc_STR("exception filename")},
+ {"filename2", T_OBJECT, offsetof(PyOSErrorObject, filename2), 0,
+ PyDoc_STR("second exception filename")},
#ifdef MS_WINDOWS
{"winerror", T_OBJECT, offsetof(PyOSErrorObject, winerror), 0,
PyDoc_STR("Win32 exception code")},
PyObject *
PyErr_SetFromErrnoWithFilenameObject(PyObject *exc, PyObject *filenameObject)
+{
+ return PyErr_SetFromErrnoWithFilenameObjects(exc, filenameObject, NULL);
+}
+
+PyObject *
+PyErr_SetFromErrnoWithFilenameObjects(PyObject *exc, PyObject *filenameObject, PyObject *filenameObject2)
{
PyObject *message;
PyObject *v, *args;
return NULL;
}
- if (filenameObject != NULL)
- args = Py_BuildValue("(iOO)", i, message, filenameObject);
- else
+ if (filenameObject != NULL) {
+ if (filenameObject2 != NULL)
+ args = Py_BuildValue("(iOOiO)", i, message, filenameObject, 0, filenameObject2);
+ else
+ args = Py_BuildValue("(iOO)", i, message, filenameObject);
+ } else {
+ assert(filenameObject2 == NULL);
args = Py_BuildValue("(iO)", i, message);
+ }
Py_DECREF(message);
if (args != NULL) {
return NULL;
}
-
PyObject *
PyErr_SetFromErrnoWithFilename(PyObject *exc, const char *filename)
{
PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL;
- PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
+ PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, NULL);
Py_XDECREF(name);
return result;
}
+PyObject *
+PyErr_SetFromErrnoWithFilenames(PyObject *exc, const char *filename, const char *filename2)
+{
+ PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL;
+ PyObject *name2 = filename2 ? PyUnicode_DecodeFSDefault(filename2) : NULL;
+ PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, name2);
+ Py_XDECREF(name);
+ Py_XDECREF(name2);
+ return result;
+}
+
#ifdef MS_WINDOWS
PyObject *
PyErr_SetFromErrnoWithUnicodeFilename(PyObject *exc, const Py_UNICODE *filename)
PyObject *name = filename ?
PyUnicode_FromUnicode(filename, wcslen(filename)) :
NULL;
- PyObject *result = PyErr_SetFromErrnoWithFilenameObject(exc, name);
+ PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, NULL);
Py_XDECREF(name);
return result;
}
+
+PyObject *
+PyErr_SetFromErrnoWithUnicodeFilenames(PyObject *exc, const Py_UNICODE *filename, const Py_UNICODE *filename2)
+{
+ PyObject *name = filename ?
+ PyUnicode_FromUnicode(filename, wcslen(filename)) :
+ NULL;
+ PyObject *name2 = filename2 ?
+ PyUnicode_FromUnicode(filename2, wcslen(filename2)) :
+ NULL;
+ PyObject *result = PyErr_SetFromErrnoWithFilenameObjects(exc, name, name2);
+ Py_XDECREF(name);
+ Py_XDECREF(name2);
+ return result;
+}
#endif /* MS_WINDOWS */
PyObject *
PyErr_SetFromErrno(PyObject *exc)
{
- return PyErr_SetFromErrnoWithFilenameObject(exc, NULL);
+ return PyErr_SetFromErrnoWithFilenameObjects(exc, NULL, NULL);
}
#ifdef MS_WINDOWS
PyObject *exc,
int ierr,
PyObject *filenameObject)
+{
+ return PyErr_SetExcFromWindowsErrWithFilenameObjects(exc, ierr,
+ filenameObject, NULL);
+}
+
+PyObject *PyErr_SetExcFromWindowsErrWithFilenameObjects(
+ PyObject *exc,
+ int ierr,
+ PyObject *filenameObject,
+ PyObject *filenameObject2)
{
int len;
WCHAR *s_buf = NULL; /* Free via LocalFree */
return NULL;
}
- if (filenameObject == NULL)
- filenameObject = Py_None;
- /* This is the constructor signature for passing a Windows error code.
+ if (filenameObject == NULL) {
+ assert(filenameObject2 == NULL);
+ filenameObject = filenameObject2 = Py_None;
+ }
+ else if (filenameObject2 == NULL)
+ filenameObject2 = Py_None;
+ /* This is the constructor signature for OSError.
The POSIX translation will be figured out by the constructor. */
- args = Py_BuildValue("(iOOi)", 0, message, filenameObject, err);
+ args = Py_BuildValue("(iOOiO)", 0, message, filenameObject, err, filenameObject2);
Py_DECREF(message);
if (args != NULL) {
const char *filename)
{
PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL;
- PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
+ PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc,
ierr,
- name);
+ name,
+ NULL);
Py_XDECREF(name);
return ret;
}
+PyObject *PyErr_SetExcFromWindowsErrWithFilenames(
+ PyObject *exc,
+ int ierr,
+ const char *filename,
+ const char *filename2)
+{
+ PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL;
+ PyObject *name2 = filename2 ? PyUnicode_DecodeFSDefault(filename2) : NULL;
+ PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc,
+ ierr,
+ name,
+ name2);
+ Py_XDECREF(name);
+ Py_XDECREF(name2);
+ return ret;
+}
+
PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilename(
PyObject *exc,
int ierr,
PyObject *name = filename ?
PyUnicode_FromUnicode(filename, wcslen(filename)) :
NULL;
- PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObject(exc,
+ PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc,
+ ierr,
+ name,
+ NULL);
+ Py_XDECREF(name);
+ return ret;
+}
+
+PyObject *PyErr_SetExcFromWindowsErrWithUnicodeFilenames(
+ PyObject *exc,
+ int ierr,
+ const Py_UNICODE *filename,
+ const Py_UNICODE *filename2)
+{
+ PyObject *name = filename ?
+ PyUnicode_FromUnicode(filename, wcslen(filename)) :
+ NULL;
+ PyObject *name2 = filename2 ?
+ PyUnicode_FromUnicode(filename2, wcslen(filename2)) :
+ NULL;
+ PyObject *ret = PyErr_SetExcFromWindowsErrWithFilenameObjects(exc,
ierr,
- name);
+ name,
+ name2);
Py_XDECREF(name);
+ Py_XDECREF(name2);
return ret;
}
PyObject *PyErr_SetExcFromWindowsErr(PyObject *exc, int ierr)
{
- return PyErr_SetExcFromWindowsErrWithFilename(exc, ierr, NULL);
+ return PyErr_SetExcFromWindowsErrWithFilenames(exc, ierr, NULL, NULL);
}
PyObject *PyErr_SetFromWindowsErr(int ierr)
{
- return PyErr_SetExcFromWindowsErrWithFilename(PyExc_OSError,
- ierr, NULL);
+ return PyErr_SetExcFromWindowsErrWithFilenames(PyExc_OSError,
+ ierr, NULL, NULL);
+}
+
+PyObject *PyErr_SetFromWindowsErrWithFilenames(
+ int ierr,
+ const char *filename,
+ const char *filename2)
+{
+ PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL;
+ PyObject *name2 = filename2 ? PyUnicode_DecodeFSDefault(filename2) : NULL;
+ PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects(
+ PyExc_OSError,
+ ierr, name, name2);
+ Py_XDECREF(name);
+ Py_XDECREF(name2);
+ return result;
}
+
PyObject *PyErr_SetFromWindowsErrWithFilename(
int ierr,
const char *filename)
{
PyObject *name = filename ? PyUnicode_DecodeFSDefault(filename) : NULL;
- PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(
+ PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects(
PyExc_OSError,
- ierr, name);
+ ierr, name, NULL);
Py_XDECREF(name);
return result;
}
PyObject *name = filename ?
PyUnicode_FromUnicode(filename, wcslen(filename)) :
NULL;
- PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObject(
+ PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects(
+ PyExc_OSError,
+ ierr, name, NULL);
+ Py_XDECREF(name);
+ return result;
+}
+
+PyObject *PyErr_SetFromWindowsErrWithUnicodeFilenames(
+ int ierr,
+ const Py_UNICODE *filename,
+ const Py_UNICODE *filename2)
+{
+ PyObject *name = filename ?
+ PyUnicode_FromUnicode(filename, wcslen(filename)) :
+ NULL;
+ PyObject *name2 = filename2 ?
+ PyUnicode_FromUnicode(filename2, wcslen(filename2)) :
+ NULL;
+ PyObject *result = PyErr_SetExcFromWindowsErrWithFilenameObjects(
PyExc_OSError,
- ierr, name);
+ ierr, name, name2);
Py_XDECREF(name);
+ Py_XDECREF(name2);
return result;
}
#endif /* MS_WINDOWS */