Skip to content

Commit 207a456

Browse files
committed
scandir/lstat
1 parent abfd148 commit 207a456

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

Lib/test/test_os.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4834,7 +4834,6 @@ class PathTConverterTests(unittest.TestCase):
48344834
('open', False, (os.O_RDONLY,), getattr(os, 'close', None)),
48354835
]
48364836

4837-
@unittest.expectedFailure # TODO: RUSTPYTHON; (AssertionError: TypeError not raised)
48384837
def test_path_t_converter(self):
48394838
str_filename = os_helper.TESTFN
48404839
if os.name == 'nt':
@@ -5109,7 +5108,6 @@ def test_fspath_protocol_bytes(self):
51095108
self.assertEqual(fspath,
51105109
os.path.join(os.fsencode(self.path),bytes_filename))
51115110

5112-
@unittest.expectedFailureIfWindows('TODO: RUSTPYTHON; entry.is_dir() is False')
51135111
def test_removed_dir(self):
51145112
path = os.path.join(self.path, 'dir')
51155113

@@ -5132,7 +5130,6 @@ def test_removed_dir(self):
51325130
self.assertRaises(FileNotFoundError, entry.stat)
51335131
self.assertRaises(FileNotFoundError, entry.stat, follow_symlinks=False)
51345132

5135-
@unittest.expectedFailureIfWindows('TODO: RUSTPYTHON; entry.is_file() is False')
51365133
def test_removed_file(self):
51375134
entry = self.create_file_entry()
51385135
os.unlink(entry.path)

crates/vm/src/stdlib/os.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -720,13 +720,32 @@ pub(super) mod _os {
720720
#[cfg(not(unix))]
721721
let ino = None;
722722

723+
let pathval = entry.path();
724+
725+
// On Windows, pre-cache lstat from directory entry metadata
726+
// This allows stat() to return cached data even if file is removed
727+
#[cfg(windows)]
728+
let lstat = {
729+
let cell = OnceCell::new();
730+
if let Ok(stat_struct) =
731+
crate::windows::win32_xstat(pathval.as_os_str(), false)
732+
{
733+
let stat_obj =
734+
StatResultData::from_stat(&stat_struct, vm).to_pyobject(vm);
735+
let _ = cell.set(stat_obj);
736+
}
737+
cell
738+
};
739+
#[cfg(not(windows))]
740+
let lstat = OnceCell::new();
741+
723742
Ok(PyIterReturn::Return(
724743
DirEntry {
725744
file_name: entry.file_name(),
726-
pathval: entry.path(),
745+
pathval,
727746
file_type: entry.file_type(),
728747
mode: zelf.mode,
729-
lstat: OnceCell::new(),
748+
lstat,
730749
stat: OnceCell::new(),
731750
ino: AtomicCell::new(ino),
732751
}
@@ -974,11 +993,11 @@ pub(super) mod _os {
974993

975994
#[pyfunction]
976995
fn lstat(
977-
file: OsPathOrFd<'_>,
996+
file: OsPath,
978997
dir_fd: DirFd<'_, { STAT_DIR_FD as usize }>,
979998
vm: &VirtualMachine,
980999
) -> PyResult {
981-
stat(file, dir_fd, FollowSymlinks(false), vm)
1000+
stat(file.into(), dir_fd, FollowSymlinks(false), vm)
9821001
}
9831002

9841003
fn curdir_inner(vm: &VirtualMachine) -> PyResult<PathBuf> {

0 commit comments

Comments
 (0)