8000 Fix shutil test_copy_dir · RustPython/RustPython@5c527c2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5c527c2

Browse files
committed
Fix shutil test_copy_dir
1 parent 41979f0 commit 5c527c2

File tree

8 files changed

+93
-39
lines changed

8 files changed

+93
-39
lines changed

Lib/test/test_fileio.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -381,9 +381,6 @@ def testMethods(self):
381381
def testOpenDirFD(self):
382382
super().testOpenDirFD()
383383

384-
@unittest.expectedFailureIf(sys.platform != "win32", "TODO: RUSTPYTHON")
385-
def testOpendir(self):
386-
super().testOpendir()
387384

388385
@unittest.skipIf(sys.platform == "win32", "TODO: RUSTPYTHON, test setUp errors on Windows")
389386
class PyAutoFileTests(AutoFileTests, unittest.TestCase):
@@ -617,11 +614,6 @@ class COtherFileTests(OtherFileTests, unittest.TestCase):
617614
FileIO = _io.FileIO
618615
modulename = '_io'
619616

620-
# TODO: RUSTPYTHON
621-
@unittest.expectedFailure
622-
def testInvalidFd(self):
623-
super().testInvalidFd()
624-
625617
# TODO: RUSTPYTHON
626618
@unittest.expectedFailure
627619
def testUnclosedFDOnException(self):

Lib/test/test_pathlib.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2467,8 +2467,6 @@ def _check_symlink_loop(self, *args, strict=True):
24672467
with self.assertRaises(RuntimeError):
24682468
print(path.resolve(strict))
24692469

2470-
# TODO: RUSTPYTHON
2471-
@unittest.expectedFailure
24722470
def test_open_mode(self):
24732471
old_mask = os.umask(0)
24742472
self.addCleanup(os.umask, old_mask)

Lib/test/test_shutil.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,13 +1408,9 @@ def test_copy_return_value(self):
14081408
rv = fn(src, os.path.join(dst_dir, 'bar'))
14091409
self.assertEqual(rv, os.path.join(dst_dir, 'bar'))
14101410

1411-
# TODO: RUSTPYTHON
1412-
@unittest.expectedFailure
14131411
def test_copy_dir(self):
14141412
self._test_copy_dir(shutil.copy)
14151413

1416-
# TODO: RUSTPYTHON
1417-
@unittest.expectedFailure
14181414
def test_copy2_dir(self):
14191415
self._test_copy_dir(shutil.copy2)
14201416

@@ -1546,8 +1542,6 @@ def test_copyfile_nonexistent_dir(self):
15461542
write_file(src_file, 'foo')
15471543
self.assertRaises(FileNotFoundError, shutil.copyfile, src_file, dst)
15481544

1549-
# TODO: RUSTPYTHON
1550-
@unittest.expectedFailure
15511545
def test_copyfile_copy_dir(self):
15521546
# Issue 45234
15531547
# test copy() and copyfile() raising proper exceptions when src and/or

Lib/test/test_zipapp.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,6 @@ def test_shebang_is_executable(self):
310310
zipapp.create_archive(str(source), str(target), interpreter='python')
311311
self.assertTrue(target.stat().st_mode & stat.S_IEXEC)
312312

313-
# TODO: RUSTPYTHON
314-
@unittest.expectedFailure
315313
@unittest.skipIf(sys.platform == 'win32',
316314
'Windows does not support an executable bit')
317315
def test_no_shebang_is_not_executable(self):

