Skip to content

Commit c181a7c

Browse files
authored
Merge pull request #1424 from dralley/fix-float
Allow float() to be called without an argument
2 parents 3856e93 + 32b4a92 commit c181a7c

File tree

2 files changed

+48
-34
lines changed

2 files changed

+48
-34
lines changed

tests/snippets/floats.py

+2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@
8686
assert math.isinf(float('+Inf'))
8787
assert math.isinf(float('-Inf'))
8888

89+
assert float() == 0
90+
8991
assert float('+Inf') > 0
9092
assert float('-Inf') < 0
9193

vm/src/obj/objfloat.rs

+46-34
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,19 @@ fn inner_gt_int(value: f64, other_int: &BigInt) -> bool {
157157
#[pyimpl]
158158
#[allow(clippy::trivially_copy_pass_by_ref)]
159159
impl PyFloat {
160+
#[pymethod(name = "__new__")]
161+
fn float_new(
162+
cls: PyClassRef,
163+
arg: OptionalArg<PyObjectRef>,
164+
vm: &VirtualMachine,
165+
) -> PyResult<PyFloatRef> {
166+
let float_val = match arg {
167+
OptionalArg::Present(val) => to_float(vm, &val),
168+
OptionalArg::Missing => Ok(0f64),
169+
};
170+
PyFloat::from(float_val?).into_ref_with_type(vm, cls)
171+
}
172+
160173
#[pymethod(name = "__eq__")]
161174
fn eq(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
162175
let value = self.value;
@@ -316,40 +329,6 @@ impl PyFloat {
316329
)
317330
}
318331

319-
#[pymethod(name = "__new__")]
320-
fn float_new(cls: PyClassRef, arg: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyFloatRef> {
321-
let value = if objtype::isinstance(&arg, &vm.ctx.float_type()) {
322-
get_value(&arg)
323-
} else if objtype::isinstance(&arg, &vm.ctx.int_type()) {
324-
objint::get_float_value(&arg, vm)?
325-
} else if objtype::isinstance(&arg, &vm.ctx.str_type()) {
326-
match lexical::try_parse(objstr::get_value(&arg).trim()) {
327-
Ok(f) => f,
328-
Err(_) => {
329-
let arg_repr = vm.to_pystr(&arg)?;
330-
return Err(vm.new_value_error(format!(
331-
"could not convert string to float: '{}'",
332-
arg_repr
333-
)));
334-
}
335-
}
336-
} else if objtype::isinstance(&arg, &vm.ctx.bytes_type()) {
337-
match lexical::try_parse(objbytes::get_value(&arg).as_slice()) {
338-
Ok(f) => f,
339-
Err(_) => {
340-
let arg_repr = vm.to_pystr(&arg)?;
341-
return Err(vm.new_value_error(format!(
342-
"could not convert string to float: '{}'",
343-
arg_repr
344-
)));
345-
}
346-
}
347-
} else {
348-
return Err(vm.new_type_error(format!("can't convert {} to float", arg.class().name)));
349-
};
350-
PyFloat { value }.into_ref_with_type(vm, cls)
351-
}
352-
353332
#[pymethod(name = "__mod__")]
354333
fn mod_(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
355334
try_float(&other, vm)?.map_or_else(
@@ -574,6 +553,39 @@ impl PyFloat {
574553
}
575554
}
576555

556+
fn to_float(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<f64> {
557+
let value = if objtype::isinstance(&obj, &vm.ctx.float_type()) {
558+
get_value(&obj)
559+
} else if objtype::isinstance(&obj, &vm.ctx.int_type()) {
560+
objint::get_float_value(&obj, vm)?
561+
} else if objtype::isinstance(&obj, &vm.ctx.str_type()) {
562+
match lexical::try_parse(objstr::get_value(&obj).trim()) {
563+
Ok(f) => f,
564+
Err(_) => {
565+
let arg_repr = vm.to_pystr(obj)?;
566+
return Err(vm.new_value_error(format!(
567+
"could not convert string to float: '{}'",
568+
arg_repr
569+
)));
570+
}
571+
}
572+
} else if objtype::isinstance(&obj, &vm.ctx.bytes_type()) {
573+
match lexical::try_parse(objbytes::get_value(&obj).as_slice()) {
574+
Ok(f) => f,
575+
Err(_) => {
576+
let arg_repr = vm.to_pystr(obj)?;
577+
return Err(vm.new_value_error(format!(
578+
"could not convert string to float: '{}'",
579+
arg_repr
580+
)));
581+
}
582+
}
583+
} else {
584+
return Err(vm.new_type_error(format!("can't convert {} to float", obj.class().name)));
585+
};
586+
Ok(value)
587+
}
588+
577589
fn to_hex(value: f64) -> String {
578590
let (mantissa, exponent, sign) = value.integer_decode();
579591
let sign_fmt = if sign < 0 { "-" } else { "" };

0 commit comments

Comments
 (0)