diff --git a/tests/snippets/stdlib_os.py b/tests/snippets/stdlib_os.py index df163a195..2ea052ab7 100644 --- a/tests/snippets/stdlib_os.py +++ b/tests/snippets/stdlib_os.py @@ -274,3 +274,10 @@ if "win" not in sys.platform: assert_raises(PermissionError, lambda: os.setpgid(os.getpid(), 42)) assert_raises(PermissionError, lambda: os.setuid(42)) assert_raises(PermissionError, lambda: os.seteuid(42)) + + # pty + a, b = os.openpty() + assert isinstance(a, int) + assert isinstance(b, int) + os.close(b) + os.close(a) diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index d510699c9..9f65523f3 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -5,13 +5,16 @@ use std::io::{self, ErrorKind, Read, Write}; use std::time::{Duration, SystemTime}; use std::{env, fs}; -use bitflags::bitflags; #[cfg(unix)] use nix::errno::Errno; #[cfg(unix)] +use nix::pty::openpty; +#[cfg(unix)] use nix::unistd::{self, Gid, Pid, Uid}; use num_traits::cast::ToPrimitive; +use bitflags::bitflags; + use crate::function::{IntoPyNativeFunc, PyFuncArgs}; use crate::obj::objbytes::PyBytesRef; use crate::obj::objdict::PyDictRef; @@ -849,6 +852,16 @@ fn os_seteuid(euid: PyIntRef, vm: &VirtualMachine) -> PyResult<()> { unistd::seteuid(Uid::from_raw(euid)).map_err(|err| convert_nix_error(vm, err)) } +#[cfg(unix)] +pub fn os_openpty(vm: &VirtualMachine) -> PyResult { + match openpty(None, None) { + Ok(r) => Ok(vm + .ctx + .new_tuple(vec![vm.new_int(r.master), vm.new_int(r.slave)])), + Err(err) => Err(convert_nix_error(vm, err)), + } +} + pub fn make_module(vm: &VirtualMachine) -> PyObjectRef { let ctx = &vm.ctx; @@ -1025,6 +1038,7 @@ fn extend_module_platform_specific(vm: &VirtualMachine, module: PyObjectRef) -> "setsid" => ctx.new_rustfunc(os_setsid), "setuid" => ctx.new_rustfunc(os_setuid), "seteuid" => ctx.new_rustfunc(os_seteuid), + "openpty" => ctx.new_rustfunc(os_openpty), }); module