Kaydet (Commit) 5f6a0b4e authored tarafından Serhiy Storchaka's avatar Serhiy Storchaka

Issue #25911: Restored support of bytes paths in os.walk() on Windows.

üst 44391481
...@@ -363,9 +363,12 @@ def walk(top, topdown=True, onerror=None, followlinks=False): ...@@ -363,9 +363,12 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
# minor reason when (say) a thousand readable directories are still # minor reason when (say) a thousand readable directories are still
# left to visit. That logic is copied here. # left to visit. That logic is copied here.
try: try:
# Note that scandir is global in this module due if name == 'nt' and isinstance(top, bytes):
# to earlier import-*. scandir_it = _dummy_scandir(top)
scandir_it = scandir(top) else:
# Note that scandir is global in this module due
# to earlier import-*.
scandir_it = scandir(top)
except OSError as error: except OSError as error:
if onerror is not None: if onerror is not None:
onerror(error) onerror(error)
...@@ -418,8 +421,8 @@ def walk(top, topdown=True, onerror=None, followlinks=False): ...@@ -418,8 +421,8 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
# Recurse into sub-directories # Recurse into sub-directories
islink, join = path.islink, path.join islink, join = path.islink, path.join
for name in dirs: for dirname in dirs:
new_path = join(top, name) new_path = join(top, dirname)
# Issue #23605: os.path.islink() is used instead of caching # Issue #23605: os.path.islink() is used instead of caching
# entry.is_symlink() result during the loop on os.scandir() because # entry.is_symlink() result during the loop on os.scandir() because
# the caller can replace the directory entry during the "yield" # the caller can replace the directory entry during the "yield"
...@@ -430,6 +433,20 @@ def walk(top, topdown=True, onerror=None, followlinks=False): ...@@ -430,6 +433,20 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
# Yield after recursion if going bottom up # Yield after recursion if going bottom up
yield top, dirs, nondirs 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") __all__.append("walk")
if {open, stat} <= supports_dir_fd and {listdir, stat} <= supports_fd: if {open, stat} <= supports_dir_fd and {listdir, stat} <= supports_fd:
......
...@@ -791,10 +791,10 @@ class WalkTests(unittest.TestCase): ...@@ -791,10 +791,10 @@ class WalkTests(unittest.TestCase):
# Wrapper to hide minor differences between os.walk and os.fwalk # Wrapper to hide minor differences between os.walk and os.fwalk
# to tests both functions with the same code base # to tests both functions with the same code base
def walk(self, directory, **kwargs): def walk(self, top, **kwargs):
if 'follow_symlinks' in kwargs: if 'follow_symlinks' in kwargs:
kwargs['followlinks'] = kwargs.pop('follow_symlinks') kwargs['followlinks'] = kwargs.pop('follow_symlinks')
return os.walk(directory, **kwargs) return os.walk(top, **kwargs)
def setUp(self): def setUp(self):
join = os.path.join join = os.path.join
...@@ -945,11 +945,10 @@ class WalkTests(unittest.TestCase): ...@@ -945,11 +945,10 @@ class WalkTests(unittest.TestCase):
class FwalkTests(WalkTests): class FwalkTests(WalkTests):
"""Tests for os.fwalk().""" """Tests for os.fwalk()."""
def walk(self, directory, **kwargs): def walk(self, top, **kwargs):
for root, dirs, files, root_fd in os.fwalk(directory, **kwargs): for root, dirs, files, root_fd in os.fwalk(top, **kwargs):
yield (root, dirs, files) yield (root, dirs, files)
def _compare_to_walk(self, walk_kwargs, fwalk_kwargs): def _compare_to_walk(self, walk_kwargs, fwalk_kwargs):
""" """
compare with walk() results. compare with walk() results.
...@@ -1020,6 +1019,19 @@ class FwalkTests(WalkTests): ...@@ -1020,6 +1019,19 @@ class FwalkTests(WalkTests):
os.unlink(name, dir_fd=rootfd) os.unlink(name, dir_fd=rootfd)
os.rmdir(support.TESTFN) 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): class MakedirTests(unittest.TestCase):
def setUp(self): def setUp(self):
......
...@@ -73,6 +73,8 @@ Core and Builtins ...@@ -73,6 +73,8 @@ Core and Builtins
Library 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 - Issue #26045: Add UTF-8 suggestion to error message when posting a
non-Latin-1 string with http.client. non-Latin-1 string with http.client.
......
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