From afe170645753d73b9ce49c7791fbeab15f6d0fc7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 31 Oct 2012 22:47:43 +0100 Subject: Issue #15478: Use source filename in OSError, not destination filename And other fixes for Windows: * rename, replace and link require arguments of the same type on Windows * readlink only supports unicode filenames on Windows * os.open() specifies the filename on OSError --- Lib/test/test_os.py | 86 ++++++++++++++++++++++++++++++--------------------- Modules/posixmodule.c | 14 ++------- 2 files changed, 53 insertions(+), 47 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 42a1d00..9cf4070 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2051,68 +2051,82 @@ class OSErrorTests(unittest.TestCase): class Str(str): pass - self.filenames = [] + self.bytes_filenames = [] + self.unicode_filenames = [] if support.TESTFN_UNENCODABLE is not None: decoded = support.TESTFN_UNENCODABLE else: decoded = support.TESTFN - self.filenames.append(decoded) - self.filenames.append(Str(decoded)) + self.unicode_filenames.append(decoded) + self.unicode_filenames.append(Str(decoded)) if support.TESTFN_UNDECODABLE is not None: encoded = support.TESTFN_UNDECODABLE else: encoded = os.fsencode(support.TESTFN) - self.filenames.append(encoded) - self.filenames.append(memoryview(encoded)) + self.bytes_filenames.append(encoded) + self.bytes_filenames.append(memoryview(encoded)) + + self.filenames = self.bytes_filenames + self.unicode_filenames def test_oserror_filename(self): funcs = [ - (os.chdir,), - (os.chmod, 0o777), - (os.listdir,), - (os.lstat,), - (os.open, os.O_RDONLY), - (os.rename, "dst"), - (os.replace, "dst"), - (os.rmdir,), - (os.stat,), - (os.unlink,), + (self.filenames, os.chdir,), + (self.filenames, os.chmod, 0o777), + (self.filenames, os.listdir,), + (self.filenames, os.lstat,), + (self.filenames, os.open, os.O_RDONLY), + (self.filenames, os.rmdir,), + (self.filenames, os.stat,), + (self.filenames, os.unlink,), ] - if hasattr(os, "chown"): - funcs.append((os.chown, 0, 0)) - if hasattr(os, "lchown"): - funcs.append((os.lchown, 0, 0)) - if hasattr(os, "truncate"): - funcs.append((os.truncate, 0)) if sys.platform == "win32": - import nt funcs.extend(( - (nt._getfullpathname,), - (nt._isdir,), + (self.bytes_filenames, os.rename, b"dst"), + (self.bytes_filenames, os.replace, b"dst"), + (self.unicode_filenames, os.rename, "dst"), + (self.unicode_filenames, os.replace, "dst"), + )) + else: + funcs.extend(( + (self.filenames, os.rename, "dst"), + (self.filenames, os.replace, "dst"), )) + if hasattr(os, "chown"): + funcs.append((self.filenames, os.chown, 0, 0)) + if hasattr(os, "lchown"): + funcs.append((self.filenames, os.lchown, 0, 0)) + if hasattr(os, "truncate"): + funcs.append((self.filenames, os.truncate, 0)) if hasattr(os, "chflags"): funcs.extend(( - (os.chflags, 0), - (os.lchflags, 0), + (self.filenames, os.chflags, 0), + (self.filenames, os.lchflags, 0), )) if hasattr(os, "chroot"): - funcs.append((os.chroot,)) + funcs.append((self.filenames, os.chroot,)) if hasattr(os, "link"): - funcs.append((os.link, "dst")) + if sys.platform == "win32": + funcs.append((self.bytes_filenames, os.link, b"dst")) + funcs.append((self.unicode_filenames, os.link, "dst")) + else: + funcs.append((self.filenames, os.link, "dst")) if hasattr(os, "listxattr"): funcs.extend(( - (os.listxattr,), - (os.getxattr, "user.test"), - (os.setxattr, "user.test", b'user'), - (os.removexattr, "user.test"), + (self.filenames, os.listxattr,), + (self.filenames, os.getxattr, "user.test"), + (self.filenames, os.setxattr, "user.test", b'user'), + (self.filenames, os.removexattr, "user.test"), )) if hasattr(os, "lchmod"): - funcs.append((os.lchmod, 0o777)) + funcs.append((self.filenames, os.lchmod, 0o777)) if hasattr(os, "readlink"): - funcs.append((os.readlink,)) + if sys.platform == "win32": + funcs.append((self.unicode_filenames, os.readlink,)) + else: + funcs.append((self.filenames, os.readlink,)) - for func, *func_args in funcs: - for name in self.filenames: + for filenames, func, *func_args in funcs: + for name in filenames: try: func(name, *func_args) except OSError as err: diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 59f4ca8..8cedb9e 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -3054,7 +3054,7 @@ posix_link(PyObject *self, PyObject *args, PyObject *kwargs) Py_END_ALLOW_THREADS if (!result) { - return_value = path_error(&dst); + return_value = path_error(&src); goto exit; } #else @@ -3234,7 +3234,6 @@ posix_listdir(PyObject *self, PyObject *args, PyObject *kwargs) if (error == ERROR_FILE_NOT_FOUND) goto exit; Py_DECREF(list); - path.func = "FindFirstFile"; list = path_error(&path); goto exit; } @@ -3263,7 +3262,6 @@ posix_listdir(PyObject *self, PyObject *args, PyObject *kwargs) it got to the end of the directory. */ if (!result && GetLastError() != ERROR_NO_MORE_FILES) { Py_DECREF(list); - path.func = "FindNextFile"; list = path_error(&path); goto exit; } @@ -3782,7 +3780,7 @@ internal_rename(PyObject *args, PyObject *kwargs, int is_replace) Py_END_ALLOW_THREADS if (!result) { - return_value = path_error(&dst); + return_value = path_error(&src); goto exit; } @@ -6707,7 +6705,7 @@ posix_symlink(PyObject *self, PyObject *args, PyObject *kwargs) Py_END_ALLOW_THREADS if (result) { - return_value = path_error(&dst); + return_value = path_error(&src); goto exit; } #endif @@ -7059,12 +7057,6 @@ posix_open(PyObject *self, PyObject *args, PyObject *kwargs) Py_END_ALLOW_THREADS if (fd == -1) { -#ifdef MS_WINDOWS - /* force use of posix_error here for exact backwards compatibility */ - if (path.wide) - return_value = posix_error(); - else -#endif return_value = path_error(&path); goto exit; } -- cgit v0.12