summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-03-29 11:38:22 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2016-03-29 11:38:22 (GMT)
commit06ddd35f5f88fb22d1378dc8fb7bc6d87d0d05a6 (patch)
treea016506e906231b3ce2a59004e56c5b7420d4493
parent8ba2083e0e614a1bca0a12aa61e8a55389a1220f (diff)
downloadcpython-06ddd35f5f88fb22d1378dc8fb7bc6d87d0d05a6.zip
cpython-06ddd35f5f88fb22d1378dc8fb7bc6d87d0d05a6.tar.gz
cpython-06ddd35f5f88fb22d1378dc8fb7bc6d87d0d05a6.tar.bz2
Issue #25911: Backport os._DummyDirEntry fixes
* Fix test_os.BytesWalkTests on Windows * Mimick better the reference os.DirEntry on Windows * _DummyDirEntry now caches os.stat() result * _DummyDirEntry constructor now tries to get os.stat() * Fix os._DummyDirEntry.is_symlink(), don't follow symbolic links: use os.stat(path, follow_symlinks=False).
-rw-r--r--Lib/os.py38
1 files changed, 36 insertions, 2 deletions
diff --git a/Lib/os.py b/Lib/os.py
index e32cd6b..b4c651d 100644
--- a/Lib/os.py
+++ b/Lib/os.py
@@ -425,13 +425,47 @@ def walk(top, topdown=True, onerror=None, followlinks=False):
yield top, dirs, nondirs
class _DummyDirEntry:
+ """Dummy implementation of DirEntry
+
+ Only used internally by os.walk(bytes). Since os.walk() doesn't need the
+ follow_symlinks parameter: don't implement it, always follow symbolic
+ links.
+ """
+
def __init__(self, dir, name):
self.name = name
self.path = path.join(dir, name)
+ # Mimick FindFirstFile/FindNextFile: we should get file attributes
+ # while iterating on a directory
+ self._stat = None
+ self._lstat = None
+ try:
+ self.stat(follow_symlinks=False)
+ except OSError:
+ pass
+
+ def stat(self, *, follow_symlinks=True):
+ if follow_symlinks:
+ if self._stat is None:
+ self._stat = stat(self.path)
+ return self._stat
+ else:
+ if self._lstat is None:
+ self._lstat = stat(self.path, follow_symlinks=False)
+ return self._lstat
+
def is_dir(self):
- return path.isdir(self.path)
+ if self._lstat is not None and not self.is_symlink():
+ # use the cache lstat
+ stat = self.stat(follow_symlinks=False)
+ return st.S_ISDIR(stat.st_mode)
+
+ stat = self.stat()
+ return st.S_ISDIR(stat.st_mode)
+
def is_symlink(self):
- return path.islink(self.path)
+ stat = self.stat(follow_symlinks=False)
+ return st.S_ISLNK(stat.st_mode)
def _dummy_scandir(dir):
# listdir-based implementation for bytes patches on Windows