Merge pull request #1424 from dralley/fix-float

Allow float() to be called without an argument
This commit is contained in:
Noah
2019-09-26 23:10:38 -05:00
committed by GitHub
2 changed files with 48 additions and 34 deletions

View File

@@ -86,6 +86,8 @@ assert math.isinf(float('Inf'))
assert math.isinf(float('+Inf'))
assert math.isinf(float('-Inf'))
assert float() == 0
assert float('+Inf') > 0
assert float('-Inf') < 0

View File

@@ -157,6 +157,19 @@ fn inner_gt_int(value: f64, other_int: &BigInt) -> bool {
#[pyimpl]
#[allow(clippy::trivially_copy_pass_by_ref)]
impl PyFloat {
#[pymethod(name = "__new__")]
fn float_new(
cls: PyClassRef,
arg: OptionalArg<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult<PyFloatRef> {
let float_val = match arg {
OptionalArg::Present(val) => to_float(vm, &val),
OptionalArg::Missing => Ok(0f64),
};
PyFloat::from(float_val?).into_ref_with_type(vm, cls)
}
#[pymethod(name = "__eq__")]
fn eq(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
let value = self.value;
@@ -316,40 +329,6 @@ impl PyFloat {
)
}
#[pymethod(name = "__new__")]
fn float_new(cls: PyClassRef, arg: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyFloatRef> {
let value = if objtype::isinstance(&arg, &vm.ctx.float_type()) {
get_value(&arg)
} else if objtype::isinstance(&arg, &vm.ctx.int_type()) {
objint::get_float_value(&arg, vm)?
} else if objtype::isinstance(&arg, &vm.ctx.str_type()) {
match lexical::try_parse(objstr::get_value(&arg).trim()) {
Ok(f) => f,
Err(_) => {
let arg_repr = vm.to_pystr(&arg)?;
return Err(vm.new_value_error(format!(
"could not convert string to float: '{}'",
arg_repr
)));
}
}
} else if objtype::isinstance(&arg, &vm.ctx.bytes_type()) {
match lexical::try_parse(objbytes::get_value(&arg).as_slice()) {
Ok(f) => f,
Err(_) => {
let arg_repr = vm.to_pystr(&arg)?;
return Err(vm.new_value_error(format!(
"could not convert string to float: '{}'",
arg_repr
)));
}
}
} else {
return Err(vm.new_type_error(format!("can't convert {} to float", arg.class().name)));
};
PyFloat { value }.into_ref_with_type(vm, cls)
}
#[pymethod(name = "__mod__")]
fn mod_(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
try_float(&other, vm)?.map_or_else(
@@ -574,6 +553,39 @@ impl PyFloat {
}
}
fn to_float(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<f64> {
let value = if objtype::isinstance(&obj, &vm.ctx.float_type()) {
get_value(&obj)
} else if objtype::isinstance(&obj, &vm.ctx.int_type()) {
objint::get_float_value(&obj, vm)?
} else if objtype::isinstance(&obj, &vm.ctx.str_type()) {
match lexical::try_parse(objstr::get_value(&obj).trim()) {
Ok(f) => f,
Err(_) => {
let arg_repr = vm.to_pystr(obj)?;
return Err(vm.new_value_error(format!(
"could not convert string to float: '{}'",
arg_repr
)));
}
}
} else if objtype::isinstance(&obj, &vm.ctx.bytes_type()) {
match lexical::try_parse(objbytes::get_value(&obj).as_slice()) {
Ok(f) => f,
Err(_) => {
let arg_repr = vm.to_pystr(obj)?;
return Err(vm.new_value_error(format!(
"could not convert string to float: '{}'",
arg_repr
)));
}
}
} else {
return Err(vm.new_type_error(format!("can't convert {} to float", obj.class().name)));
};
Ok(value)
}
fn to_hex(value: f64) -> String {
let (mantissa, exponent, sign) = value.integer_decode();
let sign_fmt = if sign < 0 { "-" } else { "" };