[Python-checkins] cpython (merge default -> default): Merge

antoine.pitrou python-checkins at python.org
Tue Nov 15 22:32:41 CET 2011


http://hg.python.org/cpython/rev/b24bcb1b1314
changeset:   73578:b24bcb1b1314
parent:      73577:cea2d28f2855
parent:      73576:d42811b93357
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Tue Nov 15 22:27:43 2011 +0100
summary:
  Merge

files:
  Doc/whatsnew/3.3.rst         |    4 +
  Lib/test/test_genericpath.py |   21 +-
  Lib/test/test_ntpath.py      |    7 +-
  Lib/test/test_os.py          |   44 ++-
  Lib/test/test_pep277.py      |    9 +-
  Lib/test/test_posixpath.py   |   14 +-
  Misc/NEWS                    |    4 +
  Modules/posixmodule.c        |  380 ++++++++++++----------
  8 files changed, 289 insertions(+), 194 deletions(-)


diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst
--- a/Doc/whatsnew/3.3.rst
+++ b/Doc/whatsnew/3.3.rst
@@ -573,6 +573,10 @@
   with sys.platform.startswith('linux'), or directly sys.platform == 'linux' if
   you don't need to support older Python versions.
 
+* Issue #13374: 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 --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py
--- a/Lib/test/test_genericpath.py
+++ b/Lib/test/test_genericpath.py
@@ -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 --git a/Lib/test/test_ntpath.py b/Lib/test/test_ntpath.py
--- a/Lib/test/test_ntpath.py
+++ b/Lib/test/test_ntpath.py
@@ -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 --git a/Lib/test/test_os.py b/Lib/test/test_os.py
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -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)
 
 
+ at 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 --git a/Lib/test/test_pep277.py b/Lib/test/test_pep277.py
--- a/Lib/test/test_pep277.py
+++ b/Lib/test/test_pep277.py
@@ -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 --git a/Lib/test/test_posixpath.py b/Lib/test/test_posixpath.py
--- a/Lib/test/test_posixpath.py
+++ b/Lib/test/test_posixpath.py
@@ -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 --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -374,6 +374,10 @@
 Library
 -------
 
+- Issue #13374: The Windows bytes API has been deprecated in the os module. Use
+  Unicode filenames instead of bytes filenames to not depend on the ANSI code
+  page anymore and to support any filename.
+
 - Issue #13297: Use bytes type to send and receive binary data through XMLRPC.
 
 - Issue #6397: Support "/dev/poll" polling objects in select module,
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -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 *unicode;
+    if (PyUnicode_Check(obj)) {
+        if (PyUnicode_READY(obj))
+            return NULL;
+        Py_INCREF(obj);
+        return obj;
+    }
+    if (!PyUnicode_FSDecoder(obj, &unicode))
+        return NULL;
+    if (win32_warn_bytes_api()) {
+        Py_DECREF(unicode);
+        return NULL;
+    }
+    return unicode;
+}
 #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 */
