]> granicus.if.org Git - python/commitdiff
Issue #25911: Restored support of bytes paths in os.walk() on Windows.
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 8 Feb 2016 14:23:28 +0000 (16:23 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Mon, 8 Feb 2016 14:23:28 +0000 (16:23 +0200)
Lib/os.py
Lib/test/test_os.py
Misc/NEWS

index 13a42c331e783513c1dfc20ea521b2b388fa0e4d..674a7d7efda121d2688086fe2436ffbaf94bfde8 100644 (file)
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -363,9 +363,12 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
     # minor reason when (say) a thousand readable directories are still
     # left to visit.  That logic is copied here.
     try:
-        # Note that scandir is global in this module due
-        # to earlier import-*.
-        scandir_it = scandir(top)
+        if name == 'nt' and isinstance(top, bytes):
+            scandir_it = _dummy_scandir(top)
+        else:
+            # Note that scandir is global in this module due
+            # to earlier import-*.
+            scandir_it = scandir(top)
     except OSError as error:
         if onerror is not None:
             onerror(error)
@@ -418,8 +421,8 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
 
         # Recurse into sub-directories
         islink, join = path.islink, path.join
-        for name in dirs:
-            new_path = join(top, name)
+        for dirname in dirs:
+            new_path = join(top, dirname)
             # Issue #23605: os.path.islink() is used instead of caching
             # entry.is_symlink() result during the loop on os.scandir() because
             # the caller can replace the directory entry during the "yield"
@@ -430,6 +433,20 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
         # Yield after recursion if going bottom up
         yield top, dirs, nondirs
 
+class _DummyDirEntry:
+    def __init__(self, dir, name):
+        self.name = name
+        self.path = path.join(dir, name)
+    def is_dir(self):
+        return path.isdir(self.path)
+    def is_symlink(self):
+        return path.islink(self.path)
+
+def _dummy_scandir(dir):
+    # listdir-based implementation for bytes patches on Windows
+    for name in listdir(dir):
+        yield _DummyDirEntry(dir, name)
+
 __all__.append("walk")
 
 if {open, stat} <= supports_dir_fd and {listdir, stat} <= supports_fd:
index ade75a51ed52d1ab8ba0d846079ebcedc888a7b4..73db39c8258e915cfbc43eb9b57114b7a0d686a8 100644 (file)
@@ -791,10 +791,10 @@ class WalkTests(unittest.TestCase):
 
     # Wrapper to hide minor differences between os.walk and os.fwalk
     # to tests both functions with the same code base
-    def walk(self, directory, **kwargs):
+    def walk(self, top, **kwargs):
         if 'follow_symlinks' in kwargs:
             kwargs['followlinks'] = kwargs.pop('follow_symlinks')
-        return os.walk(directory, **kwargs)
+        return os.walk(top, **kwargs)
 
     def setUp(self):
         join = os.path.join
@@ -945,11 +945,10 @@ class WalkTests(unittest.TestCase):
 class FwalkTests(WalkTests):
     """Tests for os.fwalk()."""
 
-    def walk(self, directory, **kwargs):
-        for root, dirs, files, root_fd in os.fwalk(directory, **kwargs):
+    def walk(self, top, **kwargs):
+        for root, dirs, files, root_fd in os.fwalk(top, **kwargs):
             yield (root, dirs, files)
 
-
     def _compare_to_walk(self, walk_kwargs, fwalk_kwargs):
         """
         compare with walk() results.
@@ -1020,6 +1019,19 @@ class FwalkTests(WalkTests):
                     os.unlink(name, dir_fd=rootfd)
         os.rmdir(support.TESTFN)
 
+class BytesWalkTests(WalkTests):
+    """Tests for os.walk() with bytes."""
+    def walk(self, top, **kwargs):
+        if 'follow_symlinks' in kwargs:
+            kwargs['followlinks'] = kwargs.pop('follow_symlinks')
+        for broot, bdirs, bfiles in os.walk(os.fsencode(top), **kwargs):
+            root = os.fsdecode(broot)
+            dirs = list(map(os.fsdecode, bdirs))
+            files = list(map(os.fsdecode, bfiles))
+            yield (root, dirs, files)
+            bdirs[:] = list(map(os.fsencode, dirs))
+            bfiles[:] = list(map(os.fsencode, files))
+
 
 class MakedirTests(unittest.TestCase):
     def setUp(self):
index 29a09d756af3136287f91a54ad056ace0cc32b2a..189ea311dd3b6c43a2f20d0c87f2374fb5b0b1a4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -73,6 +73,8 @@ Core and Builtins
 Library
 -------
 
+- Issue #25911: Restored support of bytes paths in os.walk() on Windows.
+
 - Issue #26045: Add UTF-8 suggestion to error message when posting a
   non-Latin-1 string with http.client.