Index: Lib/test/test_os.py =================================================================== --- Lib/test/test_os.py (revision 62453) +++ Lib/test/test_os.py (working copy) @@ -513,6 +513,13 @@ class Win32ErrorTests(unittest.TestCase): pass +class TypeErrorTests(unittest.TestCase): + def test_rename(self): + self.assertRaises(TypeError, os.rename, 0, 0) + for path in (test_support.TESTFN, unicode(test_support.TESTFN)): + self.assertRaises(TypeError, os.rename, path, 0) + self.assertRaises(TypeError, os.rename, 0, path) + def test_main(): test_support.run_unittest( FileTests, @@ -523,7 +530,8 @@ MakedirTests, DevNullTests, URandomTests, - Win32ErrorTests + Win32ErrorTests, + TypeErrorTests ) if __name__ == "__main__": Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 62453) +++ Modules/posixmodule.c (working copy) @@ -478,27 +478,20 @@ { } -/* Function suitable for O& conversion */ -static int -convert_to_unicode(PyObject *arg, void* _param) +static void +convert_to_unicode(PyObject **arg) { - PyObject **param = (PyObject**)_param; - if (PyUnicode_CheckExact(arg)) { - Py_INCREF(arg); - *param = arg; - } - else if (PyUnicode_Check(arg)) { + if (PyUnicode_CheckExact(*arg)) + Py_INCREF(*arg); + else if (PyUnicode_Check(*arg)) /* For a Unicode subtype that's not a Unicode object, return a true Unicode object with the same data. */ - *param = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(arg), - PyUnicode_GET_SIZE(arg)); - return *param != NULL; - } + *arg = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(*arg), + PyUnicode_GET_SIZE(*arg)); else - *param = PyUnicode_FromEncodedObject(arg, - Py_FileSystemDefaultEncoding, - "strict"); - return (*param) != NULL; + *arg = PyUnicode_FromEncodedObject(*arg, + Py_FileSystemDefaultEncoding, + "strict"); } #endif /* Py_WIN_WIDE_FILENAMES */ @@ -689,6 +682,45 @@ } +static PyObject* +win32_2str(PyObject* args, char* func, + char* format, BOOL (__stdcall *funcA)(LPCSTR, LPCSTR), + char* wformat, BOOL (__stdcall *funcW)(LPWSTR, LPWSTR)) +{ + PyObject *o1, *o2; + char *p1, *p2; + BOOL result; + if (unicode_file_names()) { + if (PyArg_ParseTuple(args, wformat, &o1, &o2)) { + convert_to_unicode(&o1); + convert_to_unicode(&o2); + if (o1 && o2) { + Py_BEGIN_ALLOW_THREADS + result = funcW(PyUnicode_AS_UNICODE(o1), PyUnicode_AS_UNICODE(o2)); + Py_END_ALLOW_THREADS + Py_DECREF(o1); + Py_DECREF(o2); + if (!result) + return win32_error(func, NULL); + Py_INCREF(Py_None); + return Py_None; + } + Py_XDECREF(o1); + Py_XDECREF(o2); + } + PyErr_Clear(); + } + if (!PyArg_ParseTuple(args, format, &p1, &p2)) + return NULL; + Py_BEGIN_ALLOW_THREADS + result = funcA(p1, p2); + Py_END_ALLOW_THREADS + if (!result) + return win32_error(func, NULL); + Py_INCREF(Py_None); + return Py_None; +} + /* This is a reimplementation of the C library's chdir function, but one that produces Win32 errors instead of DOS error codes. chdir is essentially a wrapper around SetCurrentDirectory; however, @@ -2517,36 +2549,7 @@ posix_rename(PyObject *self, PyObject *args) { #ifdef MS_WINDOWS - PyObject *o1, *o2; - char *p1, *p2; - BOOL result; - if (unicode_file_names()) { - if (!PyArg_ParseTuple(args, "O&O&:rename", - convert_to_unicode, &o1, - convert_to_unicode, &o2)) - PyErr_Clear(); - else { - Py_BEGIN_ALLOW_THREADS - result = MoveFileW(PyUnicode_AsUnicode(o1), - PyUnicode_AsUnicode(o2)); - 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, "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; + return win32_2str(args, "rename", "ss:rename", MoveFileA, "OO:rename", MoveFileW); #else return posix_2str(args, "etet:rename", rename); #endif @@ -8973,3 +8976,4 @@ #endif +