forked from Rust-related/RustPython
Check operand types in bool or, and, xor to be PyInt (#5461)
* Added Tests for Bitwise or, and, xor type error * Sync binary operator order comment with actual implementation * Check operand types in bool or, and, xor to be PyInt PyNumber methods are expected to type check both arguments. Dispatch is not done by inverting parameter order for __r<op>__ (example __ror__) when calls are handled via PyNumberMethods
This commit is contained in:
@@ -32,3 +32,23 @@ assert_raises(ValueError, lambda: 1 << -1)
|
||||
|
||||
# Right shift raises value error on negative
|
||||
assert_raises(ValueError, lambda: 1 >> -1)
|
||||
|
||||
# Bitwise or, and, xor raises value error on incompatible types
|
||||
assert_raises(TypeError, lambda: "abc" | True)
|
||||
assert_raises(TypeError, lambda: "abc" & True)
|
||||
assert_raises(TypeError, lambda: "abc" ^ True)
|
||||
assert_raises(TypeError, lambda: True | "abc")
|
||||
assert_raises(TypeError, lambda: True & "abc")
|
||||
assert_raises(TypeError, lambda: True ^ "abc")
|
||||
assert_raises(TypeError, lambda: "abc" | 1.5)
|
||||
assert_raises(TypeError, lambda: "abc" & 1.5)
|
||||
assert_raises(TypeError, lambda: "abc" ^ 1.5)
|
||||
assert_raises(TypeError, lambda: 1.5 | "abc")
|
||||
assert_raises(TypeError, lambda: 1.5 & "abc")
|
||||
assert_raises(TypeError, lambda: 1.5 ^ "abc")
|
||||
assert_raises(TypeError, lambda: True | 1.5)
|
||||
assert_raises(TypeError, lambda: True & 1.5)
|
||||
assert_raises(TypeError, lambda: True ^ 1.5)
|
||||
assert_raises(TypeError, lambda: 1.5 | True)
|
||||
assert_raises(TypeError, lambda: 1.5 & True)
|
||||
assert_raises(TypeError, lambda: 1.5 ^ True)
|
||||
|
||||
@@ -127,8 +127,10 @@ impl PyBool {
|
||||
let lhs = get_value(&lhs);
|
||||
let rhs = get_value(&rhs);
|
||||
(lhs || rhs).to_pyobject(vm)
|
||||
} else if let Some(lhs) = lhs.payload::<PyInt>() {
|
||||
lhs.or(rhs, vm).to_pyobject(vm)
|
||||
} else {
|
||||
get_py_int(&lhs).or(rhs, vm).to_pyobject(vm)
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,8 +143,10 @@ impl PyBool {
|
||||
let lhs = get_value(&lhs);
|
||||
let rhs = get_value(&rhs);
|
||||
(lhs && rhs).to_pyobject(vm)
|
||||
} else if let Some(lhs) = lhs.payload::<PyInt>() {
|
||||
lhs.and(rhs, vm).to_pyobject(vm)
|
||||
} else {
|
||||
get_py_int(&lhs).and(rhs, vm).to_pyobject(vm)
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,8 +159,10 @@ impl PyBool {
|
||||
let lhs = get_value(&lhs);
|
||||
let rhs = get_value(&rhs);
|
||||
(lhs ^ rhs).to_pyobject(vm)
|
||||
} else if let Some(lhs) = lhs.payload::<PyInt>() {
|
||||
lhs.xor(rhs, vm).to_pyobject(vm)
|
||||
} else {
|
||||
get_py_int(&lhs).xor(rhs, vm).to_pyobject(vm)
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,7 +213,3 @@ pub(crate) fn init(context: &Context) {
|
||||
pub(crate) fn get_value(obj: &PyObject) -> bool {
|
||||
!obj.payload::<PyInt>().unwrap().as_bigint().is_zero()
|
||||
}
|
||||
|
||||
fn get_py_int(obj: &PyObject) -> &PyInt {
|
||||
obj.payload::<PyInt>().unwrap()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user