Skip to content

Commit ab6114d

Browse files
authored
Merge pull request #6942 from youknowone/os-fix
posix.link, termios.error, warn() error, closefd=False for std in/out
2 parents 019e754 + 1132f66 commit ab6114d

5 files changed

Lines changed: 65 additions & 14 deletions

File tree

Lib/test/test_os.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2350,7 +2350,6 @@ def check_bool(self, f, *args, **kwargs):
23502350
with self.assertRaises(RuntimeWarning):
23512351
f(fd, *args, **kwargs)
23522352

2353-
@unittest.expectedFailure # TODO: RUSTPYTHON
23542353
def test_fdopen(self):
23552354
self.check(os.fdopen, encoding="utf-8")
23562355
self.check_bool(os.fdopen, encoding="utf-8")

crates/stdlib/src/termios.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,13 +261,12 @@ mod termios {
261261
}
262262

263263
fn termios_error(err: std::io::Error, vm: &VirtualMachine) -> PyBaseExceptionRef {
264-
vm.new_exception(
264+
vm.new_os_subtype_error(
265265
error_type(vm),
266-
vec![
267-
err.posix_errno().to_pyobject(vm),
268-
vm.ctx.new_str(err.to_string()).into(),
269-
],
266+
Some(err.posix_errno()),
267+
vm.ctx.new_str(err.to_string()),
270268
)
269+
.upcast()
271270
}
272271

273272
#[pyattr(name = "error", once)]

crates/vm/src/stdlib/os.rs

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,13 +1268,64 @@ pub(super) mod _os {
12681268
}
12691269

12701270
#[pyfunction]
1271-
fn link(src: OsPath, dst: OsPath, vm: &VirtualMachine) -> PyResult<()> {
1272-
fs::hard_link(&src.path, &dst.path).map_err(|err| {
1273-
let builder = err.to_os_error_builder(vm);
1274-
let builder = builder.filename(src.filename(vm));
1275-
let builder = builder.filename2(dst.filename(vm));
1276-
builder.build(vm).upcast()
1277-
})
1271+
fn link(
1272+
src: OsPath,
1273+
dst: OsPath,
1274+
follow_symlinks: FollowSymlinks,
1275+
vm: &VirtualMachine,
1276+
) -> PyResult<()> {
1277+
#[cfg(unix)]
1278+
{
1279+
use std::os::unix::ffi::OsStrExt;
1280+
let src_cstr = std::ffi::CString::new(src.path.as_os_str().as_bytes())
1281+
.map_err(|_| vm.new_value_error("embedded null byte"))?;
1282+
let dst_cstr = std::ffi::CString::new(dst.path.as_os_str().as_bytes())
1283+
.map_err(|_| vm.new_value_error("embedded null byte"))?;
1284+
1285+
let flags = if follow_symlinks.0 {
1286+
libc::AT_SYMLINK_FOLLOW
1287+
} else {
1288+
0
1289+
};
1290+
1291+
let ret = unsafe {
1292+
libc::linkat(
1293+
libc::AT_FDCWD,
1294+
src_cstr.as_ptr(),
1295+
libc::AT_FDCWD,
1296+
dst_cstr.as_ptr(),
1297+
flags,
1298+
)
1299+
};
1300+
1301+
if ret != 0 {
1302+
let err = std::io::Error::last_os_error();
1303+
let builder = err.to_os_error_builder(vm);
1304+
let builder = builder.filename(src.filename(vm));
1305+
let builder = builder.filename2(dst.filename(vm));
1306+
return Err(builder.build(vm).upcast());
1307+
}
1308+
1309+
Ok(())
1310+
}
1311+
1312+
#[cfg(not(unix))]
1313+
{
1314+
// On non-Unix platforms, ignore follow_symlinks if it's the default value
1315+
// or raise NotImplementedError if explicitly set to False
1316+
if !follow_symlinks.0 {
1317+
return Err(vm.new_not_implemented_error(
1318+
"link: follow_symlinks unavailable on this platform",
1319+
));
1320+
}
1321+
1322+
fs::hard_link(&src.path, &dst.path).map_err(|err| {
1323+
let builder = err.to_os_error_builder(vm);
1324+
let builder = builder.filename(src.filename(vm));
1325+
let builder = builder.filename2(dst.filename(vm));
1326+
builder.build(vm).upcast()
1327+
})
1328+
}
12781329
}
12791330

12801331
#[cfg(any(unix, windows))]
@@ -1842,6 +1893,7 @@ pub(super) mod _os {
18421893
SupportFunc::new("access", Some(false), Some(false), None),
18431894
SupportFunc::new("chdir", None, Some(false), Some(false)),
18441895
// chflags Some, None Some
1896+
SupportFunc::new("link", Some(false), Some(false), Some(cfg!(unix))),
18451897
SupportFunc::new("listdir", Some(LISTDIR_FD), Some(false), Some(false)),
18461898
SupportFunc::new("mkdir", Some(false), Some(MKDIR_DIR_FD), Some(false)),
18471899
// mkfifo Some Some None

crates/vm/src/stdlib/warnings.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub fn warn(
1212
if let Ok(module) = vm.import("warnings", 0)
1313
&& let Ok(func) = module.get_attr("warn", vm)
1414
{
15-
let _ = func.call((message, category.to_owned(), stack_level), vm);
15+
func.call((message, category.to_owned(), stack_level), vm)?;
1616
}
1717
Ok(())
1818
}

crates/vm/src/vm/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ impl VirtualMachine {
328328
Some(if write { "wb" } else { "rb" }),
329329
crate::stdlib::io::OpenArgs {
330330
buffering: if unbuffered { 0 } else { -1 },
331+
closefd: false,
331332
..Default::default()
332333
},
333334
self,

0 commit comments

Comments
 (0)