vm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ features = [
127127
"Win32_Storage_FileSystem",
128128
"Win32_System_Console",
129129
"Win32_System_Diagnostics_Debug",
130+
"Win32_System_Environment",
130131
"Win32_System_LibraryLoader",
131132
"Win32_System_Memory",
132133
"Win32_System_Performance",

vm/src/fileutils.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ pub use libc::stat as StatStruct;
55
#[cfg(windows)]
66
pub use windows::{fstat, StatStruct};
77

8+
#[cfg(not(windows))]
9+
pub fn fstat(fd: libc::c_int) -> std::io::Result<StatStruct> {
10+
let mut stat = std::mem::MaybeUninit::uninit();
11+
unsafe {
12+
let ret = libc::fstat(fd, stat.as_mut_ptr());
13+
if ret == -1 {
14+
Err(crate::common::os::last_os_error())
15+
} else {
16+
Ok(stat.assume_init())
17+
}
18+
}
19+
}
20+
821
#[cfg(windows)]
922
mod windows {
1023
use crate::common::suppress_iph;

vm/src/stdlib/io.rs

Lines changed: 79 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3395,17 +3395,20 @@ mod _io {
33953395
}
33963396

33973397
#[repr(u8)]
3398+
#[derive(Debug)]
33983399
enum FileMode {
33993400
Read = b'r',
34003401
Write = b'w',
34013402
Exclusive = b'x',
34023403
Append = b'a',
34033404
}
34043405
#[repr(u8)]
3406+
#[derive(Debug)]
34053407
enum EncodeMode {
34063408
Text = b't',
34073409
Bytes = b'b',
34083410
}
3411+
#[derive(Debug)]
34093412
struct Mode {
34103413
file: FileMode,
34113414
encode: EncodeMode,
@@ -3734,6 +3737,7 @@ mod fileio {
37343737
common::crt_fd::Fd,
37353738
convert::ToPyException,
37363739
function::{ArgBytesLike, ArgMemoryBuffer, OptionalArg, OptionalOption},
3740+
ospath::{IOErrorBuilder, OsPath, OsPathOrFd},
37373741
stdlib::os,
37383742
types::{DefaultConstructor, Initializer, Representable},
37393743
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, VirtualMachine,
@@ -3867,7 +3871,7 @@ mod fileio {
38673871
fn default() -> Self {
38683872
Self {
38693873
fd: AtomicCell::new(-1),
3870-
closefd: AtomicCell::new(false),
3874+
closefd: AtomicCell::new(true),
38713875
mode: AtomicCell::new(Mode::empty()),
38723876
seekable: AtomicCell::new(None),
38733877
}
@@ -3880,45 +3884,100 @@ mod fileio {
38803884
type Args = FileIOArgs;
38813885

38823886
fn init(zelf: PyRef<Self>, args: Self::Args, vm: &VirtualMachine) -> PyResult<()> {
3887+
// TODO: let atomic_flag_works
3888+
let name = args.name;
3889+
let arg_fd = if let Some(i) = name.payload::<crate::builtins::PyInt>() {
3890+
let fd = i.try_to_primitive(vm)?;
3891+
if fd < 0 {
3892+
return Err(vm.new_value_error("negative file descriptor".to_owned()));
3893+
}
3894+
Some(fd)
3895+
} else {
3896+
None
3897+
};
3898+
38833899
let mode_obj = args
38843900
.mode
38853901
.unwrap_or_else(|| PyStr::from("rb").into_ref(&vm.ctx));
38863902
let mode_str = mode_obj.as_str();
3887-
let name = args.name;
38883903
let (mode, flags) =
38893904
compute_mode(mode_str).map_err(|e| vm.new_value_error(e.error_msg(mode_str)))?;
38903905
zelf.mode.store(mode);
3891-
let fd = if let Some(opener) = args.opener {
3892-
let fd = opener.call((name.clone(), flags), vm)?;
3893-
if !fd.fast_isinstance(vm.ctx.types.int_type) {
3894-
return Err(vm.new_type_error("expected integer from opener".to_owned()));
3895-
}
3896-
let fd = i32::try_from_object(vm, fd)?;
3897-
if fd < 0 {
3898-
return Err(vm.new_value_error(format!("opener returned {fd}")));
3899-
}
3900-
fd
3901-
} else if let Some(i) = name.payload::<crate::builtins::PyInt>() {
3902-
i.try_to_primitive(vm)?
3906+
3907+
let (fd, filename) = if let Some(fd) = arg_fd {
3908+
zelf.closefd.store(args.closefd);
3909+
(fd, OsPathOrFd::Fd(fd))
39033910
} else {
3904-
let path = crate::ospath::OsPath::try_from_object(vm, name.clone())?;
3911+
zelf.closefd.store(true);
39053912
if !args.closefd {
39063913
return Err(
39073914
vm.new_value_error("Cannot use closefd=False with file name".to_owned())
39083915
);
39093916
}
3910-
os::open(path, flags as _, None, Default::default(), vm)?
3917+
3918+
if let Some(opener) = args.opener {
3919+
let fd = opener.call((name.clone(), flags), vm)?;
3920+
if !fd.fast_isinstance(vm.ctx.types.int_type) {
3921+
return Err(vm.new_type_error("expected integer from opener".to_owned()));
3922+
}
3923+
let fd = i32::try_from_object(vm, fd)?;
3924+
if fd < 0 {
3925+
return Err(vm.new_value_error(format!("opener returned {fd}")));
3926+
}
3927+
(
3928+
fd,
3929+
OsPathOrFd::try_from_object(vm, name.clone()).unwrap_or(OsPathOrFd::Fd(fd)),
3930+
)
3931+
} else {
3932+
let path = OsPath::try_from_object(vm, name.clone())?;
3933+
#[cfg(any(unix, target_os = "wasi"))]
3934+
let fd = Fd::open(&path.clone().into_cstring(vm)?, flags, 0o666);
3935+
#[cfg(windows)]
3936+
let fd = Fd::wopen(&path.to_widecstring(vm)?, flags, 0o666);
3937+
let filename = OsPathOrFd::Path(path);
3938+
match fd {
3939+
Ok(fd) => (fd.0, filename),
3940+
Err(e) => return Err(IOErrorBuilder::with_filename(&e, filename, vm)),
3941+
}
3942+
}
39113943
};
3944+
zelf.fd.store(fd);
39123945

3913-
if mode.contains(Mode::APPENDING) {
3914-
let _ = os::lseek(fd as _, 0, libc::SEEK_END, vm);
3946+
// TODO: _Py_set_inheritable
3947+
3948+
let fd_fstat = crate::fileutils::fstat(fd);
3949+
3950+
#[cfg(windows)]
3951+
{
3952+
if let Err(err) = fd_fstat {
3953+
return Err(IOErrorBuilder::with_filename(&err, filename, vm));
3954+
}
3955+
}
3956+
#[cfg(any(unix, target_os = "wasi"))]
3957+
{
3958+
match fd_fstat {
3959+
Ok(status) => {
3960+
if (status.st_mode & libc::S_IFMT) == libc::S_IFDIR {
3961+
let err = std::io::Error::from_raw_os_error(libc::EISDIR);
3962+
return Err(IOErrorBuilder::with_filename(&err, filename, vm));
3963+
102D2 }
3964+
}
3965+
Err(err) => {
3966+
if err.raw_os_error() == Some(libc::EBADF) {
3967+
return Err(IOErrorBuilder::with_filename(&err, filename, vm));
3968+
}
3969+
}
3970+
}
39153971
}
39163972

3917-
zelf.fd.store(fd);
3918-
zelf.closefd.store(args.closefd);
39193973
#[cfg(windows)]
39203974
crate::stdlib::msvcrt::setmode_binary(fd);
39213975
zelf.as_object().set_attr("name", name, vm)?;
3976+
3977+
if mode.contains(Mode::APPENDING) {
3978+
let _ = os::lseek(fd as _, 0, libc::SEEK_END, vm);
3979+
}
3980+
39223981
Ok(())
39233982
}
39243983
}

vm/src/stdlib/os.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1566,7 +1566,6 @@ pub fn extend_module(vm: &VirtualMachine, module: &Py<PyModule>) {
15661566
"error" => vm.ctx.exceptions.os_error.to_owned(),
15671567
});
15681568
}
1569-
pub(crate) use _os::os_open as open;
15701569

15711570
#[cfg(not(windows))]
15721571
use super::posix as platform;

0 commit comments

Comments
 (0)
0