@@ -2,7 +2,7 @@ use pyo3::intern;
2
2
use pyo3:: prelude:: * ;
3
3
use pyo3:: types:: { PyDict , PySet , PyType } ;
4
4
5
- use crate :: build_tools:: SchemaDict ;
5
+ use crate :: build_tools:: { py_err , SchemaDict } ;
6
6
use crate :: errors:: { ErrorKind , ValError , ValResult } ;
7
7
use crate :: input:: { Input , JsonType } ;
8
8
use crate :: recursion_guard:: RecursionGuard ;
@@ -12,7 +12,7 @@ use super::{BuildContext, BuildValidator, CombinedValidator, Extra, Validator};
12
12
13
13
#[ derive( Debug , Clone ) ]
14
14
pub struct IsInstanceValidator {
15
- class : Py < PyType > ,
15
+ class : PyObject ,
16
16
json_types : u8 ,
17
17
json_function : Option < PyObject > ,
18
18
class_repr : String ,
@@ -28,8 +28,23 @@ impl BuildValidator for IsInstanceValidator {
28
28
_build_context : & mut BuildContext ,
29
29
) -> PyResult < CombinedValidator > {
30
30
let py = schema. py ( ) ;
31
- let class: & PyType = schema. get_as_req ( intern ! ( py, "cls" ) ) ?;
32
- let class_repr = class. name ( ) ?. to_string ( ) ;
31
+ let cls_key = intern ! ( py, "cls" ) ;
32
+ let class: & PyAny = schema. get_as_req ( cls_key) ?;
33
+
34
+ // test that class works with isinstance to avoid errors at call time, reuse cls_key since it doesn't
35
+ // matter what object is being checked
36
+ let test_value: & PyAny = cls_key. as_ref ( ) ;
37
+ if test_value. input_is_instance ( class, 0 ) . is_err ( ) {
38
+ return py_err ! ( "'cls' must be valid as the first argument to 'isinstance'" ) ;
39
+ }
40
+
41
+ let class_repr = match schema. get_as ( intern ! ( py, "cls_repr" ) ) ? {
42
+ Some ( s) => s,
43
+ None => match class. extract :: < & PyType > ( ) {
44
+ Ok ( t) => t. name ( ) ?. to_string ( ) ,
45
+ Err ( _) => class. repr ( ) ?. extract ( ) ?,
46
+ } ,
47
+ } ;
33
48
let name = format ! ( "{}[{}]" , Self :: EXPECTED_TYPE , class_repr) ;
34
49
let json_types = match schema. get_as :: < & PySet > ( intern ! ( py, "json_types" ) ) ? {
35
50
Some ( s) => JsonType :: combine ( s) ?,
@@ -55,7 +70,7 @@ impl Validator for IsInstanceValidator {
55
70
_slots : & ' data [ CombinedValidator ] ,
56
71
_recursion_guard : & ' s mut RecursionGuard ,
57
72
) -> ValResult < ' data , PyObject > {
58
- match input. is_instance ( self . class . as_ref ( py) , self . json_types ) ? {
73
+ match input. input_is_instance ( self . class . as_ref ( py) , self . json_types ) ? {
59
74
true => {
60
75
if input. get_type ( ) . is_json ( ) {
61
76
if let Some ( ref json_function) = self . json_function {
0 commit comments