forked from Rust-related/RustPython
non-int indexable base for int()
This commit is contained in:
@@ -280,7 +280,6 @@ class IntTestCases(unittest.TestCase):
|
||||
with self.assertRaises(TypeError):
|
||||
int('0', 5.0)
|
||||
|
||||
@unittest.skip("TODO: RUSTPYTHON")
|
||||
def test_int_base_indexable(self):
|
||||
class MyIndexable(object):
|
||||
def __init__(self, value):
|
||||
|
||||
@@ -659,12 +659,13 @@ struct IntOptions {
|
||||
#[pyarg(positional_only, optional = true)]
|
||||
val_options: OptionalArg<PyObjectRef>,
|
||||
#[pyarg(positional_or_keyword, optional = true)]
|
||||
base: OptionalArg<PyIntRef>,
|
||||
base: OptionalArg<PyObjectRef>,
|
||||
}
|
||||
|
||||
impl IntOptions {
|
||||
fn get_int_value(self, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
if let OptionalArg::Present(val) = self.val_options {
|
||||
// FIXME: unnessessary bigint clone/creation
|
||||
let base = if let OptionalArg::Present(base) = self.base {
|
||||
if !(objtype::isinstance(&val, &vm.ctx.str_type())
|
||||
|| objtype::isinstance(&val, &vm.ctx.bytes_type()))
|
||||
@@ -673,11 +674,17 @@ impl IntOptions {
|
||||
"int() can't convert non-string with explicit base".to_owned(),
|
||||
));
|
||||
}
|
||||
base
|
||||
let base = vm.to_index(&base).unwrap_or_else(|| {
|
||||
Err(vm.new_type_error(format!(
|
||||
"'{}' object cannot be interpreted as an integer missing string argument",
|
||||
base.class().name
|
||||
)))
|
||||
})?;
|
||||
base.as_bigint().clone()
|
||||
} else {
|
||||
PyInt::new(10).into_ref(vm)
|
||||
BigInt::from(10)
|
||||
};
|
||||
to_int(vm, &val, base.as_bigint())
|
||||
to_int(vm, &val, &base)
|
||||
} else if let OptionalArg::Present(_) = self.base {
|
||||
Err(vm.new_type_error("int() missing string argument".to_owned()))
|
||||
} else {
|
||||
|
||||
@@ -3,7 +3,6 @@ use super::objtype::PyClassRef;
|
||||
use crate::function::{OptionalArg, PyFuncArgs};
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryIntoRef,
|
||||
TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::{BigInt, ToBigInt};
|
||||
@@ -323,23 +322,12 @@ fn to_index_value(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Option<Big
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if let Some(val) = obj.payload::<PyInt>() {
|
||||
Ok(Some(val.as_bigint().clone()))
|
||||
} else {
|
||||
let cls = obj.class();
|
||||
if cls.has_attr("__index__") {
|
||||
let index_result = vm.call_method(obj, "__index__", vec![])?;
|
||||
if let Some(val) = index_result.payload::<PyInt>() {
|
||||
Ok(Some(val.as_bigint().clone()))
|
||||
} else {
|
||||
Err(vm.new_type_error("__index__ method returned non integer".to_owned()))
|
||||
}
|
||||
} else {
|
||||
Err(vm.new_type_error(
|
||||
"slice indices must be integers or None or have an __index__ method".to_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
let result = vm.to_index(obj).unwrap_or_else(|| {
|
||||
Err(vm.new_type_error(
|
||||
"slice indices must be integers or None or have an __index__ method".to_owned(),
|
||||
))
|
||||
})?;
|
||||
Ok(Some(result.as_bigint().clone()))
|
||||
}
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
|
||||
26
vm/src/vm.rs
26
vm/src/vm.rs
@@ -29,7 +29,7 @@ use crate::import;
|
||||
use crate::obj::objbool;
|
||||
use crate::obj::objcode::{PyCode, PyCodeRef};
|
||||
use crate::obj::objdict::PyDictRef;
|
||||
use crate::obj::objint::PyInt;
|
||||
use crate::obj::objint::{PyInt, PyIntRef};
|
||||
use crate::obj::objiter;
|
||||
use crate::obj::objlist::PyList;
|
||||
use crate::obj::objmodule::{self, PyModule};
|
||||
@@ -546,6 +546,30 @@ impl VirtualMachine {
|
||||
Ok(self.new_str(ascii))
|
||||
}
|
||||
|
||||
pub fn to_index(&self, obj: &PyObjectRef) -> Option<PyResult<PyIntRef>> {
|
||||
Some(
|
||||
if let Ok(val) = TryFromObject::try_from_object(self, obj.clone()) {
|
||||
Ok(val)
|
||||
} else {
|
||||
let cls = obj.class();
|
||||
if cls.has_attr("__index__") {
|
||||
self.call_method(obj, "__index__", vec![]).and_then(|r| {
|
||||
if let Ok(val) = TryFromObject::try_from_object(self, r) {
|
||||
Ok(val)
|
||||
} else {
|
||||
Err(self.new_type_error(format!(
|
||||
"__index__ returned non-int (type {})",
|
||||
cls.name
|
||||
)))
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn import(&self, module: &str, from_list: &[String], level: usize) -> PyResult {
|
||||
// if the import inputs seem weird, e.g a package import or something, rather than just
|
||||
// a straight `import ident`
|
||||
|
||||
Reference in New Issue
Block a user