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
21 changes: 6 additions & 15 deletions crates/vm/src/stdlib/_operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub(crate) use _operator::module_def;
mod _operator {
use crate::{
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
builtins::{PyInt, PyIntRef, PyStr, PyStrRef, PyTupleRef, PyType, PyTypeRef, PyUtf8StrRef},
builtins::{PyIntRef, PyStr, PyStrRef, PyTupleRef, PyType, PyTypeRef, PyUtf8StrRef},
class::PyClassDef,
common::wtf8::{Wtf8, Wtf8Buf},
function::{ArgBytesLike, ArgumentError, Either, FromArgs, FuncArgs, Param},
Expand Down Expand Up @@ -223,25 +223,16 @@ mod _operator {
struct LengthHintArgs {
#[pyarg(positional)]
obj: PyObjectRef,
// The value is checked as an exact int.
#[pyarg(positional, default = 0)]
default: PyObjectRef,
default: isize,
}

#[pyfunction]
fn length_hint(args: LengthHintArgs, vm: &VirtualMachine) -> PyResult<usize> {
fn length_hint(args: LengthHintArgs, vm: &VirtualMachine) -> PyResult<isize> {
let LengthHintArgs { obj, default } = args;
if !default.fast_isinstance(vm.ctx.types.int_type) {
return Err(vm.new_type_error(format!(
"'{}' object cannot be interpreted as an integer",
default.class().name()
)));
}
let default: usize = default
.downcast_ref::<PyInt>()
.unwrap()
.try_to_primitive(vm)?;
obj.length_hint(default, vm)
Ok(vm
.length_hint_opt(obj)?
.map_or(default, |hint| hint as isize))
}

// Inplace Operators
Expand Down
25 changes: 25 additions & 0 deletions extra_tests/snippets/stdlib_operator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import _operator

from testutils import assert_raises

assert _operator._compare_digest("abcdef", "abcdef")
assert not _operator._compare_digest("abcdef", "abc")
assert not _operator._compare_digest("abc", "abcdef")
Expand Down Expand Up @@ -31,3 +33,26 @@ class Name(str):


check_operator_reference_cycles()


class Index:
def __index__(self):
return 5


class RaisingIndex:
def __index__(self):
raise ZeroDivisionError


class TupleHint:
def __length_hint__(self):
return ()


assert _operator.length_hint(object(), Index()) == 5

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep test-file edits within the permitted changes

The root AGENTS.md explicitly limits test-file modifications to adding/removing @unittest.expectedFailure decorators and removing associated TODO comments. These new assertions and supporting classes fall outside that allowance. Keep the Rust fix, but remove the added snippet changes unless an explicit exception to the repository policy is approved.

AGENTS.md reference: AGENTS.md:L280-L282

Useful? React with 👍 / 👎.

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.

That section covers the CPython tests in Lib/test. For extra_tests/snippets, AGENTS.md asks for new tests in the most closely related existing file (L119-L120), which is what this does.

assert_raises(ZeroDivisionError, _operator.length_hint, [], RaisingIndex())
assert _operator.length_hint(object(), -1) == -1
assert _operator.length_hint([], -1) == 0
assert_raises(TypeError, _operator.length_hint, TupleHint(), -1)
assert_raises(OverflowError, _operator.length_hint, object(), -(2**70))
Loading