Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion Lib/test/test_grp.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ def test_values_extended(self):
# Discovered on Ubuntu 5.04 (custom).
self.assertEqual(e2.gr_name.lower(), name.lower())

@unittest.expectedFailure # TODO: RUSTPYTHON; KeyError: 'getgrgid: group id 340282366920938463463374607431768211456 not found'
def test_errors(self):
self.assertRaises(TypeError, grp.getgrgid)
self.assertRaises(TypeError, grp.getgrgid, 3.14)
Expand Down
53 changes: 38 additions & 15 deletions crates/stdlib/src/grp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ pub(crate) use grp::module_def;
#[pymodule]
mod grp {
use crate::vm::{
PyObjectRef, PyResult, VirtualMachine,
AsObject, PyObjectRef, PyResult, VirtualMachine,
builtins::{PyListRef, PyUtf8StrRef},
convert::ToPyObject,
convert::{ToPyObject, TryFromObject},
exceptions,
function::ArgIndex,
types::PyStructSequence,
Expand Down Expand Up @@ -45,23 +45,46 @@ mod grp {
#[derive(FromArgs)]
struct GetGrGidArgs {
#[pyarg(any)]
id: ArgIndex,
id: PyObjectRef,
}

#[pyfunction]
fn getgrgid(id: GetGrGidArgs, vm: &VirtualMachine) -> PyResult<GroupData> {
let gid = id.id.into_int_ref();
let gr_gid = gid.as_bigint();
let gid = host_grp::gid_t::try_from(gr_gid).ok();
let group = gid
.and_then(|gid| host_grp::getgrgid(gid).ok().flatten())
.ok_or_else(|| {
vm.new_key_error(
vm.ctx
.new_str(format!("getgrgid: group id {gr_gid} not found"))
.into(),
)
})?;
let index = ArgIndex::try_from_object(vm, id.id.clone()).map_err(|_| {
let name = id.id.class().slot_name().to_string();
let name = &name[..name.floor_char_boundary(200.min(name.len()))];
vm.new_type_error(format!("gid should be integer, not {name}"))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we must be able to override this using ArgIndex now. pls check other error messages if this is necessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to the existing ArgIndex::try_from_object path in 29ced2896d, without adding a new converter API.

The call-site error override is still needed: CPython's _Py_Gid_Converter deliberately replaces every _PyNumber_Index failure, including exceptions raised by __index__, with TypeError("gid should be integer, not <type>"). The current #[pyarg(error_msg = ...)] supports only a fixed string, so it cannot preserve this type-dependent diagnostic. Both overflow messages and the normalized-gid KeyError were also checked against that implementation and remain unchanged.

Scoped Cargo check and strict Clippy passed, along with normal commit hooks. NSS was not invoked locally; the canonical test_grp coverage is left to the new-head CI.

})?;
let index = index.into_int_ref();
let value = index.as_bigint();
// Match CPython's _Py_Gid_Converter, including the -1 sentinel and
// the different overflow paths before and after signed-long conversion.
let gid = if let Ok(value) = libc::c_long::try_from(value) {
if value == -1 {
-1_i32 as host_grp::gid_t
} else {
if value < 0 {
return Err(vm.new_overflow_error("gid is less than minimum"));
}
host_grp::gid_t::try_from(value)
.map_err(|_| vm.new_overflow_error("gid is less than minimum"))?
}
} else if value < &0.into() {
return Err(vm.new_overflow_error("gid is less than minimum"));
} else {
libc::c_ulong::try_from(value)
.ok()
.and_then(|value| host_grp::gid_t::try_from(value).ok())
.filter(|&gid| gid != -1_i32 as host_grp::gid_t)
.ok_or_else(|| vm.new_overflow_error("gid is greater than maximum"))?
};
let group = host_grp::getgrgid(gid).ok().flatten().ok_or_else(|| {
vm.new_key_error(
vm.ctx
.new_str(format!("getgrgid(): gid not found: {gid}"))
.into(),
)
})?;
Ok(GroupData::from_group(group, vm))
}

Expand Down
Loading