///|
/// Checks equality between two Python objects using the `__eq__` method
/// of the first object.
pub fn[A : PyObjectInto, B : PyObjectInto] py_equal(
sel : A,
other : B,
) -> Bool raise @py.PyRuntimeError {
let a = sel.to_py_object()
let b = other.to_py_object()
guard a.get_attr("__eq__") is Some(PyCallable(mtd)) else { false }
let args = @py.PyTuple::new(1)
args..set(0, b)
guard mtd.invoke(args~) is Some(PyBool(r)) else { false }
@py.PyBool::to_bool(r)
}
///|
test "eq int" {
assert_true(py_equal(42, 42))
assert_false(py_equal(42, 432))
assert_false(py_equal(42, "42"))
assert_true(py_equal("hello", "hello"))
}
///|
pub fn[A : PyObjectInto] invoke_unary(
sel : A,
mtd : String,
) -> @py.PyObjectEnum? raise @py.PyRuntimeError {
let obj = sel.to_py_object()
guard obj.get_attr(mtd) is Some(PyCallable(mtd)) else { None }
let args = @py.PyTuple::new(0)
mtd.invoke(args~)
}
///|
pub fn[A : PyObjectInto, B : PyObjectInto] invoke_binary(
sel : A,
other : B,
mtd : String,
) -> @py.PyObjectEnum? raise @py.PyRuntimeError {
let obj = sel.to_py_object()
guard obj.get_attr(mtd) is Some(PyCallable(mtd)) else { None }
let args = @py.PyTuple::new(1)
args.set(0, other.to_py_object())
mtd.invoke(args~)
}
///|
pub suberror CallError {
MtdNotFound(String)
UnexpectedReturnType(String)
RuntimeError(@py.PyRuntimeError)
}
///|
pub fn[A : PyObjectInto] py_repr(sel : A) -> String raise CallError {
match (invoke_unary(sel, "__repr__") catch { e => raise RuntimeError(e) }) {
Some(PyString(repr)) => @py.PyString::to_string(repr)
Some(en) => raise UnexpectedReturnType(en.to_string())
None => raise MtdNotFound("__repr__")
}
}
///|
pub fn[A : PyObjectInto] py_str(sel : A) -> String raise CallError {
match (invoke_unary(sel, "__str__") catch { e => raise RuntimeError(e) }) {
Some(PyString(s)) => @py.PyString::to_string(s)
Some(en) => raise UnexpectedReturnType(en.to_string())
None => raise MtdNotFound("__str__")
}
}
///|
test "py_repr" {
assert_eq(py_repr(42), "42")
assert_eq(py_repr("hello"), "'hello'")
assert_eq(py_repr([1, 2, 3]), "[1, 2, 3]")
assert_eq(py_repr(TypedPyTuple2::new(1, 2)), "(1, 2)")
assert_eq(py_repr(TypedPyTuple2::new(1, "2")), "(1, '2')")
assert_eq(py_str("hello"), "hello")
assert_eq(py_str(3.14), "3.14")
assert_eq(py_str(1.0 / 2), "0.5")
inspect(invoke_binary(12, 42, "__add__"), content="Some(PyInteger(54))")
}