Skip to content

Commit 621be14

Browse files
youknowdotcodex
andauthored
Match CPython group id conversion and update grp tests (#9462)
* Match CPython group id conversion and update grp tests Assisted-by: OpenAI Codex: model version unavailable * Use ArgIndex for group id conversion Preserve CPython-specific gid index failure diagnostics through the existing argument converter. Assisted-by: OpenAI Codex: model version unavailable --------- Co-authored-by: Codex <codex@openai.com>
1 parent a838216 commit 621be14

2 files changed

Lines changed: 38 additions & 16 deletions

File tree

‎Lib/test/test_grp.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ def test_values_extended(self):
4949
# Discovered on Ubuntu 5.04 (custom).
5050
self.assertEqual(e2.gr_name.lower(), name.lower())
5151

52-
@unittest.expectedFailure # TODO: RUSTPYTHON; KeyError: 'getgrgid: group id 340282366920938463463374607431768211456 not found'
5352
def test_errors(self):
5453
self.assertRaises(TypeError, grp.getgrgid)
5554
self.assertRaises(TypeError, grp.getgrgid, 3.14)

‎crates/stdlib/src/grp.rs‎

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ pub(crate) use grp::module_def;
44
#[pymodule]
55
mod grp {
66
use crate::vm::{
7-
PyObjectRef, PyResult, VirtualMachine,
7+
AsObject, PyObjectRef, PyResult, VirtualMachine,
88
builtins::{PyListRef, PyUtf8StrRef},
9-
convert::ToPyObject,
9+
convert::{ToPyObject, TryFromObject},
1010
exceptions,
1111
function::ArgIndex,
1212
types::PyStructSequence,
@@ -45,23 +45,46 @@ mod grp {
4545
#[derive(FromArgs)]
4646
struct GetGrGidArgs {
4747
#[pyarg(any)]
48-
id: ArgIndex,
48+
id: PyObjectRef,
4949
}
5050

5151
#[pyfunction]
5252
fn getgrgid(id: GetGrGidArgs, vm: &VirtualMachine) -> PyResult<GroupData> {
53-
let gid = id.id.into_int_ref();
54-
let gr_gid = gid.as_bigint();
55-
let gid = host_grp::gid_t::try_from(gr_gid).ok();
56-
let group = gid
57-
.and_then(|gid| host_grp::getgrgid(gid).ok().flatten())
58-
.ok_or_else(|| {
59-
vm.new_key_error(
60-
vm.ctx
61-
.new_str(format!("getgrgid: group id {gr_gid} not found"))
62-
.into(),
63-
)
64-
})?;
53+
let index = ArgIndex::try_from_object(vm, id.id.clone()).map_err(|_| {
54+
let name = id.id.class().slot_name().to_string();
55+
let name = &name[..name.floor_char_boundary(200.min(name.len()))];
56+
vm.new_type_error(format!("gid should be integer, not {name}"))
57+
})?;
58+
let index = index.into_int_ref();
59+
let value = index.as_bigint();
60+
// Match CPython's _Py_Gid_Converter, including the -1 sentinel and
61+
// the different overflow paths before and after signed-long conversion.
62+
let gid = if let Ok(value) = libc::c_long::try_from(value) {
63+
if value == -1 {
64+
-1_i32 as host_grp::gid_t
65+
} else {
66+
if value < 0 {
67+
return Err(vm.new_overflow_error("gid is less than minimum"));
68+
}
69+
host_grp::gid_t::try_from(value)
70+
.map_err(|_| vm.new_overflow_error("gid is less than minimum"))?
71+
}
72+
} else if value < &0.into() {
73+
return Err(vm.new_overflow_error("gid is less than minimum"));
74+
} else {
75+
libc::c_ulong::try_from(value)
76+
.ok()
77+
.and_then(|value| host_grp::gid_t::try_from(value).ok())
78+
.filter(|&gid| gid != -1_i32 as host_grp::gid_t)
79+
.ok_or_else(|| vm.new_overflow_error("gid is greater than maximum"))?
80+
};
81+
let group = host_grp::getgrgid(gid).ok().flatten().ok_or_else(|| {
82+
vm.new_key_error(
83+
vm.ctx
84+
.new_str(format!("getgrgid(): gid not found: {gid}"))
85+
.into(),
86+
)
87+
})?;
6588
Ok(GroupData::from_group(group, vm))
6689
}
6790

0 commit comments

Comments
 (0)