@@ -2450,51 +2468,56 @@
 static PyObject *
 win32_link(PyObject *self, PyObject *args)
 {
-    PyObject *osrc, *odst;
-    char *src, *dst;
-    BOOL rslt;
-    PyObject *usrc, *udst;
-
-    if (PyArg_ParseTuple(args, "UU:link", &usrc, &udst))
+    PyObject *src, *dst;
+    BOOL ok;
+
+    if (PyArg_ParseTuple(args, "UU:link", &src, &dst))
     {
         wchar_t *wsrc, *wdst;
-        wsrc = PyUnicode_AsUnicode(usrc);
+
+        wsrc = PyUnicode_AsUnicode(src);
         if (wsrc == NULL)
+            goto error;
+        wdst = PyUnicode_AsUnicode(dst);
+        if (wdst == NULL)
+            goto error;
+
+        Py_BEGIN_ALLOW_THREADS
+        ok = CreateHardLinkW(wdst, wsrc, NULL);
+        Py_END_ALLOW_THREADS
+
+        if (!ok)
+            return win32_error("link", NULL);
+        Py_RETURN_NONE;
+    }
+    else {
+        PyErr_Clear();
+        if (!PyArg_ParseTuple(args, "O&O&:link",
+                              PyUnicode_FSConverter, &src,
+                              PyUnicode_FSConverter, &dst))
             return NULL;
-        wdst = PyUnicode_AsUnicode(udst);
-        if (wdst == NULL)
-            return NULL;
+
+        if (win32_warn_bytes_api())
+            goto error;
 
         Py_BEGIN_ALLOW_THREADS
-        rslt = CreateHardLinkW(wdst, wsrc, NULL);
+        ok = CreateHardLinkA(PyBytes_AS_STRING(dst),
+                             PyBytes_AS_STRING(src),
+                             NULL);
         Py_END_ALLOW_THREADS
 
-        if (rslt == 0)
+        Py_XDECREF(src);
+        Py_XDECREF(dst);
+
+        if (!ok)
             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 (rslt == 0)
-        return win32_error("link", NULL);
-
-    Py_RETURN_NONE;
+
+    error:
+        Py_XDECREF(src);
+        Py_XDECREF(dst);
+        return NULL;
+    }
 }
 #endif /* MS_WINDOWS */
 
@@ -2519,7 +2542,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 +2637,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 +2938,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 +2974,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 +3088,7 @@
 static PyObject *
 posix__isdir(PyObject *self, PyObject *args)
 {
-    PyObject *opath;
-    char *path;
+    const char *path;
     PyObject *po;
     DWORD attributes;
 
@@ -3088,11 +3106,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 +3130,7 @@
 posix_mkdir(PyObject *self, PyObject *args)
 {
     int res;
-    PyObject *opath;
-    char *path;
+    const char *path;
     int mode = 0777;
 
 #ifdef MS_WINDOWS
@@ -3136,22 +3152,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))
@@ -3265,44 +3280,54 @@
 posix_rename(PyObject *self, PyObject *args)
 {
 #ifdef MS_WINDOWS
-    PyObject *o1, *o2;
-    wchar_t *w1, *w2;
-    char *p1, *p2;
+    PyObject *src, *dst;
     BOOL result;
-    if (!PyArg_ParseTuple(args, "OO:rename", &o1, &o2))
-        goto error;
-    if (!convert_to_unicode(&o1))
-        goto error;
-    if (!convert_to_unicode(&o2)) {
-        Py_DECREF(o1);
-        goto error;
-    }
-    w1 = PyUnicode_AsUnicode(o1);
-    if (w1 == NULL)
-        goto error;
-    w2 = PyUnicode_AsUnicode(o2);
-    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;
+    if (PyArg_ParseTuple(args, "UU:rename", &src, &dst))
+    {
+        wchar_t *wsrc, *wdst;
+
+        wsrc = PyUnicode_AsUnicode(src);
+        if (wsrc == NULL)
+            return NULL;
+        wdst = PyUnicode_AsUnicode(dst);
+        if (wdst == NULL)
+            return NULL;
+        Py_BEGIN_ALLOW_THREADS
+        result = MoveFileW(wsrc, wdst);
+        Py_END_ALLOW_THREADS
+        if (!result)
+            return win32_error("rename", NULL);
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+    else {
+        PyErr_Clear();
+        if (!PyArg_ParseTuple(args, "O&O&:rename",
+                              PyUnicode_FSConverter, &src,
+                              PyUnicode_FSConverter, &dst))
+            return NULL;
+
+        if (win32_warn_bytes_api())
+            goto error;
+
+        Py_BEGIN_ALLOW_THREADS
+        result = MoveFileA(PyBytes_AS_STRING(src),
+                           PyBytes_AS_STRING(dst));
+        Py_END_ALLOW_THREADS
+
+        Py_XDECREF(src);
+        Py_XDECREF(dst);
+
+        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(src);
+        Py_XDECREF(dst);
+        return NULL;
+    }
 #else
     return posix_2str(args, "O&O&:rename", rename);
 #endif
@@ -3546,8 +3571,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 +3595,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 +3607,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 +6538,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 +6551,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 +6587,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 +6815,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 +9320,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,

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list