diff -r b66e82c9f852 Doc/library/os.rst --- a/Doc/library/os.rst Tue Jun 26 23:05:27 2012 +0200 +++ b/Doc/library/os.rst Wed Jun 27 21:34:48 2012 +0300 @@ -2128,7 +2128,7 @@ and the *dir_fd*, *follow_symlinks*, and *ns* parameters. -.. function:: walk(top, topdown=True, onerror=None, followlinks=False) +.. function:: walk(top, topdown=True, onerror=None, follow_symlinks=False) .. index:: single: directory; walking @@ -2168,12 +2168,12 @@ is available as the ``filename`` attribute of the exception object. By default, :func:`walk` will not walk down into symbolic links that resolve to - directories. Set *followlinks* to ``True`` to visit directories pointed to by + directories. Set *follow_symlinks* to ``True`` to visit directories pointed to by symlinks, on systems that support them. .. note:: - Be aware that setting *followlinks* to ``True`` can lead to infinite + Be aware that setting *follow_symlinks* to ``True`` can lead to infinite recursion if a link points to a parent directory of itself. :func:`walk` does not keep track of the directories it visited already. @@ -2210,8 +2210,12 @@ for name in dirs: os.rmdir(os.path.join(root, name)) - -.. function:: fwalk(top='.', topdown=True, onerror=None, followlinks=False, *, dir_fd=None) + .. versionchanged:: 3.3 + *followlinks* renamed to *follow_symlinks*. For backward compatibility + the old name accepted as alias to new one. + + +.. function:: fwalk(top='.', topdown=True, onerror=None, follow_symlinks=False, *, dir_fd=None) .. index:: single: directory; walking diff -r b66e82c9f852 Lib/os.py --- a/Lib/os.py Tue Jun 26 23:05:27 2012 +0200 +++ b/Lib/os.py Wed Jun 27 21:34:48 2012 +0300 @@ -331,7 +331,9 @@ __all__.extend(["makedirs", "removedirs", "renames"]) -def walk(top, topdown=True, onerror=None, followlinks=False): +_sentry = object() + +def walk(top, topdown=True, onerror=None, follow_symlinks=_sentry, *, followlinks=_sentry): """Directory tree generator. For each directory in the directory tree rooted at top (including top @@ -369,7 +371,7 @@ By default, os.walk does not follow symbolic links to subdirectories on systems that support them. In order to get this functionality, set the - optional argument 'followlinks' to true. + optional argument 'follow_symlinks' to true. Caution: if you pass a relative pathname for top, don't change the current working directory between resumptions of walk. walk never @@ -387,7 +389,18 @@ if 'CVS' in dirs: dirs.remove('CVS') # don't visit CVS directories """ + if follow_symlinks is _sentry: + if followlinks is _sentry: + follow_symlinks = False + else: + follow_symlinks = followlinks + elif followlinks is not _sentry: + raise ValueError( + "'follow_symlinks' and 'followlinks' arguments are incompatible") + yield from _walk(top, topdown, onerror, follow_symlinks) + +def _walk(top, topdown, onerror, follow_symlinks): islink, join, isdir = path.islink, path.join, path.isdir # We may not have read permission for top, in which case we can't @@ -415,8 +428,8 @@ yield top, dirs, nondirs for name in dirs: new_path = join(top, name) - if followlinks or not islink(new_path): - yield from walk(new_path, topdown, onerror, followlinks) + if follow_symlinks or not islink(new_path): + yield from walk(new_path, topdown, onerror, follow_symlinks) if not topdown: yield top, dirs, nondirs @@ -424,7 +437,7 @@ if {open, stat} <= supports_dir_fd and {listdir, stat} <= supports_fd: - def fwalk(top=".", topdown=True, onerror=None, followlinks=False, *, dir_fd=None): + def fwalk(top=".", topdown=True, onerror=None, follow_symlinks=False, *, dir_fd=None): """Directory tree generator. This behaves exactly like walk(), except that it yields a 4-tuple @@ -435,7 +448,7 @@ and `dirfd` is a file descriptor referring to the directory `dirpath`. The advantage of fwalk() over walk() is that it's safe against symlink - races (when followlinks is False). + races (when follow_symlinks is False). If dir_fd is not None, it should be a file descriptor open to a directory, and top should be relative; top will then be relative to that directory. @@ -462,13 +475,13 @@ orig_st = stat(top, follow_symlinks=False, dir_fd=dir_fd) topfd = open(top, O_RDONLY, dir_fd=dir_fd) try: - if (followlinks or (st.S_ISDIR(orig_st.st_mode) and - path.samestat(orig_st, stat(topfd)))): - yield from _fwalk(topfd, top, topdown, onerror, followlinks) + if (follow_symlinks or (st.S_ISDIR(orig_st.st_mode) and + path.samestat(orig_st, stat(topfd)))): + yield from _fwalk(topfd, top, topdown, onerror, follow_symlinks) finally: close(topfd) - def _fwalk(topfd, toppath, topdown, onerror, followlinks): + def _fwalk(topfd, toppath, topdown, onerror, follow_symlinks): # Note: This uses O(depth of the directory tree) file descriptors: if # necessary, it can be adapted to only require O(1) FDs, see issue # #13734. @@ -499,16 +512,16 @@ for name in dirs: try: - orig_st = stat(name, dir_fd=topfd, follow_symlinks=followlinks) + orig_st = stat(name, dir_fd=topfd, follow_symlinks=follow_symlinks) dirfd = open(name, O_RDONLY, dir_fd=topfd) except error as err: if onerror is not None: onerror(err) return try: - if followlinks or path.samestat(orig_st, stat(dirfd)): + if follow_symlinks or path.samestat(orig_st, stat(dirfd)): dirpath = path.join(toppath, name) - yield from _fwalk(dirfd, dirpath, topdown, onerror, followlinks) + yield from _fwalk(dirfd, dirpath, topdown, onerror, follow_symlinks) finally: close(dirfd) diff -r b66e82c9f852 Lib/test/test_os.py --- a/Lib/test/test_os.py Tue Jun 26 23:05:27 2012 +0200 +++ b/Lib/test/test_os.py Wed Jun 27 21:34:48 2012 +0300 @@ -712,6 +712,14 @@ if support.can_symlink(): # Walk, following symlinks. + for root, dirs, files in os.walk(walk_path, follow_symlinks=True): + if root == link_path: + self.assertEqual(dirs, []) + self.assertEqual(files, ["tmp4"]) + break + else: + self.fail("Didn't follow symlink with follow_symlinks=True") + # Walk, using backward compatible argument name "followlinks". for root, dirs, files in os.walk(walk_path, followlinks=True): if root == link_path: self.assertEqual(dirs, []) @@ -720,6 +728,12 @@ else: self.fail("Didn't follow symlink with followlinks=True") + # Incopatible using new and old argument names for "follow_symlinks". + with self.assertRaises(ValueError): + for x in os.walk(walk_path, + follow_symlinks=True, followlinks=True): + break + def tearDown(self): # Tear everything down. This is a decent use for bottom-up on # Windows, which doesn't have a recursive delete command. The @@ -745,8 +759,8 @@ """ compare with walk() results. """ - for topdown, followlinks in itertools.product((True, False), repeat=2): - d = {'topdown': topdown, 'followlinks': followlinks} + for topdown, follow_symlinks in itertools.product((True, False), repeat=2): + d = {'topdown': topdown, 'follow_symlinks': follow_symlinks} walk_kwargs.update(d) fwalk_kwargs.update(d) @@ -774,8 +788,8 @@ def test_yields_correct_dir_fd(self): # check returned file descriptors - for topdown, followlinks in itertools.product((True, False), repeat=2): - args = support.TESTFN, topdown, None, followlinks + for topdown, follow_symlinks in itertools.product((True, False), repeat=2): + args = support.TESTFN, topdown, None, follow_symlinks for root, dirs, files, rootfd in os.fwalk(*args): # check that the FD is valid os.fstat(rootfd) diff -r b66e82c9f852 Modules/_ctypes/libffi/generate-ios-source-and-headers.py --- a/Modules/_ctypes/libffi/generate-ios-source-and-headers.py Tue Jun 26 23:05:27 2012 +0200 +++ b/Modules/_ctypes/libffi/generate-ios-source-and-headers.py Wed Jun 27 21:34:48 2012 +0300 @@ -83,7 +83,7 @@ headers_seen = collections.defaultdict(set) def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None): - for root, dirs, files in os.walk(src_dir, followlinks=True): + for root, dirs, files in os.walk(src_dir, follow_symlinks=True): relroot = os.path.relpath(root,src_dir) def move_dir(arch, prefix='', suffix='', files=[]): diff -r b66e82c9f852 Modules/_ctypes/libffi/generate-osx-source-and-headers.py --- a/Modules/_ctypes/libffi/generate-osx-source-and-headers.py Tue Jun 26 23:05:27 2012 +0200 +++ b/Modules/_ctypes/libffi/generate-osx-source-and-headers.py Wed Jun 27 21:34:48 2012 +0300 @@ -77,7 +77,7 @@ headers_seen = collections.defaultdict(set) def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None): - for root, dirs, files in os.walk(src_dir, followlinks=True): + for root, dirs, files in os.walk(src_dir, follow_symlinks=True): relroot = os.path.relpath(root,src_dir) def move_dir(arch, prefix='', suffix='', files=[]):