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 @@ -8,6 +8,7 @@ import warnings import sys import signal +import stat import subprocess import time try: @@ -17,12 +18,23 @@ from test import test_support from test.script_helper import assert_python_ok +from test.test_support import TESTFN, TESTFN_UNICODE, TESTFN_ENCODING import mmap import uuid warnings.filterwarnings("ignore", "tempnam", RuntimeWarning, __name__) warnings.filterwarnings("ignore", "tmpnam", RuntimeWarning, __name__) +supports_unicode_filenames = True +if not os.path.supports_unicode_filenames: + try: + TESTFN_UNICODE.encode(TESTFN_ENCODING) + except (AttributeError, UnicodeError, TypeError): + # Either the file system encoding is None, or the file name + # cannot be encoded in the file system encoding. + supports_unicode_filenames = False + + # Tests creating TESTFN class FileTests(unittest.TestCase): def setUp(self): @@ -871,6 +883,125 @@ self._kill_with_event(signal.CTRL_BREAK_EVENT, "CTRL_BREAK_EVENT") +@unittest.skipUnless(supports_unicode_filenames, + "unicode file names are not supported") +class UnicodePathNames(unittest.TestCase): + + def setUp(self): + test_support.unlink(TESTFN) + test_support.unlink(TESTFN_UNICODE) + test_support.rmdir(TESTFN_UNICODE) + + tearDown = setUp + + def test_mkdir_chdir_getcwd_getcwdu_rmdir(self): + os.mkdir(TESTFN_UNICODE) + os.chdir(TESTFN_UNICODE) + os.getcwd() + os.getcwdu() + os.chdir('..') + os.rmdir(TESTFN_UNICODE) + + @unittest.skipUnless(hasattr(os, 'access'), 'test needs os.access()') + def test_access(self): + with open(TESTFN_UNICODE, 'w'): + os.access(TESTFN_UNICODE, os.R_OK) + + @unittest.skipUnless(hasattr(os, 'chflags'), 'test needs os.chflags()') + def test_chflags(self): + with open(TESTFN_UNICODE, 'w'): + os.chflags(TESTFN_UNICODE, stat.UF_APPEND) + if hasattr(os, 'lchflags'): + os.lchflags(TESTFN_UNICODE, stat.UF_APPEND) + + @unittest.skipUnless(hasattr(os, 'chmod'), 'test needs os.chdmod()') + def test_chdmod(self): + with open(TESTFN_UNICODE, 'w'): + os.chmod(TESTFN_UNICODE, 0755) + if hasattr(os, 'lchmod'): + os.lchmod(TESTFN_UNICODE, 0755) + + @unittest.skipUnless(hasattr(os, 'chown'), 'test needs os.chown()') + def test_chown(self): + with open(TESTFN_UNICODE, 'w'): + os.chown(TESTFN_UNICODE, -1, -1) + if hasattr(os, 'lchown'): + os.lchown(TESTFN_UNICODE, -1, -1) + + @unittest.skipUnless(hasattr(os, 'link'), 'test needs os.link()') + def test_link(self): + with open(TESTFN_UNICODE, 'w'): + os.link(TESTFN_UNICODE, TESTFN) + + def test_listdir(self): + os.mkdir(TESTFN_UNICODE) + os.listdir(TESTFN_UNICODE) + + def test_stat(self): + with open(TESTFN_UNICODE, 'w'): + os.stat(TESTFN_UNICODE) + if hasattr(os, 'lstat'): + os.lstat(TESTFN_UNICODE) + + @unittest.skipUnless(hasattr(os, 'mkfifo'), 'test needs os.mkfifo()') + def test_mkfifo(self): + with open(TESTFN_UNICODE, 'w'): + os.mkfifo(TESTFN_UNICODE) + + @unittest.skipUnless(hasattr(os, 'mknod'), 'test needs os.mknod()') + def test_mknod(self): + with open(TESTFN_UNICODE, 'w'): + try: + os.mknod(TESTFN_UNICODE) + except OSError: + # Can't get this to work (always get file exists). + # That's OK, we're just testing encoding errors are not raised. + pass + + def test_remove(self): + with open(TESTFN_UNICODE, 'w'): + os.remove(TESTFN_UNICODE) + + def test_rename(self): + with open(TESTFN_UNICODE, 'w'): + os.rename(TESTFN_UNICODE, TESTFN) + os.rename(TESTFN, TESTFN_UNICODE) + + def test_renames(self): + with open(TESTFN_UNICODE, 'w'): + os.renames(TESTFN_UNICODE, TESTFN) + os.renames(TESTFN, TESTFN_UNICODE) + + def test_makedirs_removedirs(self): + os.makedirs(TESTFN_UNICODE) + os.removedirs(TESTFN_UNICODE) + + @unittest.skipUnless(hasattr(os, 'pathconf'), 'test needs os.pathconf()') + def test_pathconf(self): + with open(TESTFN_UNICODE, 'w'): + try: + os.pathconf(TESTFN_UNICODE, 0) + except ValueError: + pass + + @unittest.skipUnless(hasattr(os, 'statvfs'), 'test needs os.statvfs()') + def test_statvfs(self): + with open(TESTFN_UNICODE, 'w'): + os.statvfs(TESTFN_UNICODE) + + @unittest.skipUnless(hasattr(os, 'symlink'), 'test needs os.symlink()') + def test_symlink(self): + with open(TESTFN_UNICODE, 'w'): + os.symlink(TESTFN_UNICODE, TESTFN) + + # skip os.tempnam as it is removed in 3.X + + @unittest.skipUnless(hasattr(os, 'utime'), 'test needs os.utime()') + def test_utime(self): + with open(TESTFN_UNICODE, 'w'): + os.utime(TESTFN_UNICODE, None) + + def test_main(): test_support.run_unittest( FileTests, @@ -885,7 +1016,8 @@ Win32ErrorTests, TestInvalidFD, PosixUidGidTests, - Win32KillTests + Win32KillTests, + UnicodePathNames, ) if __name__ == "__main__": diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -6295,10 +6295,10 @@ #ifdef Py_USING_UNICODE int arg_is_unicode = 0; #endif - if (!PyArg_ParseTuple(args, "et:readlink", Py_FileSystemDefaultEncoding, &path)) return NULL; + #ifdef Py_USING_UNICODE v = PySequence_GetItem(args, 0); if (v == NULL) { @@ -6950,8 +6950,8 @@ char *filename; int mode = 0666; int res; - if (!PyArg_ParseTuple(args, "s|i:mkfifo", &filename, &mode)) - return NULL; + if (!PyArg_ParseTuple(args, "et|i:mkfifo", + Py_FileSystemDefaultEncoding, &filename, &mode)) Py_BEGIN_ALLOW_THREADS res = mkfifo(filename, mode); Py_END_ALLOW_THREADS @@ -6981,7 +6981,9 @@ int mode = 0600; int device = 0; int res; - if (!PyArg_ParseTuple(args, "s|ii:mknod", &filename, &mode, &device)) + + if (!PyArg_ParseTuple(args, "et|ii:mknod", Py_FileSystemDefaultEncoding, + &filename, &mode, &device)) return NULL; Py_BEGIN_ALLOW_THREADS res = mknod(filename, mode, device); @@ -7447,7 +7449,8 @@ char *path; int res; struct statvfs st; - if (!PyArg_ParseTuple(args, "s:statvfs", &path)) + if (!PyArg_ParseTuple(args, "et:statvfs", + Py_FileSystemDefaultEncoding, &path)) return NULL; Py_BEGIN_ALLOW_THREADS res = statvfs(path, &st);