Commit c990f645 authored by Neal Norwitz's avatar Neal Norwitz

Try backing out 54407 to see if it corrects the problems on the Windows

buildbots.  This rev was backported, so we will need to keep both branches
in sync, pending the outcome of the test after this checkin.
parent c473d5eb
...@@ -1233,8 +1233,7 @@ Availability: Macintosh, \UNIX, Windows. ...@@ -1233,8 +1233,7 @@ Availability: Macintosh, \UNIX, Windows.
\end{funcdesc} \end{funcdesc}
\begin{funcdesc}{walk}{top\optional{, topdown\code{=True} \begin{funcdesc}{walk}{top\optional{, topdown\code{=True}
\optional{, onerror\code{=None}\optional{, \optional{, onerror\code{=None}}}}
followlinks\code{=False}}}}}
\index{directory!walking} \index{directory!walking}
\index{directory!traversal} \index{directory!traversal}
\function{walk()} generates the file names in a directory tree, by \function{walk()} generates the file names in a directory tree, by
...@@ -1274,18 +1273,8 @@ report the error to continue with the walk, or raise the exception ...@@ -1274,18 +1273,8 @@ report the error to continue with the walk, or raise the exception
to abort the walk. Note that the filename is available as the to abort the walk. Note that the filename is available as the
\code{filename} attribute of the exception object. \code{filename} attribute of the exception object.
By default, \function{walk()} will not walk down into symbolic links that
resolve to directories. Set \var{followlinks} to True to visit directories
pointed to by symlinks, on systems that support them.
\versionadded[The \var{followlinks} parameter]{2.6} \versionadded[The \var{followlinks} parameter]{2.6}
\begin{notice}
Be aware that setting \var{followlinks} to true can lead to infinite recursion
if a link points to a parent directory of itself. \function{walk()} does not
keep track of the directories it visited already.
\end{notice}
\begin{notice} \begin{notice}
If you pass a relative pathname, don't change the current working If you pass a relative pathname, don't change the current working
directory between resumptions of \function{walk()}. \function{walk()} directory between resumptions of \function{walk()}. \function{walk()}
...@@ -1293,6 +1282,15 @@ never changes the current directory, and assumes that its caller ...@@ -1293,6 +1282,15 @@ never changes the current directory, and assumes that its caller
doesn't either. doesn't either.
\end{notice} \end{notice}
\begin{notice}
On systems that support symbolic links, links to subdirectories appear
in \var{dirnames} lists, but \function{walk()} will not visit them
(infinite loops are hard to avoid when following symbolic links).
To visit linked directories, you can identify them with
\code{os.path.islink(\var{path})}, and invoke \code{walk(\var{path})}
on each directly.
\end{notice}
This example displays the number of bytes taken by non-directory files This example displays the number of bytes taken by non-directory files
in each directory under the starting directory, except that it doesn't in each directory under the starting directory, except that it doesn't
look under any CVS subdirectory: look under any CVS subdirectory:
......
...@@ -221,7 +221,7 @@ def renames(old, new): ...@@ -221,7 +221,7 @@ def renames(old, new):
__all__.extend(["makedirs", "removedirs", "renames"]) __all__.extend(["makedirs", "removedirs", "renames"])
def walk(top, topdown=True, onerror=None, followlinks=False): def walk(top, topdown=True, onerror=None):
"""Directory tree generator. """Directory tree generator.
For each directory in the directory tree rooted at top (including top For each directory in the directory tree rooted at top (including top
...@@ -257,10 +257,6 @@ def walk(top, topdown=True, onerror=None, followlinks=False): ...@@ -257,10 +257,6 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
to abort the walk. Note that the filename is available as the to abort the walk. Note that the filename is available as the
filename attribute of the exception object. filename attribute of the exception object.
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.
Caution: if you pass a relative pathname for top, don't change the Caution: if you pass a relative pathname for top, don't change the
current working directory between resumptions of walk. walk never current working directory between resumptions of walk. walk never
changes the current directory, and assumes that the client doesn't changes the current directory, and assumes that the client doesn't
...@@ -304,8 +300,8 @@ def walk(top, topdown=True, onerror=None, followlinks=False): ...@@ -304,8 +300,8 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
yield top, dirs, nondirs yield top, dirs, nondirs
for name in dirs: for name in dirs:
path = join(top, name) path = join(top, name)
if followlinks or not islink(path): if not islink(path):
for x in walk(path, topdown, onerror, followlinks): for x in walk(path, topdown, onerror):
yield x yield x
if not topdown: if not topdown:
yield top, dirs, nondirs yield top, dirs, nondirs
......
...@@ -277,34 +277,22 @@ class WalkTests(unittest.TestCase): ...@@ -277,34 +277,22 @@ class WalkTests(unittest.TestCase):
# SUB1/ a file kid and a directory kid # SUB1/ a file kid and a directory kid
# tmp2 # tmp2
# SUB11/ no kids # SUB11/ no kids
# SUB2/ a file kid and a dirsymlink kid # SUB2/ just a file kid
# tmp3 # tmp3
# link/ a symlink to TESTFN.2
# TESTFN.2/
# tmp4 a lone file
sub1_path = join(test_support.TESTFN, "SUB1") sub1_path = join(test_support.TESTFN, "SUB1")
sub11_path = join(sub1_path, "SUB11") sub11_path = join(sub1_path, "SUB11")
sub2_path = join(test_support.TESTFN, "SUB2") sub2_path = join(test_support.TESTFN, "SUB2")
tmp1_path = join(test_support.TESTFN, "tmp1") tmp1_path = join(test_support.TESTFN, "tmp1")
tmp2_path = join(sub1_path, "tmp2") tmp2_path = join(sub1_path, "tmp2")
tmp3_path = join(sub2_path, "tmp3") tmp3_path = join(sub2_path, "tmp3")
link_path = join(sub2_path, "link")
t2_path = join(test_support.TESTFN + ".2")
tmp4_path = join(test_support.TESTFN + ".2", "tmp4")
# Create stuff. # Create stuff.
os.makedirs(sub11_path) os.makedirs(sub11_path)
os.makedirs(sub2_path) os.makedirs(sub2_path)
os.makedirs(t2_path) for path in tmp1_path, tmp2_path, tmp3_path:
for path in tmp1_path, tmp2_path, tmp3_path, tmp4_path:
f = file(path, "w") f = file(path, "w")
f.write("I'm " + path + " and proud of it. Blame test_os.\n") f.write("I'm " + path + " and proud of it. Blame test_os.\n")
f.close() f.close()
if hasattr(os, "symlink"):
os.symlink(os.path.join("..", "..", t2_path), link_path)
else:
# it must be a directory because the test expects that
os.mkdir(link_path)
# Walk top-down. # Walk top-down.
all = list(os.walk(test_support.TESTFN)) all = list(os.walk(test_support.TESTFN))
...@@ -317,7 +305,7 @@ class WalkTests(unittest.TestCase): ...@@ -317,7 +305,7 @@ class WalkTests(unittest.TestCase):
self.assertEqual(all[0], (test_support.TESTFN, ["SUB1", "SUB2"], ["tmp1"])) self.assertEqual(all[0], (test_support.TESTFN, ["SUB1", "SUB2"], ["tmp1"]))
self.assertEqual(all[1 + flipped], (sub1_path, ["SUB11"], ["tmp2"])) self.assertEqual(all[1 + flipped], (sub1_path, ["SUB11"], ["tmp2"]))
self.assertEqual(all[2 + flipped], (sub11_path, [], [])) self.assertEqual(all[2 + flipped], (sub11_path, [], []))
self.assertEqual(all[3 - 2 * flipped], (sub2_path, ["link"], ["tmp3"])) self.assertEqual(all[3 - 2 * flipped], (sub2_path, [], ["tmp3"]))
# Prune the search. # Prune the search.
all = [] all = []
...@@ -329,7 +317,7 @@ class WalkTests(unittest.TestCase): ...@@ -329,7 +317,7 @@ class WalkTests(unittest.TestCase):
dirs.remove('SUB1') dirs.remove('SUB1')
self.assertEqual(len(all), 2) self.assertEqual(len(all), 2)
self.assertEqual(all[0], (test_support.TESTFN, ["SUB2"], ["tmp1"])) self.assertEqual(all[0], (test_support.TESTFN, ["SUB2"], ["tmp1"]))
self.assertEqual(all[1], (sub2_path, ["link"], ["tmp3"])) self.assertEqual(all[1], (sub2_path, [], ["tmp3"]))
# Walk bottom-up. # Walk bottom-up.
all = list(os.walk(test_support.TESTFN, topdown=False)) all = list(os.walk(test_support.TESTFN, topdown=False))
...@@ -342,17 +330,7 @@ class WalkTests(unittest.TestCase): ...@@ -342,17 +330,7 @@ class WalkTests(unittest.TestCase):
self.assertEqual(all[3], (test_support.TESTFN, ["SUB1", "SUB2"], ["tmp1"])) self.assertEqual(all[3], (test_support.TESTFN, ["SUB1", "SUB2"], ["tmp1"]))
self.assertEqual(all[flipped], (sub11_path, [], [])) self.assertEqual(all[flipped], (sub11_path, [], []))
self.assertEqual(all[flipped + 1], (sub1_path, ["SUB11"], ["tmp2"])) self.assertEqual(all[flipped + 1], (sub1_path, ["SUB11"], ["tmp2"]))
self.assertEqual(all[2 - 2 * flipped], (sub2_path, ["link"], ["tmp3"])) self.assertEqual(all[2 - 2 * flipped], (sub2_path, [], ["tmp3"]))
# Walk, following symlinks.
for root, dirs, files in os.walk(test_support.TESTFN, followlinks=True):
if root == link_path:
self.assertEqual(dirs, [])
self.assertEqual(files, ["tmp4"])
break
else:
self.fail("Didn't follow symlink with followlinks=True")
# Tear everything down. This is a decent use for bottom-up on # Tear everything down. This is a decent use for bottom-up on
# Windows, which doesn't have a recursive delete command. The # Windows, which doesn't have a recursive delete command. The
...@@ -362,14 +340,8 @@ class WalkTests(unittest.TestCase): ...@@ -362,14 +340,8 @@ class WalkTests(unittest.TestCase):
for name in files: for name in files:
os.remove(join(root, name)) os.remove(join(root, name))
for name in dirs: for name in dirs:
dirname = join(root, name) os.rmdir(join(root, name))
if not os.path.islink(dirname):
os.rmdir(dirname)
else:
os.remove(dirname)
os.rmdir(test_support.TESTFN) os.rmdir(test_support.TESTFN)
os.unlink(tmp4_path)
os.rmdir(t2_path)
class MakedirTests (unittest.TestCase): class MakedirTests (unittest.TestCase):
def setUp(self): def setUp(self):
......
...@@ -189,10 +189,6 @@ Library ...@@ -189,10 +189,6 @@ Library
- Patch #1630118: add a SpooledTemporaryFile class to tempfile.py. - Patch #1630118: add a SpooledTemporaryFile class to tempfile.py.
- Patch #1273829: os.walk() now has a "followlinks" parameter. If set to
True (which is not the default), it visits symlinks pointing to
directories.
- Bug #1681228: the webbrowser module now correctly uses the default - Bug #1681228: the webbrowser module now correctly uses the default
GNOME or KDE browser, depending on whether there is a session of one GNOME or KDE browser, depending on whether there is a session of one
of those present. Also, it tries the Windows default browser before of those present. Also, it tries the Windows default browser before
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment