diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-03-29 11:38:22 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-03-29 11:38:22 (GMT) |
commit | 06ddd35f5f88fb22d1378dc8fb7bc6d87d0d05a6 (patch) | |
tree | a016506e906231b3ce2a59004e56c5b7420d4493 | |
parent | 8ba2083e0e614a1bca0a12aa61e8a55389a1220f (diff) | |
download | cpython-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.py | 38 |
1 files changed, 36 insertions, 2 deletions
@@ -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 |