diff -r 6bf07db23445 Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst Wed Nov 09 01:13:45 2011 +0100 +++ b/Doc/whatsnew/3.3.rst Wed Nov 09 21:35:21 2011 +0100 @@ -568,6 +568,10 @@ with sys.platform.startswith('linux'), or directly sys.platform == 'linux' if you don't need to support older Python versions. +* Issue #xxx: The Windows bytes API has been deprecated in the :mod:`os` + module. Use Unicode filenames instead of bytes filenames to not depend on the + ANSI code page anymore and to support any filename. + Porting C code -------------- diff -r 6bf07db23445 Lib/test/test_genericpath.py --- a/Lib/test/test_genericpath.py Wed Nov 09 01:13:45 2011 +0100 +++ b/Lib/test/test_genericpath.py Wed Nov 09 21:35:21 2011 +0100 @@ -2,11 +2,12 @@ Tests common to genericpath, macpath, ntpath and posixpath """ +import genericpath +import os +import sys import unittest +import warnings from test import support -import os -import genericpath -import sys def safe_rmdir(dirname): @@ -258,7 +259,9 @@ def test_abspath(self): self.assertIn("foo", self.pathmodule.abspath("foo")) - self.assertIn(b"foo", self.pathmodule.abspath(b"foo")) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + self.assertIn(b"foo", self.pathmodule.abspath(b"foo")) # Abspath returns bytes when the arg is bytes for path in (b'', b'foo', b'f\xf2\xf2', b'/foo', b'C:\\'): @@ -266,7 +269,9 @@ def test_realpath(self): self.assertIn("foo", self.pathmodule.realpath("foo")) - self.assertIn(b"foo", self.pathmodule.realpath(b"foo")) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + self.assertIn(b"foo", self.pathmodule.realpath(b"foo")) def test_normpath_issue5827(self): # Make sure normpath preserves unicode @@ -296,8 +301,10 @@ "Mac OS X denies the creation of a directory with an invalid utf8 name") def test_nonascii_abspath(self): # Test non-ASCII, non-UTF8 bytes in the path. - with support.temp_cwd(b'\xe7w\xf0'): - self.test_abspath() + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + with support.temp_cwd(b'\xe7w\xf0'): + self.test_abspath() def test_main(): diff -r 6bf07db23445 Lib/test/test_ntpath.py --- a/Lib/test/test_ntpath.py Wed Nov 09 01:13:45 2011 +0100 +++ b/Lib/test/test_ntpath.py Wed Nov 09 21:35:21 2011 +0100 @@ -1,10 +1,11 @@ import ntpath import os import sys +import unittest +import warnings from test.support import TestFailed from test import support, test_genericpath from tempfile import TemporaryFile -import unittest def tester(fn, wantResult): @@ -21,7 +22,9 @@ fn = fn.replace('["', '[b"') fn = fn.replace(", '", ", b'") fn = fn.replace(', "', ', b"') - gotResult = eval(fn) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + gotResult = eval(fn) if isinstance(wantResult, str): wantResult = wantResult.encode('ascii') elif isinstance(wantResult, tuple): diff -r 6bf07db23445 Lib/test/test_os.py --- a/Lib/test/test_os.py Wed Nov 09 01:13:45 2011 +0100 +++ b/Lib/test/test_os.py Wed Nov 09 21:35:21 2011 +0100 @@ -213,7 +213,9 @@ fname = self.fname.encode(sys.getfilesystemencoding()) except UnicodeEncodeError: self.skipTest("cannot encode %a for the filesystem" % self.fname) - self.check_stat_attributes(fname) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + self.check_stat_attributes(fname) def test_statvfs_attributes(self): if not hasattr(os, "statvfs"): @@ -838,7 +840,9 @@ with open(file1, "w") as f1: f1.write("test") - os.link(file1, file2) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + os.link(file1, file2) with open(file1, "r") as f1, open(file2, "r") as f2: self.assertTrue(os.path.sameopenfile(f1.fileno(), f2.fileno())) @@ -1160,8 +1164,10 @@ self.assertNotEqual(os.lstat(link), os.stat(link)) bytes_link = os.fsencode(link) - self.assertEqual(os.stat(bytes_link), os.stat(target)) - self.assertNotEqual(os.lstat(bytes_link), os.stat(bytes_link)) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + self.assertEqual(os.stat(bytes_link), os.stat(target)) + self.assertNotEqual(os.lstat(bytes_link), os.stat(bytes_link)) def test_12084(self): level1 = os.path.abspath(support.TESTFN) @@ -1619,6 +1625,35 @@ self._check_xattrs(getxattr, setxattr, removexattr, listxattr) +@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests") +class Win32DeprecatedBytesAPI(unittest.TestCase): + def test_deprecated(self): + import nt + filename = os.fsencode(support.TESTFN) + with warnings.catch_warnings(): + warnings.simplefilter("error", DeprecationWarning) + for func, *args in ( + (nt._getfullpathname, filename), + (nt._isdir, filename), + (os.access, filename, os.R_OK), + (os.chdir, filename), + (os.chmod, filename, 0o777), + (os.link, filename, filename), + (os.listdir, filename), + (os.lstat, filename), + (os.mkdir, filename), + (os.open, filename, os.O_RDONLY), + (os.rename, filename, filename), + (os.rmdir, filename), + (os.startfile, filename), + (os.stat, filename), + (os.symlink, filename, filename), + (os.unlink, filename), + (os.utime, filename), + ): + self.assertRaises(DeprecationWarning, func, *args) + + @support.reap_threads def test_main(): support.run_unittest( @@ -1643,6 +1678,7 @@ TestSendfile, ProgramPriorityTests, ExtendedAttributeTests, + Win32DeprecatedBytesAPI, ) if __name__ == "__main__": diff -r 6bf07db23445 Lib/test/test_pep277.py --- a/Lib/test/test_pep277.py Wed Nov 09 01:13:45 2011 +0100 +++ b/Lib/test/test_pep277.py Wed Nov 09 21:35:21 2011 +0100 @@ -1,6 +1,9 @@ # Test the Unicode versions of normal file functions # open, os.open, os.stat. os.listdir, os.rename, os.remove, os.mkdir, os.chdir, os.rmdir -import sys, os, unittest +import os +import sys +import unittest +import warnings from unicodedata import normalize from test import support @@ -155,7 +158,9 @@ @unittest.skipIf(sys.platform == 'darwin', 'irrelevant test on Mac OS X') def test_listdir(self): sf0 = set(self.files) - f1 = os.listdir(support.TESTFN.encode(sys.getfilesystemencoding())) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + f1 = os.listdir(support.TESTFN.encode(sys.getfilesystemencoding())) f2 = os.listdir(support.TESTFN) sf2 = set(os.path.join(support.TESTFN, f) for f in f2) self.assertEqual(sf0, sf2, "%a != %a" % (sf0, sf2)) diff -r 6bf07db23445 Lib/test/test_posixpath.py --- a/Lib/test/test_posixpath.py Wed Nov 09 01:13:45 2011 +0100 +++ b/Lib/test/test_posixpath.py Wed Nov 09 21:35:21 2011 +0100 @@ -1,11 +1,11 @@ +import os +import posixpath +import sys import unittest +import warnings +from posixpath import realpath, abspath, dirname, basename from test import support, test_genericpath -import posixpath -import os -import sys -from posixpath import realpath, abspath, dirname, basename - try: import posix except ImportError: @@ -231,7 +231,9 @@ def test_ismount(self): self.assertIs(posixpath.ismount("/"), True) - self.assertIs(posixpath.ismount(b"/"), True) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + self.assertIs(posixpath.ismount(b"/"), True) def test_ismount_non_existent(self): # Non-existent mountpoint. diff -r 6bf07db23445 Modules/posixmodule.c --- a/Modules/posixmodule.c Wed Nov 09 01:13:45 2011 +0100 +++ b/Modules/posixmodule.c Wed Nov 09 21:35:21 2011 +0100 @@ -546,6 +546,34 @@ return TRUE; } + +static int +win32_warn_bytes_api() +{ + return PyErr_WarnEx(PyExc_DeprecationWarning, + "The Windows bytes API has been deprecated, " + "use Unicode filenames instead", + 1); +} + +static PyObject* +win32_decode_filename(PyObject *obj) +{ + PyObject *bytes; + if (PyUnicode_Check(obj)) { + if (PyUnicode_READY(obj)) + return NULL; + Py_INCREF(obj); + return obj; + } + if (!PyUnicode_FSDecoder(obj, &bytes)) + return NULL; + if (win32_warn_bytes_api()) { + Py_DECREF(bytes); + return NULL; + } + return bytes; +} #endif /* MS_WINDOWS */ /* Return a dictionary corresponding to the POSIX environment table */ @@ -725,22 +753,6 @@ return PyErr_SetFromWindowsErr(errno); } -static int -convert_to_unicode(PyObject **param) -{ - if (PyUnicode_CheckExact(*param)) - Py_INCREF(*param); - else if (PyUnicode_Check(*param)) - /* For a Unicode subtype that's not a Unicode object, - return a true Unicode object with the same data. */ - *param = PyUnicode_Copy(*param); - else - *param = PyUnicode_FromEncodedObject(*param, - Py_FileSystemDefaultEncoding, - "strict"); - return (*param) != NULL; -} - #endif /* MS_WINDOWS */ #if defined(PYOS_OS2) @@ -895,7 +907,7 @@ char* wformat, BOOL (__stdcall *funcW)(LPWSTR)) { PyObject *uni; - char *ansi; + const char *ansi; BOOL result; if (PyArg_ParseTuple(args, wformat, &uni)) @@ -915,6 +927,8 @@ if (!PyArg_ParseTuple(args, format, &ansi)) return NULL; + if (win32_warn_bytes_api()) + return NULL; Py_BEGIN_ALLOW_THREADS result = funcA(ansi); Py_END_ALLOW_THREADS @@ -1129,14 +1143,15 @@ /* Grab GetFinalPathNameByHandle dynamically from kernel32 */ static int has_GetFinalPathNameByHandle = 0; -static DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, - DWORD); static DWORD (CALLBACK *Py_GetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD, DWORD); static int check_GetFinalPathNameByHandle() { HINSTANCE hKernel32; + DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD, + DWORD); + /* only recheck */ if (!has_GetFinalPathNameByHandle) { @@ -1853,6 +1868,12 @@ if (!PyArg_ParseTuple(args, format, PyUnicode_FSConverter, &opath)) return NULL; +#ifdef MS_WINDOWS + if (win32_warn_bytes_api()) { + Py_DECREF(opath); + return NULL; + } +#endif path = PyBytes_AsString(opath); Py_BEGIN_ALLOW_THREADS res = (*statfunc)(path, &st); @@ -1885,8 +1906,7 @@ static PyObject * posix_access(PyObject *self, PyObject *args) { - PyObject *opath; - char *path; + const char *path; int mode; #ifdef MS_WINDOWS @@ -1904,14 +1924,13 @@ /* Drop the argument parsing error as narrow strings are also valid. */ PyErr_Clear(); - if (!PyArg_ParseTuple(args, "O&i:access", - PyUnicode_FSConverter, &opath, &mode)) - return NULL; - path = PyBytes_AsString(opath); + if (!PyArg_ParseTuple(args, "yi:access", &path, &mode)) + return NULL; + if (win32_warn_bytes_api()) + return NULL; Py_BEGIN_ALLOW_THREADS attr = GetFileAttributesA(path); Py_END_ALLOW_THREADS - Py_DECREF(opath); finish: if (attr == 0xFFFFFFFF) /* File does not exist, or cannot read attributes */ @@ -1923,6 +1942,7 @@ || !(attr & FILE_ATTRIBUTE_READONLY) || (attr & FILE_ATTRIBUTE_DIRECTORY)); #else + PyObject *opath; int res; if (!PyArg_ParseTuple(args, "O&i:access", PyUnicode_FSConverter, &opath, &mode)) @@ -2042,7 +2062,7 @@ posix_chmod(PyObject *self, PyObject *args) { PyObject *opath = NULL; - char *path = NULL; + const char *path = NULL; int i; int res; #ifdef MS_WINDOWS @@ -2073,10 +2093,10 @@ are also valid. */ PyErr_Clear(); - if (!PyArg_ParseTuple(args, "O&i:chmod", PyUnicode_FSConverter, - &opath, &i)) - return NULL; - path = PyBytes_AsString(opath); + if (!PyArg_ParseTuple(args, "yi:chmod", &path, &i)) + return NULL; + if (win32_warn_bytes_api()) + return NULL; Py_BEGIN_ALLOW_THREADS attr = GetFileAttributesA(path); if (attr != 0xFFFFFFFF) { @@ -2091,10 +2111,8 @@ Py_END_ALLOW_THREADS if (!res) { win32_error("chmod", path); - Py_DECREF(opath); - return NULL; - } - Py_DECREF(opath); + return NULL; + } Py_INCREF(Py_None); return Py_None; #else /* MS_WINDOWS */ @@ -2451,50 +2469,40 @@ win32_link(PyObject *self, PyObject *args) { PyObject *osrc, *odst; - char *src, *dst; + PyObject *usrc = NULL, *udst = NULL; + wchar_t *wsrc, *wdst; BOOL rslt; - PyObject *usrc, *udst; - - if (PyArg_ParseTuple(args, "UU:link", &usrc, &udst)) - { - wchar_t *wsrc, *wdst; - wsrc = PyUnicode_AsUnicode(usrc); - if (wsrc == NULL) - return NULL; - wdst = PyUnicode_AsUnicode(udst); - if (wdst == NULL) - return NULL; - - Py_BEGIN_ALLOW_THREADS - rslt = CreateHardLinkW(wdst, wsrc, NULL); - Py_END_ALLOW_THREADS - - if (rslt == 0) - return win32_error("link", NULL); - - Py_RETURN_NONE; - } - - /* Narrow strings also valid. */ - PyErr_Clear(); - - if (!PyArg_ParseTuple(args, "O&O&:link", PyUnicode_FSConverter, &osrc, - PyUnicode_FSConverter, &odst)) - return NULL; - - src = PyBytes_AsString(osrc); - dst = PyBytes_AsString(odst); - - Py_BEGIN_ALLOW_THREADS - rslt = CreateHardLinkA(dst, src, NULL); - Py_END_ALLOW_THREADS - - Py_DECREF(osrc); - Py_DECREF(odst); + + if (!PyArg_ParseTuple(args, "OO:link", &osrc, &odst)) + return NULL; + + usrc = win32_decode_filename(osrc); + if (!usrc) + goto error; + udst = win32_decode_filename(odst); + if (!udst) + goto error; + + wsrc = PyUnicode_AsUnicode(usrc); + if (wsrc == NULL) + goto error; + wdst = PyUnicode_AsUnicode(udst); + if (wdst == NULL) + goto error; + + Py_BEGIN_ALLOW_THREADS + rslt = CreateHardLinkW(wdst, wsrc, NULL); + Py_END_ALLOW_THREADS + if (rslt == 0) return win32_error("link", NULL); Py_RETURN_NONE; + +error: + Py_XDECREF(usrc); + Py_XDECREF(udst); + return NULL; } #endif /* MS_WINDOWS */ @@ -2519,7 +2527,8 @@ HANDLE hFindFile; BOOL result; WIN32_FIND_DATA FileData; - PyObject *opath; + const char *path; + Py_ssize_t pathlen; char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */ char *bufptr = namebuf; Py_ssize_t len = sizeof(namebuf)-5; /* only claim to have space for MAX_PATH */ @@ -2613,17 +2622,16 @@ are also valid. */ PyErr_Clear(); - if (!PyArg_ParseTuple(args, "O&:listdir", - PyUnicode_FSConverter, &opath)) - return NULL; - if (PyBytes_GET_SIZE(opath)+1 > MAX_PATH) { + if (!PyArg_ParseTuple(args, "y#:listdir", &path, &pathlen)) + return NULL; + if (win32_warn_bytes_api()) + return NULL; + if (pathlen+1 > MAX_PATH) { PyErr_SetString(PyExc_ValueError, "path too long"); - Py_DECREF(opath); - return NULL; - } - strcpy(namebuf, PyBytes_AsString(opath)); - len = PyObject_Size(opath); - Py_DECREF(opath); + return NULL; + } + strcpy(namebuf, path); + len = pathlen; if (len > 0) { char ch = namebuf[len-1]; if (ch != SEP && ch != ALTSEP && ch != ':') @@ -2915,11 +2923,9 @@ static PyObject * posix__getfullpathname(PyObject *self, PyObject *args) { - PyObject *opath; - char *path; + const char *path; char outbuf[MAX_PATH*2]; char *temp; -#ifdef MS_WINDOWS PyObject *po; if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) @@ -2953,19 +2959,17 @@ /* Drop the argument parsing error as narrow strings are also valid. */ PyErr_Clear(); -#endif - - if (!PyArg_ParseTuple (args, "O&:_getfullpathname", - PyUnicode_FSConverter, &opath)) - return NULL; - path = PyBytes_AsString(opath); + + if (!PyArg_ParseTuple (args, "y:_getfullpathname", + &path)) + return NULL; + if (win32_warn_bytes_api()) + return NULL; if (!GetFullPathName(path, Py_ARRAY_LENGTH(outbuf), outbuf, &temp)) { win32_error("GetFullPathName", path); - Py_DECREF(opath); - return NULL; - } - Py_DECREF(opath); + return NULL; + } if (PyUnicode_Check(PyTuple_GetItem(args, 0))) { return PyUnicode_Decode(outbuf, strlen(outbuf), Py_FileSystemDefaultEncoding, NULL); @@ -3069,8 +3073,7 @@ static PyObject * posix__isdir(PyObject *self, PyObject *args) { - PyObject *opath; - char *path; + const char *path; PyObject *po; DWORD attributes; @@ -3088,11 +3091,10 @@ are also valid. */ PyErr_Clear(); - if (!PyArg_ParseTuple(args, "O&:_isdir", - PyUnicode_FSConverter, &opath)) - return NULL; - - path = PyBytes_AsString(opath); + if (!PyArg_ParseTuple(args, "y:_isdir", &path)) + return NULL; + if (win32_warn_bytes_api()) + return NULL; attributes = GetFileAttributesA(path); if (attributes == INVALID_FILE_ATTRIBUTES) Py_RETURN_FALSE; @@ -3113,8 +3115,7 @@ posix_mkdir(PyObject *self, PyObject *args) { int res; - PyObject *opath; - char *path; + const char *path; int mode = 0777; #ifdef MS_WINDOWS @@ -3136,22 +3137,21 @@ /* Drop the argument parsing error as narrow strings are also valid. */ PyErr_Clear(); - if (!PyArg_ParseTuple(args, "O&|i:mkdir", - PyUnicode_FSConverter, &opath, &mode)) - return NULL; - path = PyBytes_AsString(opath); + if (!PyArg_ParseTuple(args, "y|i:mkdir", &path, &mode)) + return NULL; + if (win32_warn_bytes_api()) + return NULL; Py_BEGIN_ALLOW_THREADS res = CreateDirectoryA(path, NULL); Py_END_ALLOW_THREADS if (!res) { win32_error("mkdir", path); - Py_DECREF(opath); - return NULL; - } - Py_DECREF(opath); + return NULL; + } Py_INCREF(Py_None); return Py_None; #else + PyObject *opath; if (!PyArg_ParseTuple(args, "O&|i:mkdir", PyUnicode_FSConverter, &opath, &mode)) @@ -3266,43 +3266,37 @@ { #ifdef MS_WINDOWS PyObject *o1, *o2; + PyObject *u1 = NULL, *u2 = NULL; wchar_t *w1, *w2; - char *p1, *p2; BOOL result; if (!PyArg_ParseTuple(args, "OO:rename", &o1, &o2)) + return NULL; + + u1 = win32_decode_filename(o1); + if (!u1) goto error; - if (!convert_to_unicode(&o1)) + u2 = win32_decode_filename(o2); + if (!u2) goto error; - if (!convert_to_unicode(&o2)) { - Py_DECREF(o1); - goto error; - } - w1 = PyUnicode_AsUnicode(o1); + + w1 = PyUnicode_AsUnicode(u1); if (w1 == NULL) goto error; - w2 = PyUnicode_AsUnicode(o2); + w2 = PyUnicode_AsUnicode(u2); if (w2 == NULL) goto error; Py_BEGIN_ALLOW_THREADS result = MoveFileW(w1, w2); Py_END_ALLOW_THREADS - Py_DECREF(o1); - Py_DECREF(o2); if (!result) return win32_error("rename", NULL); Py_INCREF(Py_None); return Py_None; + error: - PyErr_Clear(); - if (!PyArg_ParseTuple(args, "ss:rename", &p1, &p2)) - return NULL; - Py_BEGIN_ALLOW_THREADS - result = MoveFileA(p1, p2); - Py_END_ALLOW_THREADS - if (!result) - return win32_error("rename", NULL); - Py_INCREF(Py_None); - return Py_None; + Py_XDECREF(u1); + Py_XDECREF(u2); + return NULL; #else return posix_2str(args, "O&O&:rename", rename); #endif @@ -3546,8 +3540,7 @@ PyObject *arg = Py_None; PyObject *obwpath; wchar_t *wpath = NULL; - PyObject *oapath; - char *apath; + const char *apath; HANDLE hFile; time_t atimesec, mtimesec; long ausec, musec; @@ -3571,11 +3564,11 @@ are also valid. */ PyErr_Clear(); - if (!PyArg_ParseTuple(args, "O&|O:utime", - PyUnicode_FSConverter, &oapath, &arg)) + if (!PyArg_ParseTuple(args, "y|O:utime", &apath, &arg)) return NULL; - - apath = PyBytes_AsString(oapath); + if (win32_warn_bytes_api()) + return NULL; + Py_BEGIN_ALLOW_THREADS hFile = CreateFileA(apath, FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, @@ -3583,10 +3576,8 @@ Py_END_ALLOW_THREADS if (hFile == INVALID_HANDLE_VALUE) { win32_error("utime", apath); - Py_DECREF(oapath); return NULL; } - Py_DECREF(oapath); } if (arg == Py_None) { @@ -6516,7 +6507,8 @@ win_symlink(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"src", "dest", "target_is_directory", NULL}; - PyObject *src, *dest; + PyObject *osrc, *odest; + PyObject *usrc = NULL, *udest = NULL; wchar_t *wsrc, *wdest; int target_is_directory = 0; DWORD res; @@ -6528,24 +6520,25 @@ return PyErr_Format(PyExc_NotImplementedError, "CreateSymbolicLinkW not found"); } - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:symlink", - kwlist, &src, &dest, &target_is_directory)) - return NULL; + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, "OO|i:symlink", kwlist, + &osrc, &odest, &target_is_directory)) + return NULL; + + usrc = win32_decode_filename(osrc); + if (!usrc) + return NULL; + udest = win32_decode_filename(odest); + if (!udest) + goto error; if (win32_can_symlink == 0) return PyErr_Format(PyExc_OSError, "symbolic link privilege not held"); - if (!convert_to_unicode(&src)) - return NULL; - if (!convert_to_unicode(&dest)) { - Py_DECREF(src); - return NULL; - } - - wsrc = PyUnicode_AsUnicode(src); + wsrc = PyUnicode_AsUnicode(usrc); if (wsrc == NULL) goto error; - wdest = PyUnicode_AsUnicode(dest); + wdest = PyUnicode_AsUnicode(udest); if (wsrc == NULL) goto error; @@ -6563,17 +6556,17 @@ res = Py_CreateSymbolicLinkW(wdest, wsrc, target_is_directory); Py_END_ALLOW_THREADS - Py_DECREF(src); - Py_DECREF(dest); + Py_DECREF(usrc); + Py_DECREF(udest); if (!res) - return win32_error_object("symlink", src); + return win32_error_object("symlink", osrc); Py_INCREF(Py_None); return Py_None; error: - Py_DECREF(src); - Py_DECREF(dest); + Py_XDECREF(usrc); + Py_XDECREF(udest); return NULL; } #endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */ @@ -6791,6 +6784,12 @@ PyUnicode_FSConverter, &ofile, &flag, &mode)) return NULL; +#ifdef MS_WINDOWS + if (win32_warn_bytes_api()) { + Py_DECREF(ofile); + return NULL; + } +#endif file = PyBytes_AsString(ofile); Py_BEGIN_ALLOW_THREADS fd = open(file, flag, mode); @@ -9290,6 +9289,10 @@ PyUnicode_FSConverter, &ofilepath, &operation)) return NULL; + if (win32_warn_bytes_api()) { + Py_DECREF(ofilepath); + return NULL; + } filepath = PyBytes_AsString(ofilepath); Py_BEGIN_ALLOW_THREADS rc = ShellExecute((HWND)0, operation, filepath,