diff --git a/src/input/input_python.rs b/src/input/input_python.rs index 1eaa69415..b07405af2 100644 --- a/src/input/input_python.rs +++ b/src/input/input_python.rs @@ -291,6 +291,15 @@ impl<'py> Input<'py> for Bound<'py, PyAny> { return Ok(ValidationMatch::exact(EitherFloat::Py(float.clone()))); } + if self.is_instance_of::() { + if strict { + return Err(ValError::new(ErrorTypeDefaults::FloatType, self)); + } + let real = self.getattr(intern!(self.py(), "real")).unwrap(); + let float = real.extract::().unwrap(); + return Ok(ValidationMatch::lax(EitherFloat::F64(float))); + } + if !strict { if let Some(s) = maybe_as_string(self, ErrorTypeDefaults::FloatParsing)? { // checking for bytes and string is fast, so do this before isinstance(float) diff --git a/tests/validators/test_float.py b/tests/validators/test_float.py index c397f453c..4da61941b 100644 --- a/tests/validators/test_float.py +++ b/tests/validators/test_float.py @@ -29,6 +29,10 @@ (False, 0), ('wrong', Err('Input should be a valid number, unable to parse string as a number [type=float_parsing')), ([1, 2], Err('Input should be a valid number [type=float_type, input_value=[1, 2], input_type=list]')), + (1 + 0j, 1.0), + (2.5 + 0j, 2.5), + (3 + 1j, 3.0), + (1j, 0), ], ) def test_float(py_and_json: PyAndJson, input_value, expected): @@ -37,7 +41,10 @@ def test_float(py_and_json: PyAndJson, input_value, expected): with pytest.raises(ValidationError, match=re.escape(expected.message)): v.validate_test(input_value) else: - output = v.validate_test(input_value) + if isinstance(input_value, complex): + output = v.validate_python(input_value) + else: + output = v.validate_test(input_value) assert output == expected assert isinstance(output, float) @@ -52,6 +59,10 @@ def test_float(py_and_json: PyAndJson, input_value, expected): (42.5, 42.5), ('42', Err("Input should be a valid number [type=float_type, input_value='42', input_type=str]")), (True, Err('Input should be a valid number [type=float_type, input_value=True, input_type=bool]')), + (1 + 0j, Err('Input should be a valid number [type=float_type, input_value=(1+0j), input_type=complex]')), + (2.5 + 0j, Err('Input should be a valid number [type=float_type, input_value=(2.5+0j), input_type=complex]')), + (3 + 1j, Err('Input should be a valid number [type=float_type, input_value=(3+1j), input_type=complex]')), + (1j, Err('Input should be a valid number [type=float_type, input_value=1j, input_type=complex]')), ], ids=repr, ) @@ -59,7 +70,10 @@ def test_float_strict(py_and_json: PyAndJson, input_value, expected): v = py_and_json({'type': 'float', 'strict': True}) if isinstance(expected, Err): with pytest.raises(ValidationError, match=re.escape(expected.message)): - v.validate_test(input_value) + if isinstance(input_value, complex): + v.validate_python(input_value) + else: + v.validate_test(input_value) else: output = v.validate_test(input_value) assert output == expected