From a548eda50a19629d0129cd6951780aeb3b755372 Mon Sep 17 00:00:00 2001 From: mrbean-bremen Date: Tue, 20 Aug 2024 19:24:35 +0200 Subject: [PATCH] Allow removing entries while iterating over scandir results --- CHANGES.md | 3 +++ pyfakefs/fake_scandir.py | 2 +- pyfakefs/tests/fake_os_test.py | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 23452efd..038457ac 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,9 @@ The released versions correspond to PyPI releases. * added support for `os.fchmod`, allow file descriptor argument for `os.chmod` only for POSIX for Python < 3.13 +### Fixes +* removing files while iterating over `scandir` results is now possible (see [#1051](../../issues/1051)) + ## [Version 5.6.0](https://pypi.python.org/pypi/pyfakefs/5.6.0) (2024-07-12) Adds preliminary Python 3.13 support. diff --git a/pyfakefs/fake_scandir.py b/pyfakefs/fake_scandir.py index 443c259e..fff25388 100644 --- a/pyfakefs/fake_scandir.py +++ b/pyfakefs/fake_scandir.py @@ -138,7 +138,7 @@ def __init__(self, filesystem, path): self.abspath = self.filesystem.absnormpath(path) self.path = to_string(path) entries = self.filesystem.confirmdir(self.abspath, check_exe_perm=False).entries - self.entry_iter = iter(entries) + self.entry_iter = iter(tuple(entries)) def __iter__(self): return self diff --git a/pyfakefs/tests/fake_os_test.py b/pyfakefs/tests/fake_os_test.py index 10c608eb..a110207e 100644 --- a/pyfakefs/tests/fake_os_test.py +++ b/pyfakefs/tests/fake_os_test.py @@ -5452,6 +5452,20 @@ def test_scandir_with_fd(self): children = [dir_entry.name for dir_entry in self.os.scandir(fd)] assert sorted(children) == ["file1", "file2", "subdir"] + def test_file_removed_during_scandir(self): + # regression test for #1051 + dir_path = self.make_path("wls") + file1_path = self.os.path.join(dir_path, "1.log") + self.create_file(file1_path) + file2_path = self.os.path.join(dir_path, "2.log") + self.create_file(file2_path) + with self.os.scandir(dir_path) as it: + for entry in it: + if entry.is_file(): + self.os.remove(entry.path) + assert not self.os.path.exists(file1_path) + assert not self.os.path.exists(file2_path) + def check_stat( self, absolute_symlink_expected_size, relative_symlink_expected_size ):