diff --git a/src/validators/is_instance.rs b/src/validators/is_instance.rs index 9d22ad24a..cdcce4b54 100644 --- a/src/validators/is_instance.rs +++ b/src/validators/is_instance.rs @@ -9,7 +9,6 @@ use crate::input::Input; use crate::recursion_guard::RecursionGuard; use crate::tools::SchemaDict; -use super::InputType; use super::{BuildValidator, CombinedValidator, Definitions, DefinitionsBuilder, Extra, Validator}; #[derive(Debug, Clone)] @@ -60,27 +59,26 @@ impl Validator for IsInstanceValidator { &'s self, py: Python<'data>, input: &'data impl Input<'data>, - extra: &Extra, + _extra: &Extra, _definitions: &'data Definitions, _recursion_guard: &'s mut RecursionGuard, ) -> ValResult<'data, PyObject> { - match extra.mode { - InputType::Json => Err(ValError::InternalErr(PyNotImplementedError::new_err( - "Cannot check isinstance when validating from json,\ + if !input.is_python() { + return Err(ValError::InternalErr(PyNotImplementedError::new_err( + "Cannot check isinstance when validating from json, \ use a JsonOrPython validator instead.", - ))), - InputType::Python => { - let ob = input.to_object(py); - match ob.as_ref(py).is_instance(self.class.as_ref(py))? { - true => Ok(ob), - false => Err(ValError::new( - ErrorType::IsInstanceOf { - class: self.class_repr.clone(), - }, - input, - )), - } - } + ))); + } + + let ob = input.to_object(py); + match ob.as_ref(py).is_instance(self.class.as_ref(py))? { + true => Ok(ob), + false => Err(ValError::new( + ErrorType::IsInstanceOf { + class: self.class_repr.clone(), + }, + input, + )), } } diff --git a/tests/validators/test_is_instance.py b/tests/validators/test_is_instance.py index a77c415ba..7a5351554 100644 --- a/tests/validators/test_is_instance.py +++ b/tests/validators/test_is_instance.py @@ -164,3 +164,28 @@ def test_class_repr(): assert v.validate_python(1) == 1 with pytest.raises(ValidationError, match=r'Input should be an instance of Foobar \[type=is_instance_of,'): v.validate_python('1') + + +def test_is_instance_json_type_before_validator(): + # See https://github.com/pydantic/pydantic/issues/6573 - when using a + # "before" validator to coerce JSON to valid Python input it should be + # possible to use isinstance validation. This gives a way for things + # such as type to have a valid input from JSON. + + schema = core_schema.is_instance_schema(type) + v = SchemaValidator(schema) + + with pytest.raises( + NotImplementedError, + match='Cannot check isinstance when validating from json, use a JsonOrPython validator instead.', + ): + v.validate_json('null') + + # now wrap in a before validator + def set_type_to_int(input: None) -> type: + return int + + schema = core_schema.no_info_before_validator_function(set_type_to_int, schema) + v = SchemaValidator(schema) + + assert v.validate_json('null') == int